Adding a variable to all views in grails - grails

I am trying to set a variable for the current user (a POJO) in all views so I can get things like the user name and check their role on every view (including the default layout). How can I setup something (e.g. currentUser) in grails so that it is accessible in every grails view like so:
<div>${currentUser.name}</div>
or like this:
<g:if test="${currentUser.admin}">ADMIN</g:if>

You want to use a grails filter. Using a filter, you can specify which controllers and methods (using wild cards) you want to intercept using before/after and afterView methods.
This makes it easy to stuff a new variable into the model so it's available in a view. Here's an example that uses the acegi plugin authenticateService:
class SecurityFilters {
def authenticateService
def filters = {
all(controller:'*', action:'*') {
after = { model ->
def principal = authenticateService.principal()
if (principal != null && principal != 'anonymousUser') {
model?.loggedInUser = principal?.domainClass
log.debug("SecurityFilter: adding current user to model = $model")
} else {
log.debug("SecurityFilter: anonymous user, model = $model")
}
}
}
}
}

You can use the session scope to store the variable. Your calls would change to:
<div>${session.currentUser.name}</div>
and
<g:if test="${session.currentUser.admin}">ADMIN</g:if>
And you would set the variable like so in a controller:
session.currentUser = XXXXX

Related

GRAILS: findALL() vs FindBy---(params.id)

Greeting everyone,
I am trying to pass a parameters from a URL to a findAll() method.
LINE3 I use findAll() to define mouse.
LINE2 def house will bring in the parameter DELAWARE when I go to the page: http://localhost:8080/TestApp/home/county/DELAWARE
House will only show one instance instead of a list.. is there anyway to pass the url instead of ["DELAWARE"]? (please see line 3) thanks :)
def county() {
def house = Home.findByCounty(params.id) //sends only user related address to view
def mouse = Home.findAll("from Home h where h.county= ?", ["DELAWARE"]);
if (!house) {
response.sendError(404)
} else {
[house:house, mouse:mouse ]
}
}
Working Code +1 #Danilo
def county() {
def house = Home.findAllByCounty (params.id) //sends only county specified thru URL e.g. http://localhost:8080/TestAPP/home/county/DELAWARE
if (!house) {
response.sendError(404)
} else {
[house:house ]
}
}
findBy* will return at most one row, if you want to get all rows use findAllBy*
In order to understand how the URL will be used by Grails you have to have a look at conf/UrlMappings.groovy. You may find something like this:
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
}
}
this means that when you call TestApp/home/county/DELAWARE what Grails is trying to do is use the home controller (HomeController), invoking the county method (def county(){...}) and passing DELAWARE as id.
This should work correctly if inside county method of the HomeController you have:
def filteredInstances = Home.findAllByCounty(params.id)

grails Spring security custom permission in controller

I want to create a custom permission handler using grails spring security plugin.
Imagine I have a User class and a company class with a many-to-many association.
I want only allow users to call a method called "delete company" when they belong to the company. Example:
class User {
static hasMany= [companies:Company]
static belongsTo = [Company]
}
class Company {
static hasMany = [users:User]
}
the controller action looks like to following:
def deleteCompany(Long id) {
}
I only want to allow users to call the method that are part of the company. So when
assert Company.get(id}.users.find { it == currentUser }
This is just a simplified example. The actual structure is much more complex. That's why I want to use the power of spring security for this.
I already played around with spring security ACL but it seems that I can only use custom permissions in services but not in controllers
You could use beforeInterceptor in your controller:
def springSecurityService
def beforeInterceptor=[action:this.&auth]
private auth = {
def toBeCheckedId=params.id
if(toBeCheckedId
&& Company.get(toBeCheckedId}.users.find { it == springSecurityService.currentUser }){
redirect action:someHandlingAction
return false
}
}
}

How to create a generic field like version in Grails?

I am creating a restful service from Grails and would like to add a user field on every table which on insert or on update automatically changed to the corresponding user making the change.
Is there any way to create a variable like version or dateCreated which are automatically bound to each domain where defined and added automatically updated on creation or update?
1. Define an abstract domain class, put your common fields on it (on src/groovy)
2. Extend it by each domain object that needs the common fields
So your abstract domain class will look like this (also note how the updateByUser and createdByUser are automatically determined):
abstract class AbstractDomain {
transient securityService
User createdByUser;
User updatedByUser;
def beforeInsert() {
if(null != securityService) {
User currentUser = securityService.getCurrentUser()
if(null != currentUser){
this.createdByUser = currentUser
}
}
}
def beforeUpdate() {
if(null != securityService) {
User currentUser = securityService.getCurrentUser()
if(null != currentUser){
this.updatedByUser = currentUser
}
}
}
}

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...

How do I get Shiro's annotations to work in Grails?

I'm trying to apply annotation-based security to my Grails app.
Peter says here that we should be using Shiro's annotations instead of the quasi-deprecated grails-shiro plugin annotations.
How does one get that working?
I'm finding the grails-shiro plugin strays from how Shiro does things, what with the Realm-converting and all. Has anyone tried implementing Shiro directly rather than using the grails plugin? Any success?
Thanks,
Graham.
G'day I have taken over the Grails-Shiro plugin project. I'm currently re-writing the functional tests and can confirm that the shiro annotations do work, with a couple of caveats:
You can use them in controllers on method actions in grails 2.x
You can use them on Service methods
They don't currently work on service classes (I'm investigating this)
e.g. this works on a service
class SecuredMethodsService {
def methodOne() {
return 'one'
}
#RequiresGuest
def methodTwo() {
return 'two'
}
#RequiresUser
def methodThree() {
return 'three'
}
#RequiresAuthentication
def methodFour() {
return 'four'
}
#RequiresRoles('User')
def methodFive() {
return 'five'
}
#RequiresPermissions("book:view")
def methodSix() {
return 'six'
}
}
or in a controller on an action method like this:
#RequiresAuthentication
def unrestricted() {
render(view: 'simple', model: [msg: "secure action"])
}
When using annotations you may need to add an "afterView" filter to catch the AuthorizationException thrown by the annotation e.g.
class ShiroSecurityFilters {
def filters = {
all(uri: "/**") {
before = {
// Ignore direct views (e.g. the default main index page).
if (!controllerName) return true
// Access control by convention.
accessControl()
}
afterView = { e ->
while (e && !(e instanceof AuthorizationException)) {
e = e.cause
}
if (e instanceof AuthorizationException) {
if (e instanceof UnauthenticatedException) {
// User is not authenticated, so redirect to the login page.
flash.message = "You need to be logged in to continue."
redirect(
controller: 'auth',
action: 'login',
params: [targetUri: request.forwardURI - request.contextPath])
} else {
redirect(controller: 'auth', action: 'unauthorized')
}
}
}
}
}
}
I hope that helps. A new version of the plugin should be released RSN.
Cheers,
Peter.
Since nobody is anwering...
I don't know how you get the annotations to work, but I've used shiro in several Grails projects and didn't miss them... So why do you need them?
When you need to permission explicit roles, you can just create some ShiroRoles and assign star-permissions to them: 'book:*' allows a role to execute all actions on the book controller. 'book:list,show' allows a role to only list or show books.
When you need implicit permissions, use a filter. So if you want to give someone access if she is (for instance) the boss of someone, just fetch the object on which you want to decide in a filter and make a decision.
When you need switches in you gsp-code (e.g. show this only if it's an admin), use the shiro tags. Just unzip the shiro plugin and look for the taglibrary. It is well documented.
HTH

Resources