Grails - passing domain classes between controllers - grails

In my Grails application, I have created a User class. In one controller, I query the database to confirm that the information a user has given is valid. Then, I would like to pass that User object to another controller to do some more processing on it. Is this possible? Thanks!

For your question on passing objects between controllers, if you are using a redirect or a forward you can add objects in the param map:
redirect(action: "actionName", user: userInstance)
or
forward(action: "actionName", user: userInstance)
Another solution would be to store the user in the flash object (a temporary storage map cleared after the next request) or session:
flash.user = userInstance
or
session.user = userInstance
But in your case, as stated by tim_yates, you should create a service to handle the User entity.
To do so execute the command:
create-service com.package.user
Then add all the processing you are doing on a User in the newly created class and inject the User service in your controller like this:
def controller{
def userService
def action(){
userService.validate(...)
}
}

Essentaily what #tim_yates was getting at was the logic for all of your controllers should be in services. Then any action in any controller can execute that logic without redirecting/forwarding a request. This also is the way it should be due to the transactional nature of services.

Related

Jhipster, prevent user to update entities created by other users

I have been implementing Jhipster at my work and loving it. I was asked to implement a security validation that one user should not be allowed to edit the entity created by other user. For this I need two things:
First, in all entities, add a ManytoOne relation with User entity.
In Backend put a validation in controller while updating the entity to check if current logged in user is same as what is stored in DB. In front end also same logic to show/hide edit button.
I have done a POC for this and it works but is little ugly, check the code:
public ResponseEntity<Entry> updateEntry(#RequestBody Entry entry) throws URISyntaxException {
log.debug("REST request to update Entry : {}", entry);
if (entry.getId() == null) {
throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
}
//here is my logic
Optional<Entry> entry_db = entryRepository.findOneWithEagerRelationships(entry.getId());
if(!entry_db.get().getUser().getId().equals(userService.getUserWithAuthorities().get().getId())) {
//throw someexception
}
//
Entry result = entryRepository.save(entry);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, entry.getId().toString()))
.body(result);
}
Is there any better or OOTB way of doing this??? may be something in spring security i am not aware of??
Thanks for help!!
This is a job for Spring Security Expression-Based Access Control, in particular you could annotate your method with #PreFilter and a custom PermissionEvaluator you would implement with similar logic as in your POC. The PermissionEvaluator could be generic and applied to several entity types if you define an Owned interface that models the ownership with a method like User getOwner() and that all your entity classes would implement.
See https://docs.spring.io/spring-security/site/docs/current/reference/html5/#el-access
The annotated method should be in a service rather than in a resource controller.
Also, UserService alone will not help you in finding the current authenticated user, you should use JHipster's SecurityUtils first and then ÙserService if you need more data about it.

Grails Session scope for service not working as expected

I'm making a web app that stores reports of various types as domain objects, so I have a domain object HeadOfHousehold which contains name data, and references to other domain objects such as the reports, addresses, and any dependants. I am trying to build a list of recently viewed/created HeadOfHousehold objects. After multiple Google searches, and scouring the manual, it appeared that a service would be an appropriate solution. So I created ClientListService:
#Transactional
class ClientListService {
static scope = "session"
String message // right now I'll be happy to just see the same message across
// pages I can add a list and manipulate it later.
}
I thought I could then reference it in my various controllers, and it would persist Something like this:
def clientListService
def index(){
hasSearched = false
clientListService = new ClientListService(message: "Hello")
[errorMessage: params.errorMessage, clients:clientListService]
}
Which should be available in a later controller:
class HeadOfHouseHoldController {
def clientListService
def index() {
[customer: HeadOfHousehold.get(params.id), clients: clientListService]
}//...
However when I try to get the message, it appears as if the object is null.
From my index.gsp:
***************${clients?.message}********************
So I don't know if I am not defining session properly (I'm not doing anything special to do so), if I'm misunderstanding how the session scope works, or something else. I do see the proper message on the original page which has defined the object, however I don't see it on any subsequent pages.
Also, I'm not sure if this is the proper way to go about this; right now all I really need is the list of HeadOfHouseholds that I would need (so I can add to the list from other pages), however I can see possibly adding other logic and items into such a class.
I think you understood the session scope correctly. Each Spring bean with a session scope is bound to the HTTP session.
But your first controller listing does it all wrong. You are not supposed to instantiate the service class yourself. This is what Spring (Grails) does.
class FooController {
def clientListService // gets autowired by Grails/Spring
def index(){
hasSearched = false
clientListService.message = 'Hello' // only assign a String value to the service
[errorMessage: params.errorMessage, clients:clientListService]
}
}
This means you cannot not do something like
clientListService = new ClientListService(message: "Hello")
and expect your code to work. Hope this helps.

Grails command object initialization

In my Grails 2.3.8 app, I've defined the following controller action
class RegisterController {
def register(User user) {
render text: "User name is '$user.name'"
}
}
The user argument is a domain class instance. If I invoke this controller with the URL
http://localhost:8080/myapp/register/register
I get a NullPointerException. However my understanding of databinding is that if this action is invoked without any parameters, the argument should be assigned a new User()
However my understanding of databinding is that if this action is
invoked without any parameters, the argument should be assigned a new
User()
That is not necessarily the case. For domain class command objects if no parameters are present a new instance is only created for POST requests.
From http://grails.org/doc/2.4.0.RC1/guide/theWebLayer.html#commandObjects...
If the command object's type is a domain class and there is no id
request parameter then null will be passed into the controller action
unless the HTTP request method is "POST", in which case a new instance
of the domain class will be created by invoking the domain class
constructor.
That text may be missing from the 2.3.8 docs. I will verify that and add it if necessary.
What if you modify:
'$user.name'
To be:
'${user?.name}'

How to get current user role with spring security plugin?

I am using the spring-security-core plugin in my grails app. I need to know the current user's role in a controller action. How can I retrieve that?
You can inject springSecurityService into your controller:
def springSecurityService
and then in your action, call:
def roles = springSecurityService.getPrincipal().getAuthorities()
See the docs here.
From a controller you can use two methods the plugin adds to the metaclass, getPrincipal and isLoggedIn:
def myAction = {
if (loggedIn) {
// will be a List of String
def roleNames = principal.authorities*.authority
}
}
If the action is secured you can skip the loggedIn/isLoggedIn() check.
If you simply need to check to see if a user is in a specific role then use SpringSecurityUtils.ifAllGranted which takes a single String as an argument which contains a comma-delimited list of roles. It will return true if the current user belongs to all of them. SpringSecurityUtils also has methods like ifAnyGranted, ifNotGranted, etc, so it should work for whatever it is you are trying to accomplish.
To get the user
def springSecurityService
def principal = springSecurityService.principal
String username = principal.username
SecurityContextHolder knows that:
SecurityContextHolder.getContext().getAuthentication().getAuthorities()
You can also use getAuthenticatedUser() by itself. This method is automatically injected in every controller, and thus only available from controllers. You will have to use one of the other methods if you want to access the current logged in user from anywhere else.

How to access User object in grails controller

I'm using spring security, and I need to get the User domain object in a controller.
If I call SpringSecurityService.getPrincipal(), I get back an object of type org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser. However, what I'm looking for is the User domain object I've defined in my Config.groovy like so:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'project.auth.User'
How can I best get at the User domain object?
Load the user instance using the cached id in the GrailsUser instance:
def user = User.get(SpringSecurityService.principal.id)

Resources