how to add users in spring security core - grails

I just added the spring security plugin to my grails application. I have a question about adding users and their associated roles. I am able to do it correctly in the bootstrap but was wondering how to do it in the GSP page. I have a gsp page with the corresponding fields. when submited, it call the save method. my user domain controller extends SecUser. below is the example:
class User extends SecUser {
String fname
String lname
Date dateCreated
Date lastUpdated
static constraints = {
fname (blank:false)
lname (blank:false)
}
String toString(){
fname & " " & lname
}
}
When the user is saved, it saves only items in the user domain, not the SecUser. Does anyone have an example GSP and controller code to save the all the user data?

I perceive that you have two problems :
How to create a Crud (including gsp) on your User class
How to persist the data on your class and its inherited fields
For the first question:
To create GSPs and everything you need to have a CRUD on your User class, I suggest that you use scaffolding. If will take care of all of this for you.
Remove everything from your UserController or create another controller with only the following code:
class UserController {
static scaffold = User
}
then, navigate to your UserController ({your_app}/user/index) and everything should be there.
If you want to have an actual controller and gsps and modify how they work, use the grails command :grails generate-all your.package.User
For the second question :
Unless there is a problem with your SecUser class (transient fields for example), all fields inherited from SecUser should be saved through a User.save()
Let me know how it goes,
Vincent Giguère

Did you use the included script to generate your User class?
grails s2-quickstart
DOMAIN_CLASS_PACKAGE USER_CLASS_NAME
ROLE_CLASS_NAME
[REQUESTMAP_CLASS_NAME]
eg.
grails s2-quickstart com.yourapp User Authority
When I did that in my grails app, the resulting User class did not extend SecUser.

Related

Operation save in Grails on a POGO

I'm beginner in Grails and I have a problem when I try to save a POGO
I have created 1 domain class
class Book {
String title
}
Then, I have generated the controller and view automatically.
Now, I want to be able to create a book with the code by clicking "create" (I know it is possible directly with the code generated but for my example I want to do it by the code). To do this, I have modified the method 'save(Book bookInstance)' in the controller like this
#Transactional
def save(Book bookInstance) {
def book = new Book(title:"New Grails Book").save()
But, when I go to the URL localhost:8080/myApp/book/create and then I click "Create", I have the error
message -> /myApp/WEB-INF/grails-app/views/book/save.jsp
description -> The requested resource is not available.
When I put this code in bootStrap, it is OK, so I don't understand why it is not in the controller
When you have a hasMany property in a domain class, Grails adds a Set property to the domain class with an AST transformation (so it's actually there in the bytecode, and it's visiable to Java) to represent the collection, and when you add a belongsTo a field of that type is added. So it's as if you had this code:
class Author {
Set<Book> books
static hasMany = [books: Book]
String name
}
and
class Book {
Author author
static belongsTo = [author: Author]
String title
}
The AST xform uses the map key as the field name, so you can use any valid field name, but the convention is to do what you did.
Properties are nullable:false by default, so your code doesn't save the Book instance because you didn't set the author property. When doing this explicitly you typically don't create the Book directly, but instead add it to the Author's collection using the dynamic addToBooks method. This sets the author field back-reference and when you save the author, the book is transitively validated and saved. This is all handled for you when you have code like new Book(params).save(), and you can do it directly, e.g.
Author author = ...
def book = new Book(title:"New Grails Book", author: author).save()
If you're using a generated controller and GSPs, there should be an author id in the params map, it'll likely be author.id, so that first line would be
Author author = Author.get(params['author.id'])
but you can add
println params
at the top of the action method to see all of the submitted params.
In general you don't want to look at the return value of the save call, since it will be null if there's a validation error and there's no way to retrieve the errors. So change
def book = new Book(...).save()
to
def book = new Book(...)
book.save()
and now you can call book.hasErrors(), book.getErrors(), book.errors, etc. to see if it was successful and if not, what went wrong.
But that's not the exact problem you're seeing, just one you will when you fix your problem. There's no save.gsp, and Grails also looks for save.jsp and confusingly includes that name in the not-found message. The save method is accessed via a POST request, typically from the form generated by the create action, and it either re-displays create.gsp with the submitted data and error messages when validation fails, or redirects to the view action when the save succeeds. There's no need for a save.gsp when using the generated code.

grails and spring security acl: show only some instances of a domain class

I'm using Spring Security ACL in my Grails project to manage access into my application. I can create Admin and User to have different permissions into the application.
Now, I want that a particular user can see only some instances of a domain class object. That is:
following the example domain class object
class Patient
{
String name;
String surname;
...
}
Suppose that there are 3 created Patient objects.
I want that, if I login with
username = test1
password=test1
I can see only Patient that belongs to this User.
I think that is needed that, when I create a new Patient, it is stored that this Patient belongs to the User currently logged.
How can I do that?
EDIT:
Another problem is that, if I change the URL in the part of id to show, I can see all the Patient that are created. I want that, if I change URL manually, I see an access error. Is it possible?
EDIT 2:
How can I get the role of the user currently logged in? I've tried with the following code How to get current user role with spring security plugin? but I cannot perform the getAuthorities() because it tells me that it does not exists
I've solved EDIT2 in the following discussion grails exception: Tag [paginate] is missing required attribute [total]
I need to solve the EDIT1
thanks
If I understand you right you need to define belongsTo. This will create mapping in database from Patient to User.
Edit: to get current logged in user use
class SomeController {
def authenticateService
def list = {
def user = authenticateService.principal()
def username = user?.getUsername()
.....
.....
}
}
To map to user change logic in controller or use events to create mapping
Edit: edit create action:
class PatientController {
def authenticateService
...
def create() {
def patientInstance = new Patient(params)
patientInstance.user = authenticateService.principal()
...
[patientInstance: patientInstance]
}
...
}

How to implement grails bean

In my grails application, there are ten domain classes, in every domain class there is one comment field which is common. It compromises of current authenticated user with current time-stamp.
How can I implement the above said comments using beans
Create a comment Domain class
class comment
{
String message;
static belongsTo=[User] //add or can leave it , for all your ten domains
}
Then you need to associate it with let say to Ten of your domain class ,ex.User
class User {
String UserName
static hasMany=[comments:Comment] // if you have many commentin one pass or
Comment comment ///just one to one relationship for every login one record
}
And the Bean ,
You can create a commentService for just operating on the comment and your domain class,grails create a DI bean automatically after you create a commentService on services
and you could have some sample service method which will be injected
def registerInfo (){
//do some comment and domin related stuff
}
like in a controller login
def commentService
def signin(){
commentService.registerInfo(params)
}

Referring to Related Record ID In Controller On Save()

I'm still new to Grails and GORM and I got stumped on this and wasn't able to figure out what I am doing wrong. The intent is to automatically relate the record to the logged in user through the Shiro plugin for Grails.
Class User { static hasMany = [stuff: Stuff] }
Class Stuff { static belongsTo = [user:User] }
Class StuffController {
def create = {
params.put('user', User.createCriteria().get{eq('username',SecurityUtils.subject.principal)}.id)
def stuffInstance = new Stuff(params)
stuffInstance.save()
}
}
I saw in the generate-views version of the create scaffold that the relevant field was referred to as name="user.id", but neither it nor variants (such as user_id) seems to work. The query to the Users domain returns the record id necessary, and params.put in this context seems to correctly append the params object with the new value when I render to a test page (so I'm guessing it's not immutable), but this is what I get from the save():
Property [user] of class [class org.stuffing.Stuff] cannot be null
I've even tried flipping it around and going the other way, with the same result:
User.createCriteria().get{eq('username',SecurityUtils.subject.principal)}
.addToStuff(new Stuff(params))`
.save()
Anyone able to enlighten me on what I'm missing here?
Thanks!
EDIT:
Apparently I was being braindead; I was overriding the "create" method, but the default action is "save" in the _form.gsp template, so it wasn't executing that branch.
On the plus side, I did learn about dynamic finders via Burt below, so it wasn't a total wash.
Thanks for your time, guys!
Your code can be a lot cleaner - there's no reason to use createCriteria here. If you're searching by username, use a dynamic finder:
def stuffInstance = new Stuff(params)
def user = User.findByUsername(SecurityUtils.subject.principal)
stuffInstance.user = user
if (!stuffInstance.save()) {
// inspect stuffInstance.errors
}

Grails SpringSecurity User Object

I have a basic Grails 2 application which I setup along with the SpringSecurityCore plugin. This seems to be working fine. However, when I try to add additional properties to my User.groovy file by way of an extended class, I cannot seem to reference those properties in my controllers.
To better illustrate this problem, please take a look at my basic class which extends the User.groovy:
UserInfo.groovy:
class UserInfo extends User {
String firstname
String lastname
}
On my page where I want to reference the current user's firstname, I am simply writing a method as follows:
def index() {
def uname = springSecurityService.currentUser.username
def firstname = springSecurityService.currentUser.firstname
render uname
}
This works fine for rendering the username, and I believe that this is because the username is referenced in the base User.groovy file:
class User {
transient springSecurityService
String username
String password
However, the above "def index()" method fails when I try to define the firstname as part of the springSecurityService.currentUser.firstname.
If I inject extra properties into the base User.groovy class, then I can reference them by way of springSecurityService.currentUser.[property]
To illustrate this:
class User {
transient springSecurityService
String username
String password
String firstname
...
I am then able to reference the firstname property of my user in the aforementioned index method.
Is it possible to reference the extended properties of my User without injecting values in the base User class? My goal here is to try and keep the User class as clean as possible while still being able to call upon the values referenced in the UserInfo.groovy file.
Thank you in advance for your time.
If you really need to put some properties of your User information into another domain and want those properties could still be accessed from springSecurityService.currentUser, you have to implement your own UserDetailsService to package the UserInfo properties with User.
If you extend the User class, the SpringSecurity plugin does not know anything about your extended class UserInfo.
If you call springSecurityService.currentUser you get an instance of User not of UserInfo - so you don't have the property firstname.
If you don't like to add several new properties to User you could add a reference to the UserInfo class.
class UserInfo {
static belongsTo = [user: User]
String firstname
String lastname
...
}
class User {
...
UserInfo userInfo
...
}
You should remember that this reference adds an extra table to your database, which causes an additional join operation if you want to access your user instance.
When you initially install the Spring Security plugin and created your User class, it should have added some properties in Config.groovy that tells it which class to use as the default user class. When extending the default User class, you should update the property in Config.groovy to reflect this. The property you are looking for to update (or add if it's not there) is the following:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'your.package.UserInfo'
There are about a handful of properties in this page that relate to User and Role/Authorities that you may want to update if you extend/update any of the defaults.

Resources