Related
I'm working on a grails rest app. The grails version I'm using is 3.3.1. I'm using spring-security-rest for authorization. I've created the following classes using the s2-quickstart command.
User
Authority
UserAuthority
The app runs fine but the unit tests for the User class fail with the following error in console.
java.lang.IllegalStateException: Either class [hungr.Authority] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
at org.grails.datastore.gorm.GormEnhancer.stateException(GormEnhancer.groovy:469)
at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:300)
at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:296)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.currentGormStaticApi(GormEntity.groovy:1349)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.staticMethodMissing(GormEntity.groovy:756)
at hungr.UserController.$tt__save(UserController.groovy:39)
at hungr.UserController.save_closure1(UserController.groovy)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:430)
at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
at org.grails.testing.runtime.support.ActionSettingMethodHandler.invoke(ActionSettingMethodHandler.groovy:28)
at hungr.UserControllerSpec.Test the save action correctly persists(UserControllerSpec.groovy:90)
I've tried referring to the answer at GORM fails to realize Domain classes from a plugin are GORM classes
but nothing worked. I'm pretty new to grails hence I have no clue what may be going wrong.
the classes I'm using are:
User.Groovy
#GrailsCompileStatic
#EqualsAndHashCode(includes='username')
#ToString(includes='username', includeNames=true, includePackage=false)
class User implements Serializable, UserDetails {
private static final long serialVersionUID = 1
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
String name
String email
Integer age
Boolean isVeg
byte[] profilePicture
String profilePictureContentType
String facebookId
String facebookProfilePictureUrl
boolean isFacebookUser
static hasMany = [notifications: Notification, posts: DiaryItem, comments: Comment]
Set<Authority> getAuthorities() {
(UserAuthority.findAllByUser(this) as List<UserAuthority>)*.authority as Set<Authority>
}
#Override
boolean isAccountNonExpired() {
return !accountExpired
}
#Override
boolean isAccountNonLocked() {
return !accountLocked
}
#Override
boolean isCredentialsNonExpired() {
return !passwordExpired
}
static constraints = {
password nullable: false, blank: false, password: true
username nullable: false, blank: false, unique: true
facebookId nullable: true
name nullable: false, blank: false, maxSize: 100
email blank: false, email: true
age nullable: false, min: 8
isVeg nullable: false
profilePicture nullable: true, maxSize: 1073741824
profilePictureContentType nullable: true
isFacebookUser nullable: false
facebookProfilePictureUrl nullable: true, maxSize: 1000
}
static mapping = {
password column: '`password`'
}
}
Authority.Groovy
#GrailsCompileStatic
#EqualsAndHashCode(includes='authority')
#ToString(includes='authority', includeNames=true, includePackage=false)
class Authority implements Serializable, GrantedAuthority {
private static final long serialVersionUID = 1
String authority
static constraints = {
authority nullable: false, blank: false, unique: true
}
static mapping = {
cache true
}
}
UserAuthority.Groovy
#GrailsCompileStatic
#ToString(cache=true, includeNames=true, includePackage=false)
class UserAuthority implements Serializable {
private static final long serialVersionUID = 1
User user
Authority authority
#Override
boolean equals(other) {
if (other instanceof UserAuthority) {
other.userId == user?.id && other.authorityId == authority?.id
}
}
#Override
int hashCode() {
int hashCode = HashCodeHelper.initHash()
if (user) {
hashCode = HashCodeHelper.updateHash(hashCode, user.id)
}
if (authority) {
hashCode = HashCodeHelper.updateHash(hashCode, authority.id)
}
hashCode
}
static UserAuthority get(long userId, long authorityId) {
criteriaFor(userId, authorityId).get()
}
static boolean exists(long userId, long authorityId) {
criteriaFor(userId, authorityId).count()
}
private static DetachedCriteria criteriaFor(long userId, long authorityId) {
UserAuthority.where {
user == User.load(userId) &&
authority == Authority.load(authorityId)
}
}
static UserAuthority create(User user, Authority authority, boolean flush = false) {
def instance = new UserAuthority(user: user, authority: authority)
instance.save(flush: flush)
instance
}
static boolean remove(User u, Authority r) {
if (u != null && r != null) {
UserAuthority.where { user == u && authority == r }.deleteAll()
}
}
static int removeAll(User u) {
u == null ? 0 : UserAuthority.where { user == u }.deleteAll() as int
}
static int removeAll(Authority r) {
r == null ? 0 : UserAuthority.where { authority == r }.deleteAll() as int
}
static constraints = {
user nullable: false
authority nullable: false, validator: { Authority r, UserAuthority ur ->
if (ur.user?.id) {
if (UserAuthority.exists(ur.user.id, r.id)) {
return ['userRole.exists']
}
}
}
}
static mapping = {
id composite: ['user', 'authority']
version false
}
}
EDIT 1:
The Unit Test class is:
class UserControllerSpec extends Specification implements
ControllerUnitTest<UserController>, DomainUnitTest<User> {
def populateValidParams(params) {
assert params != null
// TODO: Populate valid properties like...
//params["name"] = 'someValidName'
params["username"]
params["password"]
params["name"] = "User"
params["email"] = "user#hungr.com"
params["age"] = 19
params["isVeg"] = false
// new MockMultipartFile('profilePicture', 'myImage.jpg', imgContentType, imgContentBytes)
// def multipartFile = new GrailsMockMultipartFile('profilePicture', 'profilePicture.jpg', 'image/jpeg', new byte[0])
//request.addFile(multipartFile)
// params["profilePicture"] =// new MockMultipartFile('profilePicture', 'file.jpg', 'image/jpeg', "1234567" as byte[])
params["profilePictureContentType"] = "image/jpeg"
params["facebookId"] = "fb_id"
params["facebookProfilePictureUrl"] = "http://abc.def"
params["isFacebookUser"] = true
//assert false, "TODO: Provide a populateValidParams() implementation for this generated test suite"
}
void "Test the index action returns the correct model"() {
given:
controller.userService = Mock(UserService) {
1 * list(_) >> []
1 * count() >> 0
}
when:"The index action is executed"
controller.index()
then:"The model is correct"
!model.userList
model.userCount == 0
}
void "Test the create action returns the correct model"() {
when:"The create action is executed"
controller.create()
then:"The model is correctly created"
model.user!= null
}
void "Test the save action with a null instance"() {
when:"Save is called for a domain instance that doesn't exist"
request.contentType = FORM_CONTENT_TYPE
request.method = 'POST'
request.format = 'form'
controller.save(null)
then:"A 404 error is returned"
response.redirectedUrl == '/user/index'
flash.message != null
}
void "Test the save action correctly persists"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User)
}
when:"The save action is executed with a valid instance"
response.reset()
request.contentType = FORM_CONTENT_TYPE
request.method = 'POST'
request.format = 'form'
byte[] b = new byte[1]
b[0]= 123
request.addFile(new MockMultipartFile('profilePicture', 'file.jpg', 'image/jpeg', b))
populateValidParams(params)
def user = new User(params)
user.id = 1
controller.save(user)
then:"A redirect is issued to the show action"
response.redirectedUrl == '/user/show/1'
controller.flash.message != null
}
void "Test the save action with an invalid instance"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User) >> { User user ->
throw new ValidationException("Invalid instance", user.errors)
}
}
when:"The save action is executed with an invalid instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'POST'
def user = new User()
controller.save(user)
then:"The create view is rendered again with the correct model"
model.user != null
view == 'create'
}
void "Test the show action with a null id"() {
given:
controller.userService = Mock(UserService) {
1 * get(null) >> null
}
when:"The show action is executed with a null domain"
controller.show(null)
then:"A 404 error is returned"
response.status == 404
}
void "Test the show action with a valid id"() {
given:
controller.userService = Mock(UserService) {
1 * get(2) >> new User()
}
when:"A domain instance is passed to the show action"
controller.show(2)
then:"A model is populated containing the domain instance"
model.user instanceof User
}
void "Test the edit action with a null id"() {
given:
controller.userService = Mock(UserService) {
1 * get(null) >> null
}
when:"The show action is executed with a null domain"
controller.edit(null)
then:"A 404 error is returned"
response.status == 404
}
void "Test the edit action with a valid id"() {
given:
controller.userService = Mock(UserService) {
1 * get(2) >> new User()
}
when:"A domain instance is passed to the show action"
controller.edit(2)
then:"A model is populated containing the domain instance"
model.user instanceof User
}
void "Test the update action with a null instance"() {
when:"Save is called for a domain instance that doesn't exist"
request.contentType = FORM_CONTENT_TYPE
request.method = 'PUT'
controller.update(null)
then:"A 404 error is returned"
response.redirectedUrl == '/user/index'
flash.message != null
}
void "Test the update action correctly persists"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User)
}
when:"The save action is executed with a valid instance"
response.reset()
request.contentType = FORM_CONTENT_TYPE
request.method = 'PUT'
request.format = 'form'
request.addFile(new MockMultipartFile('profilePicture', 'file.jpg', 'image/jpeg', "1234567" as byte[]))
populateValidParams(params)
def user = new User(params)
user.id = 1
controller.update(user)
then:"A redirect is issued to the show action"
response.redirectedUrl == '/user/show/1'
controller.flash.message != null
}
void "Test the update action with an invalid instance"() {
given:
controller.userService = Mock(UserService) {
1 * save(_ as User) >> { User user ->
throw new ValidationException("Invalid instance", user.errors)
}
}
when:"The save action is executed with an invalid instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'PUT'
controller.update(new User())
then:"The edit view is rendered again with the correct model"
model.user != null
view == 'edit'
}
void "Test the delete action with a null instance"() {
when:"The delete action is called for a null instance"
request.contentType = FORM_CONTENT_TYPE
request.method = 'DELETE'
controller.delete(null)
then:"A 404 is returned"
response.redirectedUrl == '/user/index'
flash.message != null
}
void "Test the delete action with an instance"() {
given:
controller.userService = Mock(UserService) {
1 * delete(2)
}
when:"The domain instance is passed to the delete action"
request.contentType = FORM_CONTENT_TYPE
request.method = 'DELETE'
controller.delete(2)
then:"The user is redirected to index"
response.redirectedUrl == '/user/index'
flash.message != null
}
}
So normally in a Unit test you test a single unit, User in this case. Because you want to test additional entities, you need to add them to the test. You can do this by implementing getDomainClassesToMock. Best is to use the DataTest trait instead of the DomainUnitTest in this situation (DomainUnitTest extends DataTest).
So your test should look like:
class UserControllerSpec extends Specification implements
ControllerUnitTest<UserController>, DataTest {
Class<?>[] getDomainClassesToMock(){
return [User,Authority,UserAuthority] as Class[]
}
....
}
When I Edit the user all are saving but when I change the password it is getting the error.Please help me.
NullPointerException occurred when processing request: [POST] /openbrm /user/save
Stacktrace follows:
java.lang.NullPointerException
at com.sapienter.jbilling.client.authentication.CompanyUserDetails.getPlainUsername(CompanyUserDetails.java:84)
at com.sapienter.jbilling.client.authentication.JBillingPasswordEncoder.isPasswordValid(JBillingPasswordEncoder.java:75)
at com.sapienter.jbilling.client.user.UserHelper.bindPassword(UserHelper.groovy:155)
at jbilling.UserController.save(UserController.groovy:304)
at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
UserController.groovy
def save () {
UserWS user = new UserWS()
user.mainRoleId= Constants.TYPE_ROOT
UserHelper.bindUser(user, params)
def contacts = []
def userId= params['user']['userId'] as Integer
log.debug "Save called for user ${userId}"
def oldUser = userId ? webServicesSession.getUserWS(userId) : null
def company_id = session['company_id']
def company = CompanyDTO.createCriteria().get {
eq("id", company_id)
fetchMode('contactFieldTypes', FM.JOIN)
}
if ( !oldUser || SpringSecurityUtils.ifAllGranted('ROLE_SUPER_USER') || SpringSecurityUtils.ifAllGranted('MY_ACCOUNT_162') ) {
UserHelper.bindUser(user, params)
UserHelper.bindContacts(user, contacts, company, params)
} else {
user= oldUser
contacts= userId ? webServicesSession.getUserContactsWS(userId) : null
}
if ( !oldUser || SpringSecurityUtils.ifAllGranted('ROLE_SUPER_USER') || SpringSecurityUtils.ifAllGranted('MY_ACCOUNT_161') ) {
UserHelper.bindPassword(user, oldUser, params, flash)
} else {
user.password= null
}
UserDTO loggedInUser = UserDTO.get(springSecurityService.principal.id)
if (flash.error) {
user = new UserWS()
UserHelper.bindUser(user, params)
contacts = []
UserHelper.bindContacts(user, contacts, company, params)
render view: 'edit', model: [user: user, contacts: contacts, company: company, loggedInUser: loggedInUser, roles: loadRoles()]
return
}
try {
if (!oldUser) {
log.debug("creating user ${user}")
user.userId = webServicesSession.createUser(user)
flash.message = 'user.created'
flash.args = [user.userId as String]
} else {
log.debug("saving changes to user ${user.userId}")
webServicesSession.updateUser(user)
flash.message = 'user.updated'
flash.args = [user.userId as String]
}
// save secondary contacts
if (user.userId) {
contacts.each {
webServicesSession.updateUserContact(user.userId, it);
}
}
} catch (SessionInternalError e) {
flash.clear()
viewUtils.resolveException(flash, session.locale, e)
contacts = userId ? webServicesSession.getUserContactsWS(userId) : null
if(!contacts && !userId){
contacts = [user.getContact()]
}
render view: 'edit', model: [user: user, contacts: contacts, company: company, loggedInUser: loggedInUser, roles: loadRoles()]
return
}
if ( SpringSecurityUtils.ifAnyGranted("MENU_99") || SpringSecurityUtils.ifAnyGranted("ROLE_SUPER_USER") ) {
chain action: 'list', params: [id: user.userId]
} else {
chain action: 'edit', params: [id: user.userId]
}
}
In UserHelper.groovy it is getting the error at this method
static def bindPassword(UserWS newUser, UserWS oldUser, GrailsParameterMap params, flash) {
if (oldUser) {
// validate that the entered confirmation password matches the users existing password
if (params.newPassword) {
//read old password directly from DB. API does not reveal password hashes
def oldPassword = UserDTO.get(oldUser.userId).password
PasswordEncoder passwordEncoder = Context.getBean(Context.Name.PASSWORD_ENCODER)
//fake user details so we can verify the customers password
//should we move this to the server side validation?
CompanyUserDetails userDetails = new CompanyUserDetails(
oldUser.getUserName(), oldPassword, true, true, true, true,
Collections.EMPTY_LIST, null,null,oldUser.getUserId(), oldUser.getMainRoleId(), oldUser.getEntityId(),
oldUser.getCurrencyId(), oldUser.getLanguageId()
)
if (!passwordEncoder.isPasswordValid(oldPassword, params.oldPassword, userDetails)) {
flash.error = 'current.password.doesnt.match.existing'
return
}
} else {
newUser.setPassword(null)
}
}
// verify passwords only when new password is present
if (params.newPassword) {
if (params.newPassword == params.verifiedPassword) {
if (params.newPassword)
newUser.setPassword(params.newPassword)
} else {
flash.error = 'passwords.dont.match'
}
} else {
newUser.setPassword(null)
}
}
My CompanayUserDetails.java
package com.sapienter.jbilling.client.authentication;
import com.sapienter.jbilling.server.user.db.UserDTO;
import org.springframework.security.core.GrantedAuthority;
import grails.plugin.springsecurity.userdetails.GrailsUser;
import java.util.Collection;
import java.util.Locale;
public class CompanyUserDetails extends GrailsUser {
private final UserDTO user;
private final Locale locale;
private final Integer mainRoleId;
private final Integer companyId;
private final Integer currencyId;
private final Integer languageId;
public CompanyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<GrantedAuthority> authorities,
UserDTO user, Locale locale,
Integer id, Integer mainRoleId, Integer companyId, Integer currencyId, Integer languageId) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id);
this.user = user;
this.locale = locale;
this.mainRoleId = mainRoleId;
this.companyId = companyId;
this.currencyId = currencyId;
this.languageId = languageId;
}
public UserDTO getUser() {
return user;
}
public String getPlainUsername() {
return user.getUserName();
}
public Locale getLocale() {
return locale;
}
public Integer getMainRoleId() {
return mainRoleId;
}
public Integer getUserId() {
return (Integer) getId();
}
public Integer getCompanyId() {
return companyId;
}
public Integer getCurrencyId() {
return currencyId;
}
public Integer getLanguageId() {
return languageId;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("CompanyUserDetails");
sb.append("{id=").append(getId());
sb.append(", username=").append("'").append(getUsername()).append("'");
sb.append(", mainRoleId=").append(getMainRoleId());
sb.append(", companyId=").append(getCompanyId());
sb.append(", currencyId=").append(getCurrencyId());
sb.append(", languageId=").append(getLanguageId());
sb.append(", enabled=").append(isEnabled());
sb.append(", accountExpired=").append(!isAccountNonExpired());
sb.append(", credentialsExpired=").append(!isCredentialsNonExpired());
sb.append(", accountLocked=").append(!isAccountNonLocked());
sb.append('}');
return sb.toString();
}
}
Well you are passing null into the constructor for UserDTO
see
for
Collection<GrantedAuthority> authorities, UserDTO user, Locale locale,
you are passing
Collections.EMPTY_LIST, null,null
so of course getPlainUsername will fail
In your call to new CompanyUserDetails
CompanyUserDetails userDetails = new CompanyUserDetails(
oldUser.getUserName(), oldPassword, true, true, true, true,
Collections.EMPTY_LIST, null, <--- param $8 is null
And the definition
public CompanyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<GrantedAuthority> authorities,
UserDTO user, <--- param #8
And finally the NPE In your call to getPlainUsername
return user.getUserName();
NPE, can not invoke method on null user object.
So to understand your problem you really need to understand error codes:
java.lang.NullPointerException
at com.sapienter.jbilling.client.authentication.CompanyUserDetails.getPlainUsername(CompanyUserDetails.java:84)
According to my editor line 84 was
sb.append(", languageId=").append(getLanguageId());
I would suggest as a test set all these to a value
private final Integer mainRoleId=0;
private final Integer companyId=0;
private final Integer currencyId=0;
private final Integer languageId=0;
then change
this.mainRoleId = mainRoleId;
this.companyId = companyId;
this.currencyId = currencyId;
this.languageId = languageId
to
if (mainRoleId) { this.mainRoleId = mainRoleId;}
if (companyId) { this.companyId = companyId; }
if (currencyId) { this.currencyId = currencyId; }
if (languageId ) { this.languageId = languageId }
bad coding causes bad problems
I have a very strange behaviour on a production server.
When I start for the first time my server, there is no problem, but when I want to stop and restart it, I get the following error :
Configuring Spring Security Core ...
... finished configuring Spring Security Core
2013-10-31 12:03:08,156 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing the application: null
java.lang.NullPointerException
at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
at BootStrap$_closure1.doCall(BootStrap.groovy:16)
at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:308)
at grails.util.Environment.executeForEnvironment(Environment.java:301)
at grails.util.Environment.executeForCurrentEnvironment(Environment.java:277)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
2013-10-31 12:03:08,156 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing Grails: null
java.lang.NullPointerException
at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
at BootStrap$_closure1.doCall(BootStrap.groovy:16)
at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:308)
at grails.util.Environment.executeForEnvironment(Environment.java:301)
at grails.util.Environment.executeForCurrentEnvironment(Environment.java:277)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
oct. 31, 2013 12:03:08 PM org.apache.catalina.core.StandardContext startInternal
Here is my BootStrap.groovy :
class BootStrap {
def springSecurityService
def init = { servletContext ->
def existingAdminRole = Role.findByAuthority('ROLE_ADMIN')
def existingUserRole = null
def existingAdminUser = null
if (existingAdminRole) {
existingUserRole = UserRole.findByRole(existingAdminRole)
}
if (existingUserRole) {
existingAdminUser = existingUserRole.user
}
if (!existingAdminUser) {
def adminRole = new Role(authority: 'ROLE_ADMIN')
def adminUser = new User(username: 'admin', password: 'admin', enabled: true)
if (adminRole.validate()) {
adminRole.save(flush: true, failOnError: true)
}
if (adminUser.validate()) {
adminUser.save(flush: true, failOnError: true)
}
UserRole userRole = UserRole.create(adminUser, adminRole, true)
if (userRole.validate()) {
userRole.save(flush: true, failOnError: true)
}
}
}
def destroy = {
}
}
Here is my User.groovy (adding the nullable constraint did not solve the problem) :
User.groovy :
class User {
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static constraints = {
username nullable: true, blank: false, unique: true
password nullable: true, 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)
}
}
Here are my classe Role.groovy and UserRole.groovy :
Role.groovy :
class Role {
String authority
static mapping = {
cache true
}
static constraints = {
authority nullable: true, 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
}
}
Here is my DataSource.groovy file with the database settings :
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
driverClassName = 'com.mysql.jdbc.Driver'
username = 'root'
password = 'root'
url = 'jdbc:mysql://localhost:3306/database?autoreconnect=true&useUnicode=true&characterEncoding=utf-8'
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
}
}
production {
dataSource {
dbCreate = 'create-drop'
driverClassName = 'com.mysql.jdbc.Driver'
username = 'root'
password = 'root'
url = 'jdbc:mysql://localhost:3306/database?autoreconnect=true&useUnicode=true&characterEncoding=utf-8'
}
}
}
I really don't have any idea about what occured.
I have added the nullable constrainst, trying to put the databe into 'create-drop' / 'update'.
Funny thing : When I drop the databse then create it again, the first server start is good, but crash after a restart.
I try to put println logs into my BootStrap.groovy, I can see them into development environment, but not into production server.
So I'm not sure if my BootStrap is updated creating war.
I create the war using :
grails prod war target/my-new-war-0.0.x.war
Thanks for reading,
Snite
I'm not really sure what's wrong with your code, however your giant block of code was making my head hurt so I had to post this.
Role role = Role.findByAuthority("ROLE_ADMIN") ?: new Role(authority: "ROLE_ADMIN").save(flush: true, failOnError: true)
if (UserRole.countByRole(role) == 0) {
User user = new User(username: 'admin', password: 'admin', enabled: true).save(flush: true, failOnError: true)
UserRole.create(user, role, true)
}
hmmm well its a null point exception:
ERROR context.GrailsContextLoader - Error initializing the application: null
java.lang.NullPointerException
at com.aftmevent.security.UserRole.create(UserRole.groovy:32)
at BootStrap$_closure1.doCall(BootStrap.groovy:16)
Unsure if the pasted content matches up exactly to your own line numbers, something you could try for now is by going around and adding the question mark :
def existingAdminRole = Role.findByAuthority('ROLE_ADMIN')
def existingUserRole = null
def existingAdminUser = null
if (existingAdminRole) {
existingUserRole = UserRole.findByRole(existingAdminRole)
}
if (existingUserRole) {
existingAdminUser = existingUserRole.user
}
change to:
def existingAdminRole = Role?.findByAuthority('ROLE_ADMIN')
def existingUserRole = null
def existingAdminUser = null
if (existingAdminRole) {
existingUserRole = UserRole?.findByRole(existingAdminRole)
}
if (existingUserRole) {
existingAdminUser = existingUserRole?.user
}
Also you could try findorsavewhere rather than an attempt to generate a new record:
https://github.com/vahidhedayati/ajaxdependancyselectexample/blob/master/grails-app/conf/BootStrap.groovy
def n1=MyContinent.findOrSaveWhere(continentName: 'Asia')
def n2=MyContinent.findOrSaveWhere(continentName: 'Europe')
// Create countries and provde continent map value as above defs
def c1 = MyCountry.findOrSaveWhere(mycontinent: n2, countryName:'United Kingdom',ccode:'GB',language:'')
def c2 = MyCountry.findOrSaveWhere(mycontinent: n2, countryName:'France',ccode:'FR',language:'')
def c3 = MyCountry.findOrSaveWhere(mycontinent: n1, countryName:'China',ccode:'CN',language:'')
def c4 = MyCountry.findOrSaveWhere(mycontinent: n1, countryName:'India',ccode:'IN',language:'')
you will need to figure out what is going on in line 32 of UserRole which will be the start of your issue followed by BootStrap on line 16..
Thanks for all of your answer which help me to solve my issue.
It was stupid but in my rundeck script to deploy the war on the production server, it was an out of date version of the war which was used -_-
So doint it manually with the correct war version solve my problem.
Thanks because your advices help me to read adequat documentation on grails's framework and help me thinking looking here.
Cheers,
Snite
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)
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]
}