grails spring security facebook login error - grails

Have no idea why this happened, it worked two weeks ago. Here is the exception log:
No signature of method: xxxxx.UserInfo.findAllByEmail() is applicable for argument types: () values: []
Possible solutions: findAllByEmail([Ljava.lang.Object;). Stacktrace follows:
groovy.lang.MissingMethodException:
No signature of method: xxxxxx.UserInfo.findAllByEmail() is applicable for argument types: () values: []
Possible solutions: findAllByEmail([Ljava.lang.Object;)
at org.grails.datastore.gorm.GormStaticApi$_methodMissing_closure2.doCall(GormStaticApi.groovy:105)
at xxxxxx.FacebookController.checkEmail(FacebookController.groovy:87)
at xcompare.FacebookController$_closure2.doCall(FacebookController.groovy:49)
at xxxxxxx.OpenIDFilter.doFilter(OpenIDFilter.groovy:64)
at java.lang.Thread.run(Thread.java:662)
this is the code of FacebookController.groovy:
private boolean checkEmail(String email){
def users = UserInfo.findAllByEmail(email)
if(users){
// email is not available
return false;
}
return true;
}
and here is the code from UserInfo:
class UserInfo extends SecUser {
Provider provider
String activationCode
String firstName
String lastName
String email
Boolean active
UserType type
Date dateCreated
Date lastUpdated
Category category
static constraints = {
email unique:true, nullable:true, email:true
provider nullable:true
activationCode nullable:true
firstName blank:true, nullable:true
lastName blank:true, nullable:true
category nullable:true
}
String toString() {
// normal user
if(!openIds){
return username
}
// openid user
String name = "";
if(firstName){
name += firstName;
if(lastName){
name += " "+lastName;
}
}else{
name = email;
}
return name;
}
}

I'm not sure, but maybe it's because email is empty. So try:
private boolean checkEmail(String email){
if (!email) {
//TODO don't think that it's what you want
return true
}
int count = UserInfo.countByEmail(email)
return count == 0
}

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

grails multiple table criteria

My application works for everything except the call to display members of different boards. I can get the correct output in the db with an SQL query but having issues trying it in Grails using createCriteria.
Have to use Oracle 11g as my DB.
Grails 2.3.3
both the DB and Grails are local.
Here are my domains
class Trustee {
String salutation
String firstName
String middleName
String lastName
static hasMany = [board:Boards, membership:TrusteeMembership]
static constraints = {
salutation nullable: true
firstName nullable: true
middleName nullable: true
lastName nullable: true
}
//map to the existing DB table
static mapping = {
table 'BOT_TRUSTEE'
id column:'TRUSTEE_ID'
salutation column: 'SALUTATION'
firstName column: 'FIRST_NAME'
middleName column: 'MIDDLE_INITIAL'
lastName column: 'LAST_NAME'
version false
}
}
class Boards {
String boardName
static belongsTo = [trustee:Trustee, hospital:Hospitals]
static constraints = {
boardName nullable:true
}
static mapping = {
table name:"BOT_BOARD"
id column:'BOARD_ID'
trustee column:'TRUSTEE_ID'
hospital column:'HOSPITAL_ID'
boardName column:'BOARD'
version false
}
}
class Hospitals {
String hospitalName
static hasMany = [committees:Committees, board:Boards]
static constraints = {
hospitalName nullable:true
}
static mapping = {
table 'BOT_HOSPITAL'
id column:'HOSPITAL_ID'
hospitalName column:'HOSPITAL'
version false
}
}
class Committees {
String committeeName
String description
static belongsTo = [hospital: Hospitals]
static hasMany = [membership:TrusteeMembership]
static constraints = {
committeeName nullable:true
description nullable:true
}
static mapping = {
table 'BOT_COMMITTEE'
id column:'COMMITTEE_ID'
hospital column:'HOSPITAL_ID'
committeeName column:'COMMITTEE'
description column:'DESCRIPTION'
version false
}
}
class TrusteeMembership implements Serializable{
String position
String type
static belongsTo = [trustee:Trustee, committees:Committees]//
static constraints = {
position nullable:true
type nullable:true
}
static mapping = {
table 'BOT_TRUSTEE_COMMITTEES'
version false
id composite: ['trustee','committees']
trustee column:'TRUSTEE_ID'
committees column: 'COMMITTEE_ID'
position column:'POSITION'
type column:'TYPE'
}
Here is my controller
def members(){
def letter = params.letter
def commId = params.committee
params.max = Math.min(params.max ? params.int('max'): 15, 100)
def indexSearch = Trustee.createCriteria().list(params){
//search by First letter of lastName
if(letter != null){
ilike("lastName", "${letter}%")
}
//search by lastName
if(params.lastName){
ilike("lastName", "%${params.lastName}%")
}
//search by firstName
if(params.firstName){
ilike("firstName", "%${params.firstName}%")
}
//search by boardName
if(params.boardId){
//display only members within a board id
board{
eq("id", "%${params.boardId}%")
}
}
order("lastName", "asc")
}
respond Hospitals.list(params), model:[hospitalsInstanceCount: Hospitals.count(),
trusteeInstanceList : indexSearch]
}
//search by boardName
if(params.boardId){
//display only members with the boardName
board{
eq("id", params.long('boardId'))
}
}
I ended up with this for the correct result.

Allow empty string for EmailAddressAttribute

I have property in my PersonDTO class:
[EmailAddress]
public string Email { get; set; }
It works fine, except I want to allow empty strings as values for my model, if I send JSON from client side:
{ Email: "" }
I got 400 bad request response and
{"$id":"1","Message":"The Email field is not a valid e-mail address."}
However, it allows omitting email value:
{ FirstName: "First", LastName: 'Last' }
I also tried:
[DataType(DataType.EmailAddress, ErrorMessage = "Email address is not valid")]
but it does not work.
As far as I understood, Data Annotations Extensions pack does not allow empty string either.
Thus, I wonder if there is a way to customize the standard EmailAddressAttribute to allow empty strings so I do not have to write custom validation attribute.
You have two options:
Convert string.Empty to null on the Email field. Many times that is perfectly acceptable. You can make this work globally, or by simply making your setter convert string.Empty to null on the email field.
Write a custom EmailAddress attribute, since EmailAddressAttribute is sealed you can wrap it and write your own forwarding IsValid method.
Sample:
bool IsValid(object value)
{
if (value == string.Empty)
{
return true;
}
else
{
return _wrappedAttribute.IsValid(value);
}
}
Expansion on option 1 (from Web Api not converting json empty strings values to null)
Add this converter:
public class EmptyToNullConverter : JsonConverter
{
private JsonSerializer _stringSerializer = new JsonSerializer();
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
string value = _stringSerializer.Deserialize<string>(reader);
if (string.IsNullOrEmpty(value))
{
value = null;
}
return value;
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
_stringSerializer.Serialize(writer, value);
}
}
and use on the property:
[JsonConverter(typeof(EmptyToNullConverter))]
public string EmailAddress {get; set; }
or globally in WebApiConfig.cs:
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
new EmptyToNullConverter());
It's Easy. Do This. Bye
private string _Email;
[EmailAddress(ErrorMessage = "Ingrese un formato de email vĂ¡lido")]
public string Email { get { return _Email; } set { _Email = string.IsNullOrWhiteSpace(value) ? null : value; } }
I used the suggestion from Yishai Galatzer to make a new ValidationAttribute called EmailAddressThatAllowsBlanks:
namespace System.ComponentModel.DataAnnotations
{
public class EmailAddressThatAllowsBlanks : ValidationAttribute
{
public const string DefaultErrorMessage = "{0} must be a valid email address";
private EmailAddressAttribute _validator = new EmailAddressAttribute();
public EmailAddressThatAllowsBlanks() : base(DefaultErrorMessage)
{
}
public override bool IsValid(object value)
{
if (string.IsNullOrEmpty(value.ToString()))
return true;
return _validator.IsValid(value.ToString());
}
}
}
Set TargetNullValue property of the binding to an empty string.
TargetNullValue=''

grails enum type validation not working as expected

I have a unit test that is failing on a constraint violation, where it should not be. I'm testing if valid enums are set as variables of a domain class.
My Enum:
public enum GenderPreference {
M('Male'),
F('Female'),
A('Any')
final String value
GenderPreference(String value) {
this.value = value
}
public String toString() {
value
}
public String getKey() {
name()
}
public String getValue() {
value
}
}
My domain:
class Profile {
GenderPreference genderPreference
static constraints = {
genderPreference (blank:true, nullable:true)
}
}
My unit test:
works fine:
def instance = new Profile(genderPreference: GenderPreference.M)
assertTrue instance.validate(['genderPreference'])
this should fail but does not. QQQ is not a valid enum
instance = new Profile(genderPreference: 'QQQ')
assertFalse instance.validate(['genderPreference'])
I'm using grails 2.2.4. I think in older versions there was something else that had to be added to the domain constraints for enums, but I thought this should work. What's missing?
You can use inList to add constraints to your enum
static constraints = {
genderPreference blank:true, nullable:true,
inList: GenderPreference.values() as List
}

While Generating controller and view getting error : Can not set int field lms.Book.bookId to java.lang.Class

While generating controller and view for a Domain class as:
class Book {
static constraints = {
bookId blank:false
bookTitle blank:false
}
private int bookId
private String bookTitle
private String author
private double price
private Date edition
private String publisher
}
Giving Error saying :
Can not set int field lms.Book.bookId to java.lang.Class
I think if u add 'private' to field declaration, u have to write getter and setter for this field:
class Book {
static constraints = {
bookId blank:false
bookTitle blank:false
}
private Integer bookId
...
Integer getBookId() { this.bookId }
void setBookId(Integer bookId) { this.bookId = bookId }
....
}
Change "int" to "Integer" (and "double" to "Double" too), e.g.
class Book {
static constraints = {
bookId blank:false
bookTitle blank:false
}
private Integer bookId
private String bookTitle
private String author
private Double price
private Date edition
private String publisher
}
Also, I doubt whether you can have a "blank" constraint on an Integer, change it to:
bookId nullable: false
assuming that is what you want (or remove it altogether, as the nullable: false constraint is implicit).

Resources