How to restrict user from accessing a particular action of a controller? - grails

def filters = {
loginCheck(controller:'*', action:'*') {
before = {
if(!session.user && !session.merchants)
{
redirect(action:'login')
return false
}
}}
That was my filter for login security. And below is interceptor in action for restricting user from search action. But both are not working. Can any one tell what the mistake is?
def beforeInterceptor = [action:this.&checkUser,Only:'search']
def scaffold = true
def checkUser()
{
if (session.user)
{
redirect(action:"search")
}
if(session.merchants)
{
redirect(action:"toIndex")
flash.message="You are not valid user for this action"
return false
}
}

There's a really nice shorthand that you can apply directly to actions (if you're not using filters):
#Secured(['ROLE_USER'])
def search = {
}
You can give every user ROLE_USER and simply require that role.

actually you filter should work as it is set for every controller and every action.
here is the grails example from the reference:
class SecurityFilters {
def filters = {
loginCheck(controller:'*', action:'*') {
before = {
if(!session.user && !actionName.equals('login')) {
redirect(action:'login')
return false
}
}
}
}
}
I worked with this one and it worked for me.
What I'm not sure is about the session.merchants in your code.
What is this ?
Did you follow this:
To create a filter create a class that
ends with the convention Filters in
the grails-app/conf directory.
Edit:
If you use spring security you don't need to add a filter or interceptor.
check the user guide: http://burtbeckwith.github.com/grails-spring-security-core/docs/manual/index.html
you can configure it with url mappings or annotations.
ex.
grails.plugins.springsecurity.controllerAnnotations.staticRules = [
'/js/admin/**': ['ROLE_ADMIN'],
'/someplugin/**': ['ROLE_ADMIN']
]
EDIT 2:
To get the logged in user use:
def authenticateService
...
def action{
def user = authenticateService.principal()
def username = user?.getUsername()
...

Related

Accessing specific controller in grails shiro plugin

I have a grails application in which I am using shiro plugin to add security. I do not give access to any of the urls without login to any user. All goes fine. Now I want to find whether there is any way to allow access to some of the urls without login ? Some links should be working without login.
that's easy. If you've a standard shiro setup, you'll find a ShiroSecurityFilters.groovy in your projects conf-folder which looks something like this:
class SecurityFilters {
def filters = {
all(uri: "/**") {
before = {
// Ignore direct views (e.g. the default main index page).
if (!controllerName) return true
// Access control by convention.
accessControl()
}
}
}
}
just replace it with something like this:
class SecurityFilters {
def filters = {
all(uri: "/**") {
before = {
// Ignore direct views (e.g. the default main index page).
if (!controllerName) return true
// Access control by convention.
if ((controllerName+':'+actionName) in ['book:view', 'book:list']) {
return true
} else {
accessControl()
}
}
}
}
}
This will make the two actions list and view of the bookController accessible to everyone.
Hope that helps...

Grails - run check after logging in but before accessing the controller

I want to show a screen the first time a user logs in. Is there a best practice for where to run the check of whether or not the user has logged in before? I'm using the Spring Security Core plugin.
There's nothing built in to Spring Security to do this. I'm doing something similar, but it is based on whether the user has accepted a license agreement or not. Here's sample filter code that may do what you want. It is untested:
def filters = {
neverLoggedIn(controller: "login", invert: true) {
before = {
if (springSecurityService.isLoggedIn()) {
def authenticatedUser = getLoggedInUserCode()
if (!authenticatedUser.hasLoggedInBefore) {
redirect controller: "someFirstLoginController", action: "index"
return false
}
}
}
after = { Map model -> }
afterView = { Exception e -> }
}
}

How to redirect to external url using filters when controller does not exist in current app

I have the following filter that in app1 that is supposed to redirect to an external app (app2).
class MyFilters {
def userService
def springSecurityService
def filters = {
all(controller: '*', action: '*') {
before = {
String userAgent = request.getHeader('User-Agent')
int buildVersion = 0
// Match "app-/{version}" where {version} is the build number
def matcher = userAgent =~ "(?i)app(?:-\\w+)?\\/(\\d+)"
if (matcher.getCount() > 0)
{
buildVersion = Integer.parseInt(matcher[0][1])
log.info("User agent is from a mobile with build version = " + buildVersion)
log.info("User agent = " + userAgent)
String redirectUrl = "https://anotherdomain.com"
if (buildVersion > 12)
{
if (request.queryString != null)
{
log.info("Redirecting request to anotherdomain with query string")
redirect(url:"${redirectUrl}${request.forwardURI}?${request.queryString}",params:params)
}
return false
}
}
}
after = { model ->
if (model) {
model['currentUser'] = userService.currentUser
}
}
afterView = {
}
}
}
}
A problem occurs when the request to app1 contains a URI where the controller name does not exist in app1 (But does in app2 where I want to redirect to).
How can I redirect requests to app2 with same URI appended? (regardless if they exist in app1 or not).
I suspect filter's are not the correct solution as it will never enter them if the controller does not exist in app.
Ideally, I need a solution that can be implmented via code and not apache.
Thanks
Define a general purpose redirect controller like this:
class RedirectController {
def index() {
redirect(url: "https://anotherdomain.com")
}
}
In UrlMappings, point 404 to this controller:
class UrlMappings {
static mappings = {
......
"404"(controller:'redirect', action:'index')
......
}
}
Actually you can define all the redirect relationships here instead of deal with filter.
You can set the scope of a filter by URI as well as by controller name, try:
def filters = {
all(uri:'/**') {

Filtering filtered data

I'm new to grails and MVC so please bear with me.
I have some links on my GSP that do some static filtering. For instance, the example below returns only
those Request domain class instances with status Open. But I also want to be able to do some dynamic filtering on the same model (results in the code bellow).
Use case would be something like this: User sees all Request domain class instances in the table. He clicks on the link Open requests and gets only those Request instances that have status property with value Open. Than he sets dateFrom and dateTo using date picker control and clicks on the Filter button which calls the method/action that further filters data from the table. So it should return only those request that are opened and that are created within the specified period.
def openedRequests = {
def contact = Contact?.findByUser(springSecurityService.currentUser)
def productlines = contact.productlines()
def requestCriteria = Request.createCriteria()
def results = requestCriteria.list {
eq("status", "Open")
and {
'in'("productline",productlines)
}
}
render(view:'supportList', model:[requestInstanceList:results, requestInstanceTotal: results.totalCount])
}
EDIT
On my GSP I have few links that call controller actions which perform some domain class instances filtering. For example I have OpenedRequests, ClosedRequests, NewRequests. But I also have some textboxes, comboboxes, datePicker controls for additional filtering. I call the filterRequests action with a button.
def filterRequests = {
def contact = Contact?.findByUser(springSecurityService.currentUser)
def productlines = contact.productlines()
def requestCriteria = Request.createCriteria()
def results = requestCriteria.list {
if(params.fDateFrom && params.fDateTo){
def dateFrom = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateFrom_value)
def dateTo = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateTo_value)
between("dateCreated",dateFrom,dateTo)
}
if(params?.fStatus){
eq("status",params.fStatus)
}
if(params?.fCompany){
eq("company", params.fCompany)
}
and {'in'("productline",productlines)
}
if(params.sort != null && params.order != null){
order(params.sort, params.order)
}
}
render(view:'supportList', model:[requestInstanceList:results, requestInstanceTotal: results.totalCount])
}
I want to be able to filter Request instances with some of mentioned links and than if I set up some additional filters, for example dateFrom i dateTo with datePicker. I want those filters to be aware of previous filtering with link if there were any. What is the right way to do this?
You can use DetachedCriterias which where introduced with Grails 2.0.
A DetachedCriteria is independed from any session and can be reused easily:
def openRequests = new DetachedCriteria(Request).build {
eq("status", "Open")
and {
'in'("productline",productlines)
}
}
Then upon your next sub-filter request you can reuse the DetachedCriteria and perform a sub-query on it, like:
def results = openRequests.findByStartDateBetweenAndEndDateBetween(dateFrom, dateTo, dateFrom, dateTo)
Of course you have to remember somehow what the original query was (session, request param), to use the correct criteria as a basis for the sub-query.
(Disclaimer: I haven't yet tried detached criterias myself)
David suggested that I use Detached Criteria but I am using Grails 1.3.7 for my app. So, at the moment this isn't an option. I also thought of using database views and stored procedures but I wasn't sure how that will work with Grails (but that is something that I will definitely have to explore) and I wanted some results fast so I did something not very DRY. When I filter table with one of the mentioned links I save the name of the link/action in session and in filterRequest action (that does additional filtering) I check the session to see if there has been any previous 'link filtering' and if it were I apply those filters on the table with criteria, and after that I apply the filters that were manualy entered. I don't like it but that's all I came up with with my limited understanding of Grails. Below is my filterRequest action:
def filterRequests = {
def contact = Contact?.findByUser(springSecurityService.currentUser)
def productlines = contact.productlines()
def requestCriteria = Request.createCriteria()
def results = requestCriteria.list {
if(session.filter == "newRequests"){
and{
isNull("acceptedBy")
ne("status", "Closed")
}
}
if(session.filter == "openRequests"){
and{
ne("status",'Closed')
}
}
if(session.filter == "closedRequests"){
and{
eq("status", "Closed")
}
}
if(session.filter == "myRequests"){
and{
eq("acceptedBy", contact.realname)
}
}
if(params.fDateFrom && params.fDateTo){
def dateFrom = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateFrom_value)
def dateTo = new SimpleDateFormat("dd.MM.yyyy").parse(params.fDateTo_value)
and{
between("dateCreated",dateFrom,dateTo)
}
}
if(params?.fAcceptedBy){
and{
eq("acceptedBy", params.fAcceptedBy)
}
}
if(params?.fStartedBy){
and{
eq("startedBy", params.fStartedBy)
}
}
if(params?.fCompany){
and{
ilike("company", "%" + params.fCompany +"%")
}
}
and {'in'("productline",productlines)
}
if(params.sort != null && params.order != null){
order(params.sort, params.order)
}
}
}

Grails and Spring Security: How do I get the authenticated user from within a controller?

I recently moved from the JSecurity plugin to Spring Security. How do I get the authenticated user from within my controllers?
It's not currently documented, but in the plugin installation file, there are 3 methods that it adds to every controller so that you don't actually have to inject the authenticationService:
private void addControllerMethods(MetaClass mc) {
mc.getAuthUserDomain = {
def principal = SCH.context?.authentication?.principal
if (principal != null && principal != 'anonymousUser') {
return principal?.domainClass
}
return null
}
mc.getPrincipalInfo = {
return SCH.context?.authentication?.principal
}
mc.isUserLogon = {
def principal = SCH.context?.authentication?.principal
return principal != null && principal != 'anonymousUser'
}
}
This means that you can just call
principalInfo
To get the principal object. It also has "isUserLogin" to see if the user is logged and "authUserDomain" to get the actual domain class instance (the Person/User) associated with the principal of the logged in user.
The following code is from the Spring Security Core Plugin (Version: 1.1.2) - Reference Documentation - Section 6.2
grails.plugins.springsecurity.SpringSecurityService provides security utility functions. It is a regular Grails service, so you use dependency injection to inject it into a controller, service, taglib, and so on:
class SomeController {
def springSecurityService
def someAction = {
def user = springSecurityService.currentUser
…
}
}
I'm using 0.5.1 and the following works for me:
class EventController {
def authenticateService
def list = {
def user = authenticateService.principal()
def username = user?.getUsername()
.....
.....
}
}
Nowadays, I think the way to do it is:
def user = getAuthenticatedUser()
You can get current User by this way also
class AnyController {
def springSecurityService
def someAction = {
def user = User.get(springSecurityService.principal.id)
}
}
Use this code:
if (springSecurityService.isLoggedIn()){
println "Logged In"
}

Resources