Grails SpringSecurity User Object - grails

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.

Related

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)
}

how to add users in spring security core

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.

Make a required class properties not required

I have a class set up to hold values on a registration form (VB.NET, MVC), and among the properties is a Password property:
Public Class RegisterModel
...
Private _password As String
<DisplayName("Password:"), Required(), ValidatePasswordLength(), DataType(DataType.Password)> _
Public Property Password() As String
Get
Return _password
End Get
Set(ByVal value As String)
_password = value
End Set
End Property
This works great when registering a new user, but I'd like to use the same class to update existing users. (Note: this app is run by an admin who is in charge of registering individuals and assigning passwords.) The way I'd like it to behave is if the admin leaves the password blank, then the password is not changed, but the rest of the information is. If I use this class, the password can't be left blank because it fails on the Required() and ValidatePasswordLength() calls.
Is there a way to use this class but tell the model to ignore these particular validations? Even if I leave the password field off my edit form, it still fails. Do I need to create a whole duplicate class without these restrictions on the password field? There must be a better way.
You could implement IDataErrorInfo and have a flag set on the model which indicates whether it is being used by an admin or not - you could then validate conditionally.
But overall, I'd say this is a bit of a code smell. You're using a model for two different, incompatible purposes. It'd be better to use a separate view model.
I'd recommend using the FluentValidation library. It's a fantastic way to separate the concerns of your view (view model) and the actual validation you want to perform. You could pass parameters into it to drive different behavior. Check out When/Unless conditions or just writing completely custom validation methods with the Must operator.
public class RegisterModelValidator: AbstractValidator<RegisterModel>
{
public RegisterModelValidator(bool isAdmin)
{
RuleFor(x => x.Password).NotEmpty().Unless(isAdmin);
...
}
}
As long as your view model would have identical properties in both scenarios, you should use the one view model and one validation class. If the model varies at all I'd use two view models as David recommends.
You can do this in 2 ways:
1: add the [ValidateInput(false )] attribute to the action
or
2: Add a new property to the Register Model
public bool IsNewUser {get;}
3: Create a new class level attribute that takes IsNewUser into account when validating

How can I reference my own table with the MVC Controller.User property?

With the default membership provider for MVC 2 projects, I can reference User.Identity.UserName as per whatever it creates by default. I don't want to do this--want to use my own tables. So, I implemented the System.Web.Security.MembershipProvider class. The only thing I've implemented, as per many posts on the web and SO, is ValidateUser(string username, string password)
I can easily see this accepts username and password strings, I access my database context (LINQ to Entities, actually the dotConnect provider for MySQL), and check the username and password--simple enough.
But, how can I make the Controller.User object use the properties of my own table. For example, my table is called Staff. It has StaffID (PK), FirstName, LastName, etc. How can I access the StaffID of the current contextual user as follows?
int id = User.StaffID;
I found this post by Matt Wrock, but I can't really make sense of implementing the User class, specifically the IsInRole method. When is this object constructed, and where do the constructor arguments come from?
I don't like the Membership provider so I try to avoid dealing with it at all cost. In case you rather not use the User from the controller, you can do the following.
Create a base controller and have all your controllers inherit from it.
In your base controller, add a property called CurrentUser of whatever type you want to use (probably Linq 2 Sql type).
Override the Initialize method on your base controller and run the logic to get the proper user if the user is authenticated. Set CurrentUser to the proper user. Now you have access to that property in any controller that inherits from your base controller.
public BaseController : Controller
{
public MyUserEntity CurrentUser {get; set;}
protected override void Initialize(RequestContext requestContext)
{
CurrentUser = null;
if (requestContext.HttpContext.User.Identity.IsAuthenticated)
{
var userRepository = new UserRepository();
CurrentUser = userRepository.GetUser(requestContext.HttpContext.User.Identity.Name);
}
}
}
And to use it:
public StaffController : BaseController
{
public ActionResult View()
{
var staffRepository = new StaffRepository();
var staff = staffRepository(CurrentUser.StaffID);
return View(staff);
}
}
You'll have to do quite a bit if you want to get that to work.
you'll need to define your own class that descend from
GenericIdentity
Next you'll need define your own class that descends from
GenericPrincipal
This class can have the properties you'd like to reference (StaffID for example).
Thne you'll need to hook into the actual authentication process and assign the instance of your GenericPrincipal descendant to the "User" property.
Then each time you reference if you'll have to cast it to be your type in order to get access to the additional properties.
((MyPrincipal)User).StaffID
That's quite a bit more work as compared to what you've had to do so far.
But it's doable.

Resources