how to get contacts created by currently logged in user in grails - grails

I have implemented spring security service for user authentication in my grails application.
I have Subscriber.groovy(user table) and Contact.groovy domains. Once a subscriber(user) logs in, he/she can create contacts.There is hasMany relationship between Subscriber and Contact domain.
Problem: I have implemented search functionality for contacts created by currently logged user or subscriber on contact page. It works fine but it fetch all contacts in system but I want only contacts those are created by currently logged in subscriber(user).
How to search contacts those are created by currently logged in subscriber.
Method for searching contacts from contact table
def searchAJAX = {
def contacts = Contact.findAllByNameLike("%${params.query}%")
//Create XML response
render(contentType: "text/xml") {
results() {
contacts.each { contact ->
result(){
name(contact.name)
//Optional id which will be available in onItemSelect
id(contact.id)
}
}
}
}
}
ContactController.groovy
package com.vproc.member
import grails.converters.*
class ContactController {
def springSecurityService
def subscriberService
def imageUploadService
def searchableService
def autoCompleteService
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index() {
redirect(action: "list", params: params)
}
def list() {
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
List<Contact>contactsList = new ArrayList<Contact>();
loggedinSubscriber?.contacts.each { it ->
contactsList.add(it)
}
[contactInstanceList:contactsList , contactInstanceTotal: contactsList.size() ]
}
def create() {
[contactInstance: new Contact(params)]
}
def save() {
// params.birthday = Date.parse( 'MM/dd/yyyy', params.birthday )
if (params.birthday){
params.birthday = (new SimpleDateFormat("MM/dd/yyyy")).parse(params.birthday)
}
def contactInstance = new Contact(params)
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null)
System.out.println("not able to save")
else {
if (!loggedinSubscriber.contacts){
loggedinSubscriber.contacts = new ArrayList<Contact>();
}
loggedinSubscriber.contacts.add(contactInstance)
if (!loggedinSubscriber.save(flush: true)) {
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
render(view: "create", model: [contactInstance: contactInstance])
return
}
}
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "list")
}
// enable search for contacts
def contact_search = {
def query = params.q
if(query){
def srchResults = searchableService.search(query)
render(view: "list",
model: [contactInstanceList: srchResults.results,
contactInstanceTotal:srchResults.total])
}
else{
render "not record found";
}
}
// fetch name from contact table for autocomplete on contact
def searchAJAX = {
def contacts = Contact.findAllByNameLike("%${params.query}%")
//Create XML response
render(contentType: "text/xml") {
results() {
contacts.each { contact ->
result(){
name(contact.name)
//Optional id which will be available in onItemSelect
id(contact.id)
}
}
}
}
}
}
Contact.groovy
package com.vproc.member
import java.util.Date;
import com.vproc.common.Tag;
import com.vproc.enquiry.ContactType;
import grails.converters.JSON;
class Contact {
String name
String phoneNumber
String emailAddress
Gender gender
String url
String note
byte[] image
String address
Date dateCreated
Date lastUpdated
ContactType contactType
Date birthday
static belongsTo = [Subscriber]
static hasMany = [tags:Tag , shares: SharedContact]
static constraints = {
image nullable: true
phoneNumber nullable: true
url nullable :true
address nullable :true
gender nullable :true
note nullable :true
contactType nullable :true
birthday nullable :true
}
static mapping = {
note(type: 'text')
}
//static searchable = [only: ['name', 'emailAddress']]
static searchable = true
static scaffold = true
//static searchable = true
}
Subscriber.groovy
package com.vproc.member
import java.util.Date;
import com.vproc.common.StatusEnum;
import com.vproc.enquiry.Discussion;
import com.vproc.enquiry.Enquiry;
import com.vproc.enquiry.Membership;
import com.vproc.enquiry.Notification;
import com.vproc.enquiry.SharedEnquiry;
import com.vproc.enquiry.Team;
import com.vproc.order.Seat;
class Subscriber extends PartyRole{
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
StatusEnum status
Date dateCreated
Date lastUpdated
List<Contact> contacts ;
static belongsTo = [ customer: Customer]
static hasMany = [seats: Seat, ownedEnquiries: Enquiry,enquiresSharedWith: SharedEnquiry, enquiriesSharedBy: SharedEnquiry ,
managedTeams: Team , memberships: Membership, contacts: Contact , sharedByContacts: SharedContact, sharedWithContacts: SharedContact,
vContacts: VContact, partOf: VContact, sharedbyVContacts: SharedVcontact, sharedWithVcontacts: SharedVcontact,
notifications: Notification, discussions: Discussion]
static mappedBy = [ managedTeams : "manager" , enquiresSharedWith: "sharedWith" , enquiriesSharedBy: "sharedBy" ,
sharedByContacts : "sharedBy" , sharedWithContacts : "sharedWith" ,
vContacts: "forSubscriber" , partOf :"ofContact",
sharedbyVContacts: "sharedby" , sharedWithVcontacts :"sharedWith"
]
static constraints = {
username validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val!= null
}
username unique: true
password validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val != null
}
contacts nullable: true
notifications nullable : true
username nullable: true
password nullable: true
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
SubscriberRole.findAllBySubscriber(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
save action for Contact controller
def save() {
// params.birthday = Date.parse( 'MM/dd/yyyy', params.birthday )
if (params.birthday){
params.birthday = (new SimpleDateFormat("MM/dd/yyyy")).parse(params.birthday)
}
def contactInstance = new Contact(params)
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null)
System.out.println("not able to save")
else {
if (!loggedinSubscriber.contacts){
loggedinSubscriber.contacts = new ArrayList<Contact>();
}
loggedinSubscriber.contacts.add(contactInstance)
if (!loggedinSubscriber.save(flush: true)) {
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
render(view: "create", model: [contactInstance: contactInstance])
return
}
}
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "list")
}
Note: while saving contacts,I have logged in subscriber in save action of Contact controller but I do not know how to use it below method which is searchAjax for searching contacts.

Assuming Subscriber has an association to Contact as,
class Subscriber {
static hasMany = [contacts: Contact]
}
then, to get all contacts for a subscriber user,
subscriberInstance.contacts
and to query among contacts of the same subscriber use,
subscriberInstance.findByContact('your_query_string')
For reference look up querying associations on the documentation http://grails.org/doc/latest/guide/GORM.html#querying

Related

Null Pointer Exception using PlainUsername

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

Spring UI RegisterController - No such property

I am using grails 2.3.4 with ":spring-security-ui:1.0-RC1" and ':spring-security-core:2.0-RC2' plugin. I have configured both plugins in the Config.groovy like that:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.SaaSTemplate.auth.Person'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.SaaSTemplate.auth.PersonRole'
grails.plugin.springsecurity.authority.className = 'com.SaaSTemplate.auth.Role'
//**********************************
// Spring Security UI Settings
//**********************************
//password validation of RegisterController.groovy
grails.plugin.springsecurity.ui.password.validationRegex='^.*(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!##$%^&]).*$' //example: 1Test#!!
grails.plugin.springsecurity.ui.password.minLength=8
grails.plugin.springsecurity.ui.password.maxLength=64
My RegisterController.groovy looks like that:
#Secured(['permitAll'])
class RegisterController extends grails.plugin.springsecurity.ui.RegisterController {
// override default value from base class
static defaultAction = 'index'
// override default value from base class
static allowedMethods = [register: 'POST']
def mailService
def messageSource
def saltSource
def index() {
def copy = [:] + (flash.chainedParams ?: [:])
copy.remove 'controller'
copy.remove 'action'
[command: new RegisterCommand(copy)] // here is where I get the exception!!!!
}
def register(RegisterCommand command) {
if (command.hasErrors()) {
render view: 'index', model: [command: command]
return
}
String salt = saltSource instanceof NullSaltSource ? null : command.username
def user = lookupUserClass().newInstance(email: command.email, username: command.username,
accountLocked: true, enabled: true)
RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt)
if (registrationCode == null || registrationCode.hasErrors()) {
// null means problem creating the user
flash.error = message(code: 'spring.security.ui.register.miscError')
flash.chainedParams = params
redirect action: 'index'
return
}
String url = generateLink('verifyRegistration', [t: registrationCode.token])
def conf = SpringSecurityUtils.securityConfig
def body = conf.ui.register.emailBody
if (body.contains('$')) {
body = evaluate(body, [user: user, url: url])
}
mailService.sendMail {
to command.email
from conf.ui.register.emailFrom
subject conf.ui.register.emailSubject
html body.toString()
}
render view: 'index', model: [emailSent: true]
}
def verifyRegistration() {
def conf = SpringSecurityUtils.securityConfig
String defaultTargetUrl = conf.successHandler.defaultTargetUrl
String token = params.t
def registrationCode = token ? RegistrationCode.findByToken(token) : null
if (!registrationCode) {
flash.error = message(code: 'spring.security.ui.register.badCode')
redirect uri: defaultTargetUrl
return
}
def user
// TODO to ui service
RegistrationCode.withTransaction { status ->
String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
user = lookupUserClass().findWhere((usernameFieldName): registrationCode.username)
if (!user) {
return
}
user.accountLocked = false
user.save(flush:true)
def UserRole = lookupUserRoleClass()
def Role = lookupRoleClass()
for (roleName in conf.ui.register.defaultRoleNames) {
UserRole.create user, Role.findByAuthority(roleName)
}
registrationCode.delete()
}
if (!user) {
flash.error = message(code: 'spring.security.ui.register.badCode')
redirect uri: defaultTargetUrl
return
}
springSecurityService.reauthenticate user.username
flash.message = message(code: 'spring.security.ui.register.complete')
redirect uri: conf.ui.register.postRegisterUrl ?: defaultTargetUrl
}
def forgotPassword() {
if (!request.post) {
// show the form
return
}
String username = params.username
if (!username) {
flash.error = message(code: 'spring.security.ui.forgotPassword.username.missing')
redirect action: 'forgotPassword'
return
}
String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
def user = lookupUserClass().findWhere((usernameFieldName): username)
if (!user) {
flash.error = message(code: 'spring.security.ui.forgotPassword.user.notFound')
redirect action: 'forgotPassword'
return
}
def registrationCode = new RegistrationCode(username: user."$usernameFieldName")
registrationCode.save(flush: true)
String url = generateLink('resetPassword', [t: registrationCode.token])
def conf = SpringSecurityUtils.securityConfig
def body = conf.ui.forgotPassword.emailBody
if (body.contains('$')) {
body = evaluate(body, [user: user, url: url])
}
mailService.sendMail {
to user.email
from conf.ui.forgotPassword.emailFrom
subject conf.ui.forgotPassword.emailSubject
html body.toString()
}
[emailSent: true]
}
def resetPassword(ResetPasswordCommand command) {
String token = params.t
def registrationCode = token ? RegistrationCode.findByToken(token) : null
if (!registrationCode) {
flash.error = message(code: 'spring.security.ui.resetPassword.badCode')
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
return
}
if (!request.post) {
return [token: token, command: new ResetPasswordCommand()]
}
command.username = registrationCode.username
command.validate()
if (command.hasErrors()) {
return [token: token, command: command]
}
String salt = saltSource instanceof NullSaltSource ? null : registrationCode.username
RegistrationCode.withTransaction { status ->
String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
def user = lookupUserClass().findWhere((usernameFieldName): registrationCode.username)
user.password = springSecurityUiService.encodePassword(command.password, salt)
user.save()
registrationCode.delete()
}
springSecurityService.reauthenticate registrationCode.username
flash.message = message(code: 'spring.security.ui.resetPassword.success')
def conf = SpringSecurityUtils.securityConfig
String postResetUrl = conf.ui.register.postResetUrl ?: conf.successHandler.defaultTargetUrl
redirect uri: postResetUrl
}
protected String generateLink(String action, linkParams) {
createLink(base: "$request.scheme://$request.serverName:$request.serverPort$request.contextPath",
controller: 'register', action: action,
params: linkParams)
}
protected String evaluate(s, binding) {
new SimpleTemplateEngine().createTemplate(s).make(binding)
}
// static final passwordValidator = { String password, command ->
// if (command.username && command.username.equals(password)) {
// return 'command.password.error.username'
// }
//
// if (!checkPasswordMinLength(password, command) ||
// !checkPasswordMaxLength(password, command) ||
// !checkPasswordRegex(password, command)) {
// return 'command.password.error.strength'
// }
// }
static boolean checkPasswordMinLength(String password, command) {
def conf = SpringSecurityUtils.securityConfig
int minLength = conf.ui.password.minLength instanceof Number ? conf.ui.password.minLength : 8
password && password.length() >= minLength
}
static boolean checkPasswordMaxLength(String password, command) {
def conf = SpringSecurityUtils.securityConfig
int maxLength = conf.ui.password.maxLength instanceof Number ? conf.ui.password.maxLength : 64
password && password.length() <= maxLength
}
static boolean checkPasswordRegex(String password, command) {
def conf = SpringSecurityUtils.securityConfig
String passValidationRegex = conf.ui.password.validationRegex ?:
'^.*(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!##$%^&]).*$'
password && password.matches(passValidationRegex)
}
// static final password2Validator = { value, command ->
// if (command.password != command.password2) {
// return 'command.password2.error.mismatch'
// }
// }
}
class RegisterCommand {
String username
String email
String password
String password2
def grailsApplication
static constraints = {
username blank: false, validator: { value, command ->
if (value) {
def User = command.grailsApplication.getDomainClass(
SpringSecurityUtils.securityConfig.userLookup.userDomainClassName).clazz
if (User.findByUsername(value)) {
return 'registerCommand.username.unique'
}
}
}
email blank: false, email: true
password blank: false, validator: RegisterController.passwordValidator
password2 validator: RegisterController.password2Validator
}
}
class ResetPasswordCommand {
String username
String password
String password2
static constraints = {
password blank: false, validator: RegisterController.passwordValidator
password2 validator: RegisterController.password2Validator
}
}
As you can see I have just copied the original controller from the source code. Therefore the other classes ResetPasswordCommand and RegisterCommand are also included. However, I still get the exception:
ui.SpringSecurityUiService problem creating Person: com.TestApp.auth.Person : (unsaved)
Die Eigenschaft [firstName] des Typs [class com.TestApp.auth.Person] darf nicht null sein
Die Eigenschaft [lastName] des Typs [class com.TestApp.auth.Person] darf nicht null sein
errors.GrailsExceptionResolver MissingPropertyException occurred when processing request: [GET] /TestApp/register/index
No such property: format for class: TestApp.Register.RegisterCommand. Stacktrace follows:
groovy.lang.MissingPropertyException: No such property: format for class: TestApp.Register.RegisterCommand
at TestApp.Register.RegisterController.index(RegisterController.groovy:26)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
at grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:49)
at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
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:744)
Why do I get this exception? I have included the class RegisterCommand (as also in the original source) in my file?
I really appreciate your input!
UPDATE
I changed my method like that:
def index() {
def copy = [:] + (flash.chainedParams ?: [:])
copy.remove 'controller'
copy.remove 'action'
['controller', 'action', 'format'].each { copy.remove it }
[command: new RegisterCommand(copy)]
}
However, now I still cannot process the registration, I get:
....ui.SpringSecurityUiService problem creating Person: com.TestApp.auth.Person : (unsaved)
The property [firstName] of the type [class com.TestApp.auth.Person] cannot be null
The property [lastName] of the type [class com.TestApp.auth.Person] cannot be null
format is added in the UrlMapping as an optional field.
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
So you would end up removing that from the map as done for action and controller.
//index action
['controller', 'action', 'format'].each { copy.remove it }
Another option will be to explicitly use bindData to avoid this collision
//index action
RegisterCommand cmd = new RegisterCommand()
bindData copy, cmd

Need help in grails model association

I am facing problem with Grails model association. Here is problem:
Subscriber and Customer are extended from PartyRole.
A customer may have many subscribers and a subscriber belongs To customer.
A Party may have many PartyRole.
Person and Organization are extended from Party.
A Person belong to Organization.
A Person has many Profile and a profile belongs to Person.
Now I want to edit currently logged-in user(subscriber) which is basically organization type mean has organization properties like orgName and orgSize.
I can find Person(firstName and lastName) and Profile (emails) details using logged-in user(subscriber) but not able to get Organization details. Code is following.
def profile = {
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null){
redirect(controller: "login" , action:"login");
}
else{
println loggedinSubscriber
Party person = Person?.get(loggedinSubscriber.party.id)
Party org = Organization?.get(loggedinSubscriber.party.id)
Profile profile = person?.profile
[userInstance: person, authorityList: sortedRoles()]
}
}
When I tried to get Organization details with
Party org = Organization?.get(loggedinSubscriber.party.id)
I got null value but in same way I can get Person details using logged-in user(subscriber) and both are extended from Party.`
Any idea to how to get Organization details.
Person:
package com.vproc.member
import com.vproc.enquiry.Enquiry;
import com.vproc.enquiry.Membership;
import com.vproc.enquiry.Notification;
import com.vproc.enquiry.Team;
class Person extends Party{
String firstName
String lastName
Profile profile
static belongsTo = [Organization]
static constraints = {
lastName nullable:true
firstName blank:false
}
}
**Organization:**
package com.vproc.member
import java.util.Date;
class Organization extends Party{
String orgName
Person contact
int orgSize
boolean isVendor
static constraints = {
}
}
Profile:
package com.vproc.member
import java.util.Date;
import com.vproc.enquiry.Enquiry;
import com.vproc.enquiry.Membership;
import com.vproc.enquiry.Team;
class Profile {
String emailAddress // field governed by privacy policy
String phoneNumber // field governed by privacy policy
Date dateCreated
Date lastUpdated
boolean isDefaultProfile
String status
static belongsTo = [person:Person]
//ProfilePrivacyLevelEnum privacyLevel = ProfilePrivacyLevelEnum.Private
static constraints = {
}
}
Subscriber:
package com.vproc.member
import java.util.Date;
import com.vproc.common.StatusEnum;
import com.vproc.enquiry.Discussion;
import com.vproc.enquiry.Enquiry;
import com.vproc.enquiry.Membership;
import com.vproc.enquiry.Notification;
import com.vproc.enquiry.SharedEnquiry;
import com.vproc.enquiry.Team;
import com.vproc.order.Seat;
class Subscriber extends PartyRole{
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
StatusEnum status
Date dateCreated
Date lastUpdated
List<Contact> contacts ;
static belongsTo = [ customer: Customer]
static hasMany = [seats: Seat, ownedEnquiries: Enquiry,enquiresSharedWith: SharedEnquiry, enquiriesSharedBy: SharedEnquiry ,
managedTeams: Team , memberships: Membership, contacts: Contact , sharedByContacts: SharedContact, sharedWithContacts: SharedContact,
vContacts: VContact, partOf: VContact, sharedbyVContacts: SharedVcontact, sharedWithVcontacts: SharedVcontact,
notifications: Notification, discussions: Discussion]
static mappedBy = [ managedTeams : "manager" , enquiresSharedWith: "sharedWith" , enquiriesSharedBy: "sharedBy" ,
sharedByContacts : "sharedBy" , sharedWithContacts : "sharedWith" ,
vContacts: "forSubscriber" , partOf :"ofContact",
sharedbyVContacts: "sharedby" , sharedWithVcontacts :"sharedWith"
]
static constraints = {
username validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val!= null
}
username unique: true
password validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val != null
}
contacts nullable: true
notifications nullable : true
username nullable: true
password nullable: true
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
SubscriberRole.findAllBySubscriber(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
Party:
package com.vproc.member
import java.util.Date;
class Party {
Date dateCreated
Date lastUpdated
static constraints = {
}
static mapping = {
tablePerHierarchy false
}
}
PartyRole:
package com.vproc.member
import java.util.Date;
class PartyRole {
Party party
Date dateCreated
Date lastUpdated
static constraints = {
}
static mapping = {
tablePerHierarchy false
}
}
BootStrap:
class BootStrap {
def init = { servletContext ->
def userRole = Role.findByAuthority('ROLE_USER') ?: new Role(authority: 'ROLE_USER').save(failOnError: true)
def adminRole = Role.findByAuthority('ROLE_COMPANY_ADMIN') ?: new Role(authority: 'ROLE_COMPANY_ADMIN').save(failOnError: true)
def guestRole = Role.findByAuthority('ROLE_GUEST') ?: new Role(authority: 'ROLE_GUEST').save(failOnError: true)
def csrRole = Role.findByAuthority('ROLE_CSR') ?: new Role(authority: 'ROLE_CSR').save(failOnError: true)
//PersonRole.create adminUser, adminRole
def address = new Address( city : 'Pune' , stateCode : 'MH' , countryCode : 'IN' )
def adminProfile = Profile.findByEmailAddress('sachin.jha#gmail.com' )?: new Profile(
privacyLevel: ProfilePrivacyLevelEnum.Private,
emailAddress: "sachin.jha#gmail.com" ,
phoneNumber: "9325507992",
status : 'Active'
).save( failOnError: true)
def adminPerson = Person.findByProfile( adminProfile) ?: new Person( firstName: 'admin' , lastName : 'user' , profile: adminProfile).save( failOnError: true) ;
def vprocOrganization = Organization.findByOrgName('VPROCURE') ?: new Organization ( orgName: 'VPROCURE' , orgSize : 100 , mailingAddress: address, contact: adminPerson ).save( failOnError: true)
def vprocCustomer = Customer.findByParty( vprocOrganization) ?: new Customer ( party: vprocOrganization, status: StatusEnum.Active ).save(failOnError: true) ;
def adminUser = Subscriber.findByUsername('admin') ?: new Subscriber( username : 'admin' , password : 'passw0rd' , enabled: true , party: adminPerson, customer: vprocCustomer , status: StatusEnum.Active ).save( failOnError: true)
if ( !adminUser.authorities.contains(adminRole)){
SubscriberRole.create adminUser, adminRole
}
JSON.registerObjectMarshaller(Date) {
return it?.format("MM/dd/yyyy")
}
def userProfile = Profile.findByEmailAddress( 'sachin.jha.user#gmail.com') ?: new Profile(
privacyLevel: ProfilePrivacyLevelEnum.Private,
emailAddress: "sachin.jha.user#gmail.com",
phoneNumber : "9325507992",
status : 'Active'
).save( failOnError: true)
def userPerson = Person.findByProfile( userProfile) ?: new Person( firstName: 'plain' , lastName : 'user' , profile: userProfile).save( failOnError: true) ;
def plainUser = Subscriber.findByUsername('plainuser') ?: new Subscriber( username: 'plainuser', password : 'passw0rd' , enabled: true , party: userPerson, customer: vprocCustomer , status: StatusEnum.Active ).save( failOnError : true )
if ( !plainUser.authorities.contains(userRole)){
SubscriberRole.create plainUser, userRole
}
/*vprocCustomer.addToSubscribers(amdinUser)
vprocCustomer.addToSubscribers(plainUser)
vprocCustomer.save( failOnError : true);*/
}
def destroy = {
}
}
Just change in Person domain class
static belongsTo = [Organization]
to
static belongsTo = [organization:Organization]
and access organization info from person instance with person.organization

How to get All users which have a certain Role in 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)

Enum constructor calls ara only allowed inside the enum class

I'm working on a grails project. Right now I have a very disturbing problem. I have an enum called Status like this:
enum Status {
ENABLED("Habilitado"), DISABLED ("Desabilitado")
String type
private Status(String type) {
this.type = type
}
def String toString() {
return this.type
}
static list() {
[ENABLED, DISABLED]
}
}
I also have a controller called TesterController, which is where I keep getting errors saying "Enum constructor calls are only allowed inside the enum class" The thing is: I do not call the enum constructor from inside the controller class! Here it is:
class TesterController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index() {
redirect(action: "list", params: params)
}
def list() {
def minElems = 10
if(params.max) minElems = params.int('max')
params.max = Math.min(minElems, 100)
[testers: Tester.list(params), testerTotal: Tester.count()]
}
def create() {
[tester: new Tester(params)]
}
def save() {
def tester = new Tester(params)
if (!tester.save(flush: true)) {
render(view: "create", model: [tester: tester])
return
}
flash.message = message(code: 'ateweb.created.message', args: [tester.name])
redirect(action: "show", id: tester.id)
}
def show() {
def tester = Tester.get(params.id)
if (!tester) {
flash.message = message(code: 'ateweb.not.found.message', args: [message(code: 'tester.label', default: 'Tester'), params.name])
redirect(action: "list")
return
}
[tester: tester]
}
def edit() {
def tester = Tester.get(params.id)
if (!tester) {
flash.message = message(code: 'ateweb.not.found.message', args: [message(code: 'tester.label', default: 'Tester'), params.name])
redirect(action: "list")
return
}
[tester: tester]
}
def update() {
def tester = Tester.get(params.id)
if (!tester) {
flash.message = message(code: 'ateweb.not.found.message', args: [message(code: 'tester.label', default: 'Tester'), params.name])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (tester.version > version) {
tester.errors.rejectValue("version", "ateweb.optimistic.locking.failure",
[message(code: 'tester.label', default: 'Tester')] as Object[],
"Another user has updated this Tester while you were editing")
render(view: "edit", model: [tester: tester])
return
}
}
tester.properties = params
if (!tester.save(flush: true)) {
render(view: "edit", model: [tester: tester])
return
}
flash.message = message(code: 'ateweb.updated.message', args: [tester.name])
redirect(action: "show", id: tester.id)
}
}
Ok. So I am lost with this. Any help is appreciated.
There are a few issues with the definition of your Status class, though I don't know if these are the cause of your problem
enum Status {
ENABLED("Habilitado"), DISABLED ("Desabilitado")
String type
// delcaring the constructor private doesn't make much sense because
// enum constuctors can never be called outside the class
private Status(String type) {
this.type = type
}
// return type is declared as both def (Object) and String
def String toString() {
return this.type
}
// this is identical to the automatically-generated values() method
static list() {
[ENABLED, DISABLED]
}
}
Redefine this class as
enum Status {
ENABLED("Habilitado"), DISABLED ("Desabilitado")
String type
Status(String type) {
this.type = type
}
String toString() {
return this.type
}
}
and use values() instead of the deleted list() method, and maybe your problem will disappear

Resources