populate a dropdown in grails - grails

i have a user that i give a role to it, and i want when i create the user, to show the roles in a dropdown, then i can select the role that i want to give to him, how can i do it ?? please i really need help in it, cause im new in grails here is the user.groovy
class User {
transient securiteService
String username
String password
String nom
String prenom
String email
String tel
static hasMany = [roles : Role]
static constraints = {
username blank: false, unique: true
password blank: false,display: false
nom nullable: true
prenom nullable: true
email email:true, nullable:true
tel nullable:true, maxSize:20, matches:/[\+]{0,1}[0-9\s]{3,15}/
}
static mapping = {
password column: '`password`'
sort nom: "asc"
affectations sort : "dateAffectation", order:"desc"
intervention sort : "responsable", order:"desc"
}
}

The following example will help you, make necessary changes in your code according to your need.
For example you have a table / domain Role
class Role {
String roleId
String roleName // e.g ROLE_ADMIN
}
// Populate the dropdown in your GSP view ( this will populate all the roles present in the Role table)
<g:select from="${Role.list().roleName}" name="selectUserRole"
              optionKey=""
              optionValue=""/>

Related

Convert Sql Query to Grails/Gorm query

How do I convert the following SQL query to Grails/Gorm? Can this be done with a basic query? I would like to avoid using Criteria, Projections and HQL to keep it consistent with the structure of the other queries in my code base (which are basic queries).
SELECT dealer_group_user_dealer_users_id, COUNT(user_id)
FROM db.dealer_group_user_user
GROUP BY dealer_group_user_dealer_users_id;
And is it possible to perform the query in the gsp page to display the result for a specific user_id as opposed to running the query in the controller?
To update from a comment made, below is my domain classes.
class DealerGroupUser extends User{
static hasMany = [dealerUsers: User]
static constraints = {
}
}
class User {
transient authService
Boolean active = true
String firstName
String lastName
String title
String username
String emailAddress
String passwordHash
Date lastLoginTime
Date dateCreated
Date lastUpdated
Retailer dealer
Client client
Date passwordUpdated
Long dealerUser
Boolean isReadOnlyClientManager = false
String regionClientManager
// Transient properties
String fullName
String password
static transients = ['fullName', 'password']
static mapping = {
//permissions fetch: 'join'
sort firstName: 'asc' // TODO: Sort on fullName
}
static hasMany = [roles: Role, permissions: String]
static constraints = {
// NOTE: If a username is not provided, the user's email address will be used
firstName maxSize: 30, blank: false
lastName maxSize: 30, blank: false
title maxSize: 50, blank: false, nullable: true
username blank: false, unique: true
emailAddress email: true, unique: false, blank: false
passwordHash blank: false
lastLoginTime nullable: true
active nullable: true
dealer nullable: true
client nullable: true
passwordUpdated nullable: true
dealerUser nullable: true
regionClientManager nullable: true
}
void setEmailAddress(String emailAddress) {
if (EmailValidator.instance.isValid(emailAddress)) {
this.emailAddress = emailAddress
if (!username) {
username = emailAddress
}
}
}
static namedQueries = {
dealerGroupUsers {
eq 'class', 'com.db.torque.DealerGroupUser'
}
}
Integer setPassword(String plainTextPassword) {
plainTextPassword = plainTextPassword?.trim()
if (plainTextPassword) {
if (!plainTextPassword.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\\S+\$).{8,}\$")){
return -1
}
String previousPassword = this.passwordHash
String newPassword = authService.encrypt(plainTextPassword)
if (previousPassword != newPassword) {
this.passwordHash = newPassword
return 1
}
else {
return -2
}
}
return -1
}
#Transient
public static List<User> findAllByRolesContains(Role role) {
return User.executeQuery("""
SELECT u
FROM User as u
WHERE :role IN elements(u.roles)
""", [role: role])
}
String fullName() {
return "${firstName} ${lastName}"
}
String toString() {
return fullName()
}
}
SELECT dealer_group_user_dealer_users_id, COUNT(user_id)
FROM db.dealer_group_user_user
GROUP BY dealer_group_user_dealer_users_id;
In your user class you have :
Retailer dealer
So lets start from the beginning what is query doing, listing users from user then getting a count of how many times user appears on Retailer domain class ?
The best way to do this would
be
String query = """ select
new map(
u.id as userId,
(select count(d) from DealerGroupUser d left join d.dealerUsers du where du=u) as userCount
)
From user u order by u.id
"""
def results = User.executeQuery(query,[:],[readOnly:true]
This should do what you are doing I think.
And is it possible to perform the query in the gsp page to display the
result for a specific user_id as opposed to running the query in the
controller?
Views are presentation layer and hardcore work should be kept out of it - if needed to use a TagLib call.
Controllers although used in grails examples and rolled out as part of defaults to make things easier also not the best place. You should be doing that in a service which is injected in a controller and presented in view as the actual model of what is needed.
That is the proper way - GSP have a runtime size - keep it short, keep it sweet

How to have multiple One-to-One relationships between three domain classes

As a follow up question to this, I want to have a User domain class which has an optional one-to-one relationship with BasicProfile domain class, User being the owner which may or may not have a profile. I have this part figured out. What I also want is an optional one-to-one relationship between the AcademicProfile domain class and the User, AcademicProfile being the owner, such that an AcademicProfile may or may not have a User. When I try to replicate this the way I did the first one-to-one relationship, it does not work. Here are my classes.
class User {
String username
String password
String email
AcademicProfile academicProfile
Date dateCreated
Date lastUpdated
static hasOne = [basicProfile: BasicProfile]
static constraints = {
username size: 3..20, unique: true, nullable: false, validator: { _username ->
_username.toLowerCase() == _username
}
password size: 6..100, nullable: false, validator: { _password, user ->
_password != user.username
}
email email: true, blank: false
basicProfile nullable: true
}
}
class BasicProfile extends Profile {
User user
Date dateCreated
Date lastUpdated
}
class AcademicProfile extends Profile {
String dblpId
String scholarId
String website
Date dateCreated
Date lastUpdated
static hasOne = [user: User]
static hasMany = [publications: Publication]
static constraints = {
dblpId nullable: true
scholarId nullable: true
website nullable: true, url: true
publications nullable: true
user nullable: true
}
}
class Profile {
String firstName
String middleName
String lastName
byte[] photo
String bio
static constraints = {
firstName blank: false
middleName nullable: true
lastName blank: false
photo nullable: true, maxSize: 2 * 1024**2
bio nullable: true, maxSize: 500
}
static mapping = {
tablePerSubclass true
}
}
When I run it, I get the error: Field error in object 'org.academic.User' on field 'academicProfile': rejected value [null];. I don't understand what I am doing wrong.
You'll have to add nullable:true constraint for AcademicProfile academicProfile in User class as you mentioned that you need an 'optional' relationship between AcademicProfile & User.
The error itself is self explanatory though, that you can't create a User class's instance, without providing the academicProfile property a non-null value.

Grails BootStrap: No signature of method: *.addTo* applicable

I have two domain classes: User
class User {
String username
String password
String email
Date dateCreated
Date lastUpdated
// static belongsTo = [profile: Profile]
static constraints = {
username size: 3..20, unique: true, nullable: false, validator: { _username ->
_username.toLowerCase() == _username
}
password size: 6..100, nullable: false, validator: { _password, user ->
_password != user.username
}
email email: true, blank: false
// profile nullable: true
}
}
and Profile:
class Profile {
String firstName
String middleName
String lastName
byte[] photo
Date dateCreated
Date lastUpdated
static belongsTo = [User]
static constraints = {
firstName blank: false
middleName nullable: true
lastName blank: false
photo nullable: true, maxSize: 2 * 1024**2
}
}
A profile can belong to only one user and a user can have (or belong to?) only one profile. When I try to create the objects in BootStrap.groovy in the current setup I get an error saying that the addTo() method does not exist. I don't really know what I am doing wrong. This is how I am creating them in BootStrap.groovy:
User arun = new User(username: 'arun', password: 'password', email: 'arun#email.com').save(failOnError: true)
Profile arunProfile = new Profile(firstName: 'Arun', lastName: 'Allamsetty').addToUser(arun).save(failOnError: true)
Can someone please point out the mistake(s). I am sure it's silly.
A strict bi-directional one-one relationship is required as you have requested for:
A profile can belong to only one user and a user can have (or belong to?) only one profile
Three modifications are mainly required in domain classes:
//User.groovy
static hasOne = [profile: Profile]
static constraints = {
profile unique: true
}
//Profile.groovy
User user
Above is a bi-directianl one-one relationship. You do not need addTo* anymore while creating each of them.
Profile arunProfile = new Profile(firstName: 'Arun', lastName: 'Allamsetty')
User arun = new User(username: 'arun', password: 'password',
email: 'arun#email.com',
profile: arunProfile).save()

Grails: How to create formula on an embedded class

When I create a general class to embed it to other class, I want to add a transient property which is defined by a formula, but I do not how to implement this. Here is my source code:
//Embedded
class LocationInfo {
Long country, state, city
String address, fullAddress
static constraints = {
country nullable: true
state nullable: true
city nullable: true
address nullable: true
}
static mapping = {
country column: 'l_country'
state column: 'l_state'
city column: 'l_city'
address column: 'l_address'
fullAddress formula: "SELECT (l_address || ', ' || city.name) FROM system_location city WHERE city.id = l_city"
}
static transients = ['fullAddress']
}
class SystemLocation {
String name
Long parentLocationId
String level
static constraints = {
name blank: false, maxSize: 100
parentLocationId nullable: true
level inList: ['country', 'state', 'city']
}
static mapping = { version false }
}
//Host
class User {
String email
String password
String firstName
String lastName
Team team
UserLevel userLevel
boolean enabled = true
boolean accountExpired = false
boolean accountLocked = false
boolean passwordExpired = false
boolean teamLeader = false
LocationInfo locationInfo
AuditingInfo auditingInfo
static embedded = ['locationInfo', 'auditingInfo']
transient springSecurityService
static constraints = {
email blank: false, unique: true, maxSize: 200
password blank: false, maxSize: 200
firstName blank: false
lastName blank: false
team nullable: true
teamLeader nullable: true
locationInfo nullable: true
auditingInfo nullable: true
}
static mapping = {
team column: "team_id"
userLevel column: "user_level_id"
}
}
The LocationInfo is embedded to User class, nhưng when I get a specific user by ID and check the value in user.locationInfo.fullAddress, it is always NULL; and the generated SQL does not contains the "SELECT (l_address || ', ' || city.name)..." statement.
I do not know how to use a formula in an embedded class.
Could you please help me solve this?
According to the Grails manual there is no such thing like formula in the mapping settings.
I'd solve this by simply declaring a getter method on your domain class:
class LocationInfo {
Long country, state,
SystemLocation city
String address // n.b. no longAddress here
static constraints = {
country nullable: true
state nullable: true
city nullable: true
address nullable: true
}
static mapping = {
country column: 'l_country'
state column: 'l_state'
address column: 'l_address'
}
static transients = ['fullAddress']
String getFullAddress() {
"$address $city.name"
}
}
N.B. that city is now a reference to another domain class. In your draft this is just an id which makes your domain model hard to navigate.
I also had this problem and I think you can't do this that way.
When you define formula for some derived property, you have to put SQL with names of columns you know. But when this class is used in embedded property column names of that embedded object are changed.
In your case table User has columns location_info_l_city, location_info_l_address. But in formula you used names like l_city, l_address... There is no such column in table User.
I resolved the problem by adding derived property for embedded object's owner.
In your case I would add to class User mapping:
class User {
//...
String fullAddress
//...
static mapping = {
//...
fullAddress formula: "SELECT (location_info_l_address || ', ' || city.name) FROM system_location city WHERE city.id = location_info_l_city"
}
}
Now, you can use column User.fullAddress also in HQL queries.

Grails Logged in username owns created record

I'm sure this has to be one of the most common things done in programming, that is how to associate a certain form submission with a certain logged in user.
I've been trying for quite some time and I just end up running in circles and getting error after error.
My question is, what is the correct way to have a user own the record they submitted?
I've tried many options, unsuccessfully. :\ I even tried the less secure method of creating a String field and inserting the current user in a hidden field in the gsp and that even didn't work right.
static belongsTo = User
in the domain class, great but that only lets me see it in the User form.
Maybe the problem is how it scaffolds. Generate Controllers, Generate Views do a great generic list for ALL records. I need this list to only show THEIR records. but then additionally I need my admins to see ALL records.
Can anyone help point me in the right direction?
SalesOrderController.groovy
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
def list(Integer max) {
params.max = Math.min(params.max ? params.max.toInteger() : 10, 100)
[salesOrderInstanceList: SalesOrder.list(params), salesOrderInstanceTotal: SalesOrder.count()]
// def user = params.id ? SecUser.findByUsername(params.id) : SecUser.get(springSecurityService.principal.id)
// [salesOrderInstanceList: SalesOrder.findAllBySoldBy(user), salesOrderInstanceTotal: SalesOrder.count()]
// if (!user) {
// response.sendError(404)
// return
// }
}
class SalesOrder {
static searchable = {
user(component:true)
}
enum JobStatus {
PENDING, APPROVED, COMPLETE
}
enum JobType {
INSTALL, REPAIR, WARRANTY, TINT
}
enum PaymentType {
INSURANCE, CASH
}
enum InstallLocation {
INSHOP, HOME, BUSINESS
}
enum InstallTime {
MORNING, MIDDAY, AFTERNOON
}
JobStatus jobStatus
JobType jobType
PaymentType paymentType
String custFirstName
String custLastName
String custBestNumber
String custAlternateNumber
String custEmail
String custAddress
String custAddress2
String custCity
String custState
String custZip
String vehicleYear
String vehicleMake
String vehicleModel
String vehicleVin
static hasMany = [glassTypes: GlassType, options: GlassOption]
Date insuranceDateOfLoss
String insuranceCompany
String insurancePolicyNumber
String insuranceClaimNumber
String insuranceDeductible
Date installDate
InstallTime installTime
InstallLocation installLocation
String installCrossStreet1
String installCrossStreet2
String installAddress
String installCity
String notes
Date dateCreated
String soldBy
static constraints = {
jobType blank: false
custFirstName blank: false
custLastName blank: false
custBestNumber blank: false, size:10..10
custAlternateNumber nullable: true, sizeMax: 10
custEmail blank: false, email: true
custAddress blank: false
custAddress2 nullable: true
custCity blank: false
custState blank: false, size: 2..2
custZip blank:false, size: 5..5
vehicleYear blank: false, size:4..4
vehicleMake blank: false
vehicleModel blank: false
vehicleVin blank: false, size:17..17
glassTypes blank: false
options blank: false
insuranceDateOfLoss nullable: true
insuranceCompany nullable: true
insurancePolicyNumber nullable: true
insuranceClaimNumber nullable: true
insuranceDeductible nullable: true
installDate blank: false
installTime blank: false
installLocation blank: false
installCrossStreet1 blank: false
installCrossStreet2 blank: false
installAddress nullable: true
installCity nullable: true
paymentType blank: false
jobStatus blank: false
notes nullable: true, size:0..1024
soldBy blank: false
}
static belongsTo = SecUser
}
<div class="fieldcontain ${hasErrors(bean: salesOrderInstance, field: 'soldBy', 'error')} required">
<label for="soldBy">
<g:message code="salesOrder.soldBy.label" default="Sold By" />
</label>
<g:textField name="soldBy" value="${salesOrderInstance?.soldBy}" default="${sec.loggedInUserInfo(field:'username')}" />
<sec:loggedInUserInfo field="username"></sec:loggedInUserInfo>
I tried following an example where it uses a Service, but that just left me lost as the example only required one field to be passed. as you can see i have more than one, and some many to one joins. Left me with more questions than answers.
Regarding the question of user's seeing their own data vs an admin seeing everyone's data, see my answer to a similar question here.
As far as associating users to their own data...if the data should belong to a user, simply associate the User domain to said data, as you have already done, but with a slight modification:
class SalesOrder {
static belongsTo = [secUser : SecUser]
}
And then add the appropriate mapping to your SecUser class:
class SecUser {
static hasMany = [salesOrders : SalesOrder]
}
Then, when you post the data to the server:
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
def save() {
def authenticatedUser = SecUser.findByUsername(springSecurityService.principal.username)
def salesOrder = new SalesOrder(params)
// this assumes you're SecUser and SalesOrder are a 1-to-many bidirectional association
authenticatedUser.addToSalesOrders(salesOrder)
authenticatedUser.save()
}
There's no need store the info in a hidden field since the same data is available in the controller. Scaffolding is a great way to get started with a proof of concept. However, I never use scaffolding anymore.

Resources