understanding createacl in spring security acl? - grails

I am following this tutorial in order to understand how spring acl works.
https://grails-plugins.github.io/grails-spring-security-acl/v3/index.html#tutorial
The sample data service is as follows.
#Transactional
class SampleDataService {
def aclService
def aclUtilService
def objectIdentityRetrievalStrategy
void createSampleData() {
createUsers()
loginAsAdmin()
grantPermissions()
// logout
SCH.clearContext()
}
private void loginAsAdmin() {
// have to be authenticated as an admin to create ACLs
SCH.context.authentication = new UsernamePasswordAuthenticationToken(
'admin', 'admin123',
AuthorityUtils.createAuthorityList('ROLE_ADMIN'))
}
private void createUsers() {
def roleAdmin = new Role(authority: 'ROLE_ADMIN').save()
def roleUser = new Role(authority: 'ROLE_USER').save()
3.times {
long id = it + 1
def user = new User("user$id", "password$id").save()
UserRole.create user, roleUser
}
def admin = new User('admin', 'admin123').save()
UserRole.create admin, roleUser
UserRole.create admin, roleAdmin
}
private void grantPermissions() {
def reports = []
100.times {
long id = it + 1
def report = new Report(name: "report$id").save()
reports << report
aclService.createAcl(
objectIdentityRetrievalStrategy.getObjectIdentity(report))
}
// grant user 1 admin on 11,12 and read on 1-67
aclUtilService.addPermission reports[10], 'user1', ADMINISTRATION
aclUtilService.addPermission reports[11], 'user1', ADMINISTRATION
67.times {
aclUtilService.addPermission reports[it], 'user1', READ
}
// grant user 2 read on 1-5, write on 5
5.times {
aclUtilService.addPermission reports[it], 'user2', READ
}
aclUtilService.addPermission reports[4], 'user2', WRITE
// user 3 has no grants
// grant admin admin on all
for (report in reports) {
aclUtilService.addPermission report, 'admin', ADMINISTRATION
}
// grant user 1 ownership on 1,2 to allow the user to grant
aclUtilService.changeOwner reports[0], 'user1'
aclUtilService.changeOwner reports[1], 'user1'
}
}
My concern is with this line
aclService.createAcl(objectIdentityRetrievalStrategy.getObjectIdentity(report))
What is the purpose of createacl? I commented out this line and the app seems to function properly. So is this line not necessary?
I appreciate any help! Thanks!

Acl is created on adding permissions too. As you can see it creates acl on add permission, but better to create acl after you insert object into db(afterInsert event) to create permission faster. The code from addPermission method:
MutableAcl acl
try {
acl = aclService.readAclById(oid)
}
catch (NotFoundException e) {
acl = aclService.createAcl(oid)
}

Related

how to get currently logged in user role in grails/spock unit test

void "test saveSupervisor action"() {
setup:
def testUser = new User()
controller.userAuthService = [currentUser: testUser]
expect:
//User supervisor= new User()
User supervisor= new User(username: "sp123456",password: "pwd")
supervisor.save()
println "spv************ : "+ supervisor
when:"When User NAME Given"
controller.params.username = "sp123456"
controller.saveSupervisor()
then:
response.redirectUrl.endsWith '/showsupervisor/id'
}`---controller code----`
#Secured("hasRole('ROLE_ADMIN') and (hasRole('ROLE_SUPERVISOR') )")
#Transactional
def saveSupervisor(User userInstance) {
if (userInstance == null) {
notFound()
return
}
if (userInstance.hasErrors()) {
respond userInstance.errors, view:'create'
return
}
userInstance.save flush:true
def spvRole = Role.findByAuthority('ROLE_SUPERVISOR')
UserRole.create userInstance, spvRole , true
}
But I think I am doingf some thing wrong
I have these user roles, ROLE_SUPERVISOR, ROLE_ADMIN
when a user with having both role_supervisor and role_admin logged in to application then only he is given access to action savSupervisor(). How can I capture the logged in user's roles in the spock test?? I want to test if a user logged in with the roles ROLE_SUPERVISOR "and" ROLE_ADMIN then ONLY he is given access to saveSupervisor() method. I am using spring security, Please help me.

Grails, Spring Security core, change user authority

I generated Role, User and UserRole class using the Spring Security Core Plugin. I want to set the users role directly in the user-creation-process. I added a "Role" field in User but don't know how and where I should set the entry in UserRole.
Is there anything else to implement like reauthentication to update a users role afterwards?
You should delete link to Role from User and use next code, after creating User and Role:
UserRole.create(user,role,true)
Where user your created user, role your created role, and true is indicated that userRole should create with flush:true
Good luck!
Yes its works!!! thanks, this is my code in a Service:
public String updateUser(long userId, String username, String password, long roleId){
Object[] args = [messageSource.getMessage('spring.security.ui.login.username',null, null),username];
def user = User.get(userId);
def userTemp = User.findAllByUsername(username);
if(userTemp.isEmpty() || userTemp.get(0).id == userId){
def role = Role.get(roleId);
user.username = username;
user.roleId = roleId;
if (password != ''){
user.password = password;
}
user.save(flush:true);
UserRole.create(user,role,true);
return "<span class='successMessage'><strong>" + messageSource.getMessage("message.common.record.saved.successfully", args, null) + "</strong></span>";
} else {
return "<span class='warnMessage'><strong>" + messageSource.getMessage("message.common.register.exist", args,null) + "</strong></span>";
}
}

How to add a User in Grails Bootsrap with Audit Trails on?

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

Grails 2.1.1 and Spring Security Core plugin

I've been noticing that a lot of the tutorials I'm following use this:
def springSecurityService
and since I want to get records only by current logged in user I use:
def user = params.id ? User.findByUserId(params.id) : User.get(springSecurityService.principal.id)
and also in my Bootstrap I want to create a username and password, so for instance
def user = new User(
username: username,
password: springSecurityService.encodePassword("tops3kr17"),
enabled: true)
However I noticed that the password is not being created, and Spring Source Tools does not find the method .principal.id or .encodePassword (they stay underlined in STS) and wants to use SpringSecurityService with a capital S when hitting CTL+SPACE (and doesn't complete .principal.id or .encodePassword).
So i'm a little lost because it seems that the tutorials are out of date
So how can I do what I described with what the current supported methods are? Or am I missing something really simple? : )
class BootStrap {
def springSecurityService
def init = { servletContext ->
def demo = [
'jack' : [ fullName: 'Jack Demo Salesman'],
'jill' : [ fullName: 'Jill Demo Saleswoman']]
def now = new Date()
def random = new Random()
def userRole = SecRole.findByAuthority("ROLE_SALES") ?: new SecRole(authority: "ROLE_SALES").save()
def adminRole = SecRole.findByAuthority("ROLE_ADMIN") ?: new SecRole(authority: "ROLE_ADMIN").save()
def users = User.list() ?: []
if (!users) {
demo.each { username, password, userAttrs ->
def user = new User(
username: username,
password: springSecurityService.encodePassword('secret'),
enabled: true)
if (user.validate()) {
println "DEBUG: Creating user ${username}..."
println "DEBUG: and their password is ${password}"
user.save(flush:true)
SecUserSecRole.create user, userRole
users << user
}
else {
println("\n\n\nError in account bootstrap for ${username}!\n\n\n")
user.errors.each {err ->
println err
}
}
Using the injected instance of SpringSecurityService is the right approach.
def springSecurityService
def foo() {
springSecurityService.principal
springSecurityService.encodePassword('fdsfads')
....
}
If the IDE isn't recognizing it, there is an issue with your IDE.

Grails Spring-Security-Core plugin - Cannot authenticate user

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.

Resources