The Following Code Adds Multiple Roles to a Single user, it also should be noted that this will only work for a single session as we're trying to define the roles and users every time we start the app, to prevent any crashes due to that add a check for the database and create the roles and user IF they don't exist.
import trippinspring.*
class BootStrap {
def init = { servletContext ->
def adminRole = new SpringRole(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = new SpringRole(authority: 'ROLE_USER').save(flush: true)
def testUser = new SpringUser(username: 'me', enabled: true, password: 'password')
testUser.save(flush: true)
if (!testUser.authorities.contains(adminRole)) {
new SpringUserSpringRole(springUser: testUser, springRole: adminRole).save(flush: true,failOnError: true)
}
if (!testUser.authorities.contains(userRole)) {
new SpringUserSpringRole(springUser: testUser, springRole: userRole).save(flush: true,failOnError: true)
}
}
}
Most of the code is a direct reference to Aram Arabyan's answer, and Ian Roberts comments with some fixes to work with my code.
if (!testUser.authorities.contains(adminRole)) {
new SpringUserSpringRole(user: testUser, role: adminRole).save(flush: true,failOnError: true)
}
if (!testUser.authorities.contains(userRole)) {
new SpringUserSpringRole(user: testUser, role: userRole).save(flush: true,failOnError: true)
}
Just a suggestion, maybe you should try creating a hierarchy for your roles instead of adding two roles for a single user:
see doc.
Related
I am new in Grails and Spring Security. I try to make a simple register view. I created the User, Role and UserRole domain classes with the s2-quickstart script from spring-security.
My problem is that only the User will be saved in the database.
But I want to save the User and the UserRole.
Thats my controller:
#Secured('permitAll')
class RegisterController {
def index() {
}
def register() {
def user = new User(params)
user.save()
def role = Role.findByAuthority('ROLE_USER') // ROLE_USER will be created in the bootstrap class
UserRole.create(user, role)
redirect view: 'index'
}
}
If i put the same code in the bootstrap class the UserRole will be saved too.
Hope someone can help and explain, why this not work.
update your code:
def register() {
def user = new User(params)
user.save(flush: true, failOnError: true)
new UserRole(user: admin, role: Role.findByAuthority('ROLE_USER')).save(flush: true, failOnError: true)
redirect view: 'index'
}
If there will any issue in during save the UserRole then failOnError: true with throw error, then you can track the issue.
I have a system in Grails 2.5.3 and I have problems with the Bootstrap file in test and production environments. In DEV environment the initial data load works perfectly.
Domain class used. SecUser - Spring security
class SecUser implements Serializable {
...
UUID id
Date dateCreated
String username
String password
String email
....
}
Normal user. User:
class User extends SecUser {
UUID id
String name
...
// Relations
static belongsTo = [department:Department]
static hasMany = [evaluations:Evaluation]
}
Evaluation:
class Evaluation {
UUID id
Integer attemptNumber
Date completenessDate
Integer maxAttempt
String testName
Float testScore
// Relations
static belongsTo = [user:User]
}
And I have the following code to load the initial data. It is the same code for all three environments. Dev works well but prod and test show an error.
// Role
def adminRole = new SecRole(authority: 'ROLE_ADMIN')
def userRole = new SecRole(authority: 'ROLE_USER')
// Administrator
def newAdmin = new SecUser(
username: 'admin',
password: 'admin',
email: 'admin#example.com')
// Department
def idDepartment = new Department(name: 'I+D')
// Normal user
def newUser = new User(
username: 'user',
password: 'user',
email: 'user#example.com',
name: 'userTest',
department: idDepartment
)
// Evaluation
def evalUser = new Evaluation(
testName: 'Test example',
attemptNumber: 1,
maxAttempt: 2,
completenessDate: new Date(),
testScore: 7.55,
user: newUser)
// Saving roles
adminRole.save(flush: true, failOnError: true)
userRole.save(flush: true, failOnError: true)
// Saving new admin
newAdmin.save(flush: true, failOnError: true)
// Saving departments
idDepartment.save(flush: true, failOnError: true)
// Saving new users
newUser.save(flush: true, failOnError: true)
// Assign user to role
if (!newAdmin.authorities.contains(adminRole)) {
SecUserSecRole.create newAdmin, adminRole, true
}
if (!newUser.authorities.contains(userRole)) {
SecUserSecRole.create newUser, userRole, true
}
// Saving evaluations - HERE IS THE ERROR
evalUserSTT1.save(flush: true, failOnError: true)
And the error that is displayed only in test and prod environments is the following. I don't know why dev environment doesn't fail and the other environments fails with this violation.
This is due to the fact that in development environment, the datasource config is set to dbCreate = "create-drop" meaning every time you restart the application it drops and then re-creates the database. However in test and production environments are set to dbCreate = "update" where it only updates new changes. Now based on your bootstrap code, you are not checking if an object exists before save hence the bootstrap code will try to create the same roles and users that already exist from first run which causes conflicts.
In summary, modify your bootstrap code to check if records already exist, this is just an example, but will have to do the same for other roles and users etc, e.g.:
def adminRole
def adminRoleExists = SecRole.findByAuthority('ROLE_ADMIN')
if(!adminRoleExists ) {
adminRole = new SecRole(authority: 'ROLE_ADMIN')
adminRole.save(flush: true, failOnError: true)
}
I have installed grails Spring security core plugin with RequestMap to retrieve URL from the database. I assume I have setup everything as its mentioned in the guide. When I start my application(http://localhost:8080/scadmin/index/) I get 'sorry, you are not authorized to view this page'. The admin user authenticated properly but RequestMap isnt allowing me to access the url. What's that I am doing wrong? please help.
config.groovy
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.tx.sc.auth.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.tx.sc.auth.UserRole'
grails.plugin.springsecurity.authority.className = 'com.tx.sc.auth.Role'
grails.plugin.springsecurity.requestMap.className = 'com.tx.sc.auth.Requestmap'
grails.plugin.springsecurity.securityConfigType = 'Requestmap'
My controller -
class AdminController {
def index() {
List<Portal> pList = portalService.listAllPortalInfo()
render(view: "admin", model:[portalList:pList])
}
}
Setting Role
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
Admin User
def adminUser = new User(username: 'admin', password: '12345',email: 'admin#abc.com',enabled: true, accountLocked: false, accountExpired: false, passwordExpired: false).save(flush: true)
Map user and role-
if (!adminUser.authorities.contains(adminRole)) {
UserRole.create(adminUser, adminRole, true)
}
RequestMap-
new Requestmap(url: '/scadmin/admin/index', configAttribute: 'ROLE_ADMIN').save(flush: true)
/scadmin/admin/index should be /admin/index - don't include the context.
Hi I'm having a hard time trying to add the first user in my grails bootstrap. I've tried many different ways but all have failed since the Audit Trail plugin wants a user to stamp the createdBy and EditedBy fields but the first one doesn't exit yet.
Here is my config for Audit Trails, essentially it's the same as default except I'm using User.username over the User.id:
grails {
plugin {
audittrail {
createdBy.field = "createdBy"
createdBy.type = "java.lang.String" //Long is the default
editedBy.field = "editedBy"
editedBy.type = "java.lang.String" //Long is the default
createdDate.field = "createdDate"
editedDate.field = "editedDate"
currentUserClosure = {ctx->
def authPrincipal = ctx.springSecurityService.principal
if(authPrincipal && authPrincipal != "anonymousUser"){
return authPrincipal.username
} else {
return null //fall back
}
}
}
}
}
Here is what my User class looks like, ie. I just add the annotation for the plugin to work:
#gorm.AuditStamp
class User {
//... basic Spring Security Generated User File with minor changes
}
Here is the contents of my bootstrap file:
def adminUser = new User(
username: 'admin',
enabled: true,
password: 'password',
firstName: 'ADMIN',
lastName: 'ADMIN'
).save(flush: true)
// The below will work if I take off the annotation on User class.
SpringSecurityUtils.doWithAuth('admin') {
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
UserRole.create adminUser, adminRole, true
}
So now how can I add that first user? I've tried:
- Using annonymousUser
- Failed, plugin prevents it
- Hardcoding the createdBy and editedby to "admin"
- Failed get's overridden
- Use executeUpdate to insert the user directly in the DB
- Failed: in bootstrap
- Delay the save of the first user until the doWithAuth
- Failed: couldn't find the user
Any help would be great! Thanks!
I had the same problem and was searching for a solution. I managed to get it working by doing the below:
grails {
plugin {
audittrail {
createdBy.field = "createdBy"
createdBy.type = "java.lang.String" //Long is the default
editedBy.field = "modifiedBy"
editedBy.type = "java.lang.String" //Long is the default
createdDate.field = "createdDate"
editedDate.field = "modifiedDate"
//custom closure to return the current user who is logged in
currentUserClosure = {ctx->
//ctx is the applicationContext
def userName = ctx.springSecurityService.principal?.username
return userName != null ? userName : "System"
}
}
}
}
In the Bootstrap.groovy file, just do a save like:
def adminUser = new User(username: 'admin', enabled: true, password: 'password',
firstName: 'ADMIN', lastName: 'ADMIN').save(flush: true)
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
UserRole.create adminUser, adminRole, true
The newly created first user will be stamped with user "System" (createdBy and modifiedBy columns).
So I am banging my head against the wall trying to get spring-security-core-1.2.7.1 to work with Grails 2.0...
I have looked at the tutorial and run s2. Read that the new plugin encrypts passwords for you, so my bootstrap looks like:
def userRole = Role.findByAuthority('ROLE_USER') ?: new Role(authority: 'ROLE_USER').save(failOnError: true)
def adminRole = Role.findByAuthority('ROLE_ADMIN') ?: new Role(authority: 'ROLE_ADMIN').save(failOnError: true)
def adminUser = User.findByUsername('admin') ?: new User(
username: 'admin',
password: "admin",
enabled: true).save(failOnError: true)
def testUser = User.findByUsername('test') ?: new User(
username: 'test',
password: "test",
enabled: true).save(failOnError: true)
if (!adminUser.authorities.contains(adminRole)) {
UserRole.create adminUser, adminRole
}
if (!testUser.authorities.contains(userRole)) {
UserRole.create testUser, userRole
}
I can look at the H2 database and I see the users, their encoded passwords, see that the roles are created and can see the user role mappings are properly created as well.
However, I still get "Sorry, we were not able to find a user with that username and password." at the login prompt for both users.
I have turned on log4j debug 'org.springframework.security' but all I really get out of the logs is:
2012-01-23 23:08:44,875 ["http-bio-8080"-exec-5] DEBUG dao.DaoAuthenticationProvider - Authentication failed: password does not match stored value
I can't see anything obviously wrong with your code. I'm using the same version of Grails and the spring security plugin, and the following code in Bootstrap.groovy works for me:
def init = { servletContext ->
// create some roles
def userRole = createRole('ROLE_USER')
def adminRole = createRole('ROLE_ADMIN')
// create some users
User admin = createUser('Admin', 'admin#mailinator.com', adminRole)
User user = createUser('User', 'user#yahoo.co.uk', userRole)
}
private User createUser(name, username, role) {
def defaultPassword = 'password'
User user = User.findByUsername(username) ?: new User(
name: name,
username: username,
password: defaultPassword,
passwordConfirm: defaultPassword,
enabled: true).save()
if (!user.authorities.contains(role)) {
UserRole.create user, role
}
user
}
private createRole(String roleName) {
Role.findByAuthority(roleName) ?: new Role(authority: roleName).save()
}
I did have similar issue. Was because I've forgotten to add
grails.plugin.springsecurity.userLookup.userDomainClassName ='yourpackage.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName =yourpackage.UserRole'
grails.plugin.springsecurity.authority.className ='yourpackage.Role'
After that authentication was working.
You can fix the multiple datasources issue by updating the User class.
See https://stackoverflow.com/q/13296594
In the OP's original code, why is the username in single quotes and the password in double quotes. That might be the problem.