How to get All users which have a certain Role in grails - grails

I want to retrieve all users which have a specific Role like "ROLE_USER".
Below are Domain Classes for User, Role and UserRole.
User.groovy
class User {
transient springSecurityService
String username
String password
String email
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
Role.groovy
class Role {
String authority
static mapping = {
cache true
}
static constraints = {
authority blank: false, unique: true
}
}
UserRole.groovy
class UserRole implements Serializable {
User user
Role role
boolean equals(other) {
if (!(other instanceof UserRole)) {
return false
}
other.user?.id == user?.id &&
other.role?.id == role?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (user) builder.append(user.id)
if (role) builder.append(role.id)
builder.toHashCode()
}
static UserRole get(long userId, long roleId) {
find 'from UserRole where user.id=:userId and role.id=:roleId',
[userId: userId, roleId: roleId]
}
static UserRole create(User user, Role role, boolean flush = false) {
new UserRole(user: user, role: role).save(flush: flush, insert: true)
}
static boolean remove(User user, Role role, boolean flush = false) {
UserRole instance = UserRole.findByUserAndRole(user, role)
if (!instance) {
return false
}
instance.delete(flush: flush)
true
}
static void removeAll(User user) {
executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user]
}
static void removeAll(Role role) {
executeUpdate 'DELETE FROM UserRole WHERE role=:role', [role: role]
}
static mapping = {
id composite: ['role', 'user']
version false
}
}
These Domain Classes are generated by Spring Security plugin.
I have added only email field for User class.
Here is my UserController.groovy
class UserController {
def index = {
}
def list = {
def role = Role.findByAuthority("ROLE_USER")
println "role id "+role.id
def users = User.findAll() //Its giving me all Users regardless of Role
println "total users "+users.size()
for(user in users)
{
println "User "+user.username+" "+user.email
}
render (view: "listUsers", model:[users:users])
}
}
In the list action I used User.findAll() but its giving me all user with all roles.
I want user list only from a certain role..
EDIT
Code to Assign Roles to newly created user
def username = params.username
def emailID = params.emailID
def password = params.password
def testUser = new User(username: username, enabled: true, password: password,email:emailID)
testUser.save(flush: true)
def userRole = new Role(authority: 'ROLE_USER').save(flush: true)
UserRole.create testUser, userRole, true
Thanks..

Replace
def users = User.findAll()
with
def users = UserRole.findAllByRole(role).user
and you should get all users with the required role.
EDIT
In your code sample you try to create a new Role for the User. Since a Role with the authority ROLE_USER already exists and authority has to be unique (see the 'constraints' part in your Role class) this new Role cannot be saved to the database. Because the Role you assign in UserRole.create doesn't exist in the database the UserRole is not saved either. You would have to assign the existing Role to the new User (e.g. with `Role.findByAuthority').
Creating the roles in Bootstrap.groovy is a good idea according to Spring Source because roles "are typically defined early in the life of the application and correspond to unchanging reference data. That makes BootStrap the ideal place to create them." (Spring Source Blog)

Related

Spring Security check if User has RoleGroup

I have the domain:
User hasOne RoleGroup hasMany Role
Exemples:
RoleGroup: Admin, Professional, Client, ...
Role: ROLE_ACTION_1, ROLE_ACTION_2, ...
How I check if a user has a RoleGroup with annotation #Secured?
I need to check if user contains all roles of RoleGroup?
User class:
class User implements Serializable {
private static final long serialVersionUID = 1
static constraints = {
password blank: false, password: true
username blank: false, unique: true
}
static mapping = {
password column: '`password`'
version false
table schema: "CA"
}
static transients = ['springSecurityService']
transient springSecurityService
transient boolean enabled = true
transient boolean accountExpired
transient boolean accountLocked
transient boolean passwordExpired
String username
String password
RoleGroup profile
Set<RoleGroup> getAuthorities() {
[profile]
}
}
RoleGroup class:
class RoleGroup implements Serializable {
private static final long serialVersionUID = 1
String name
Set<Role> getAuthorities() {
RoleGroupRole.findAllByRoleGroup (this)*.role
}
}
I think you have not fully grasped spring security.
When using annotation - first annotation must be enabled in the config - this is the case by default.
You then secure either an entire controller or a controller action using something like this
#Secured(['ROLE_ADMIN', 'ROLE_USER'])
It has no way of working out all of what the user has as authority groups.
Although in the code you pasted in the RoleGroup class you have :
getAuthorities()
I have tweaked my User domain class and added the following:
Set<RoleGroup> getAuthorities() {
UserRoleGroup.findAllByUser(this)*.roleGroup
}
Set<RoleGroup> getAuthoritiesNames() {
UserRoleGroup.findAllByUser(this)*.roleGroup?.name
}
So when I have a user
i.e. User user=User.get(1L)
def authorities = user.getAuthorities()
println "user ${user} has ${authorities}"
which is a list containing all the authorities
if (authorities.contains('ROLE_USER')) {
println "WOOHOO"
}
With spring security you could also use it within gsps:
<sec:ifAllGranted roles="ROLE_ADMIN">
show something
</sec:ifAllGranted>
So back to your question:
You have :
Set<RoleGroup> getAuthorities() {
[profile]
}
Is that something you have in put in place ?
From where it is :
class RoleGroup implements Serializable {
private static final long serialVersionUID = 1
String name
Set<Role> getAuthorities() {
RoleGroupRole.findAllByRoleGroup (this)*.role
}
}
This should list you all the authorities
User user = User.get(1L)
def authorities = user?.profile?.getAuthorities()

Grails Spring Security Core unable to log in

Installed spring-security-core 2.0-RC2 (with grails 2.3.6), ran the quick start but I'm not able to log in. Each time I try, I get the 'Sorry, we were not able to find a user with that username and password.' error.
Done some research and I'm not double encoding the password or nor am I using salt (from what I can tell). I've used earlier versions in other projects, so not sure what's going on. I've also dropped the encodePassword() from the domain class and verified in the DB that it's what I expect it to be
Here's my User domain class:
class User {
transient springSecurityService
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static transients = ['springSecurityService']
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
and my Bootstrap:
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = new Role(authority: 'ROLE_USER').save(flush: true)
def testUser = new User(username: 'me', password: 'me')
testUser.save(flush: true)
UserRole.create testUser, adminRole, true
UserRole.create testUser, userRole, true
any idea of what I'm doing wrong?
Thanks!
That looks fine, but funny things can be happening under the hood. I wrote up a couple of blog posts to help diagnose issues like this. Check out http://burtbeckwith.com/blog/?p=2003 and http://burtbeckwith.com/blog/?p=2029

With specified username getting 'Sorry, we were not able to find a user with that username and password.' message when logging int

I have installed the grails Spring-Security plugin:
plugins {
compile ':spring-security-core:2.0-RC2'
}
Then I used the grails s2-quickstart com.jane Person Role command to create the needed domain classes.
As I have my own User class I refactored the code to use my User class:
package com.jane
class User {
transient springSecurityService
String email
String name
String password
Boolean isAgreeTerms = false
Date agreeTermsDt
Boolean isActive = false
Boolean isBlocked = false
Date dateCreated
Integer createdBy = 0
Date lastUpdated
Integer modifiedBy = 0
static transients = [ 'springSecurityService' ]
static hasMany = [ userProductTier: UserProductTier ]
static mapping = {
id column: "userID"
dateCreated column: 'createdDt'
lastUpdated column: 'modifiedDT'
}
static constraints = {
email blank: false, email: true, unique: true, size: 5..100
name blank: false, size: 3..50
password blank: false
}
void beforeInsert() {
if ( isAgreeTerms ) {
agreeTermsDt = new Date()
}
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
I then modified the config.groovy file to:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.jane.User'
grails.plugin.springsecurity.userLookup.usernamePropertyName = 'email'
grails.plugin.springsecurity.userLookup.enabledPropertyName = 'isActive'
grails.plugin.springsecurity.userLookup.accountExpiredPropertyName = 'isBlocked'
grails.plugin.springsecurity.userLookup.accountLockedPropertyName = 'isBlocked'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.jane.UserRole'
grails.plugin.springsecurity.authority.className = 'com.jane.Role'
I can create users fine, verify they are in the database, have verified that encodePassword is called once. But every time I try to login I get the following error:
Sorry, we were not able to find a user with that username and
password.
And here is the service method to create users:
User createTeamLeader( String name, String email, String password, Boolean isAgreeTerms, Integer productTierId ) {
User user = new User( name: name, email: email, password: password, isAgreeTerms: isAgreeTerms, isActive: true)
UserProductTier userProductTier = new UserProductTier( productTierId: productTierId )
user.addToUserProductTier( userProductTier )
user.save()
UserRole.create( user, Role.findByAuthority('ROLE_USER'), true )
UserRole.create( user, Role.findByAuthority('ROLE_LEAD'), true )
user
}
Often adding debug logging helps, since Spring Security logs a lot at the debug level:
log4j = {
...
debug 'org.springframework.security'
}
In this case it didn't show the problem, so I added an event listener to see if there was information in the failure event:
grails.plugin.springsecurity.useSecurityEventListener = true
grails.plugin.springsecurity.onAbstractAuthenticationFailureEvent = { e, appCtx ->
println "\nERROR auth failed for user $e.authentication.name: $e.exception.message\n"
}
That displayed this:
ERROR auth failed for user ernie#ss.com: No such property: authorities for class: com.jane.User
When you made changes in the class, you removed the getAuthorities method that was in the original version, and is used by the UserDetailsService to determine granted roles during authentication. Adding it back got things working:
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}

unknown behavior of grails while adding role to existing user

Whenever i add role to my existing User its not functioning.
There are no errors in logs, I also accessed my controller with try catch but no luck.
Here is my addRole closure:
def addRole = {
def role = Role.get(params.addRoleAutoComplete_id)
def user = User.get(params.id)
if (!role) {
flash.message = "Select role from list"
} else {
try{
UserRole.create( user, role)
}catch(Exception e){e.printStackTrace()}
}
redirect action:'edit', id:user.id
}
using Grails 2.3, grails spring security plugin and STS 3.2
Here is My UserRole.Groovy:
class UserRole implements Serializable {
User user
Role role
boolean equals(other) {
if (!(other instanceof UserRole)) {
return false
}
other.user?.id == user?.id &&
other.role?.id == role?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (user) builder.append(user.id)
if (role) builder.append(role.id)
builder.toHashCode()
}
static UserRole create(User user, Role role, boolean flush = false) {
new UserRole(user: user, role: role).save(flush: flush, insert: true)
}
static boolean remove(User user, Role role, boolean flush = false) {
UserRole instance = UserRole.findByUserAndRole(user, role)
if (!instance) {
return false
}
instance.delete(flush: true)
true
}
static mapping = {
id composite: ['role', 'user']
version false
}
}

Null Pointer on springSecurityService.currentUser when using weceem grails-plugin

i'm using Grails 2.1.1 in my project, right now i'm using springSecurityService.currentUser to get user credential, etc.
in the past 2 days, my project need some CMS extension and i've stumbled upon Weceem plugins.
set things here and there, in the end my project with Weceem plugins is now running, but getting Null Pointer Exception each time the springSecurityService.currentUser method is called.
Without weceem grails-plugin everything is running fine, so i assume there's some settings that i need to make. the question is where and what?
this is my user class
class User {
transient springSecurityService
String username
String password
boolean enabled = true
boolean accountExpired = false
boolean accountLocked = false
boolean passwordExpired = false
Person person
static hasOne = [Person]
static hasMany = [roles: Role]
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
roles as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}}
and this is my controller that called the springSecurityService
//show the list of all person
def list = {
//get all the sorting params
params.sort = params.sort ?: 'firstName'
params.order = params.order ?: 'asc'
params.max = params.max ?: 10
params.offset = params.offset ?: 0
def test = springSecurityService.getCurrentUser()
def personList = Person.createCriteria().list (max: params.max, offset: params.offset) {
if (springSecurityService.currentUser.person.affiliate.value != 'Admin'){
eq("affiliate", springSecurityService.currentUser.person.affiliate)
eq("deleted", false)
}
order(params.sort, params.order)
}
render view:'list', model:[persons: personList, personTotal: personList.totalCount]
}

Resources