Search code examples
grailsgrails-controller

How to ensure models get tied to current user without using `generate controller`?


I am trying to create my first Grails application and I am finding that many of the domain models need to be tied to the current user. For example, the comment created, has to be owned by the current user, the profile saved & edited must be for the current user, etc.

I started using generate controller and inserting the necessary code each time. However, often this is the only change I'm currently making to those controllers and its the same one each time. There must be a more elegant way that feels more "Graily".

The best idea I have come up so far is to name the field that has to be tied to the current user the exact same thing in every model (e.g. originatingUser) and then user a filter on before to override whatever is currently set as originatingUser to the current User stored in session.

Are there flaws in this approach? Is there something better?


Solution

  • I started using generate controller and inserting the necessary code each time. However, often this is the only change I'm currently making to those controllers and its the same one each time. There must be a more elegant way that feels more "Graily".

    Whatever you do, don't copy/paste code everywhere. That has nothing to do with Grails. Just don't do it. Every time you do it God kills a kitten.

    It's hard to say without knowing more details about what you are doing, but I can see a few options

    1) If you need to keep the entities out the database, once you load them you can put them in the session, along with the user. You can write code in a base controller class to access the session to retrieve the "current" model instance and then have all your controllers extend that controller. Or you could optionally put the session access code in some sort of helper.

    2) The problem with 1 is it doesn't scale very well. If you have lots of objects you need to keep around, I wouldn't put them in the session. In this case you need to look at your design. Do you really need to keep the instances in the session? If you are checking if the user owns the object being modified, you can put that check in a service method. So if you check on edit, the first thing the service should do is check whether the user a) has the necessary role to modify the instance (if you are using security), and b) check the the user owns the instance (or otherwise can modify it).

    EDIT BASED ON COMMENTS

    First, if you are using the Spring Security plugin, you can get the current user easily.
    If you go this route, you need to inject the security service into every controller/service where you want to get the user.

    Second, if you are not, you should write a SessionHelper class, with static methods on it, to help keep all your session manipulation codez in one place (Spring Security also has a helper like this). If you do this, it's a one liner to get your current user whenever you want.

    Finally, you should be getting the user in your service layer. Services should do all manipulation of persistent instances. If a user can only ever be attached to their own items, this also helps error that can arise by somehow getting the wrong user for a particular thing.