Assign authority to a user without user input when updating user profile - grails

I've created a form that a user updates to update his profile. When I update the details of the user, and I log out and log in again, I get access denied. I found out that the reason for this was with the authority, every time I updated the table, other details were saved, but the authority is lost and as a result, access is denied.
So I would like to assign the role again within the form but without the user having any input. Any advise on how to implement that is appreciated.
below is my gsp;
<div class="form-group">
<label class="col-sm-5 control-label">
Roles
</label>
<div class="col-sm-5 ">
<g:each in="${roles}" var="role" status="i">
<div class="checkbox-inline">
<g:checkBox name="roles" value="${role.id}"
checked="${role.authority == "ROLE_MEMBER" ? 'true': user.hasRole(role)}"/>
<label for="roles[${i}]">${role.authority}</label>
</div>
</g:each>
</div>
</div>
<div class="form-group">
<div class="${hasErrors(bean: user, field: 'natureOfIndividual', 'error')} required">
<label for="natureOfIndividual" class="col-sm-5 control-label">
<g:message code="user.natureOfIndividual.label" default="Nature of Individual"/>
</label>
<div class="col-sm-5">
<g:select name="natureOfIndividual"
from="${['Local', 'Foreign']}"
class="form-control" noSelection="['': '-----Select-----']"
value="${user?.natureOfIndividual}"/>
</div>
</div>
</div>
With this code am not able to see the checkboxes. Still finding out why. But ultimately, I don't want the user to see any checkboxes, I want to assign the authority without his/her input.
I got a solution. In my UserController.groovy, there was updateRoles method that was called in update method. I commented out the method call. And now the roles are not affected after an update. Below is the code;
#Transactional
def update(User user) {
if (user == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (user.hasErrors()) {
transactionStatus.setRollbackOnly()
respond user.errors, view: 'edit'
return
}
boolean passChange = false
if (user.isDirty('password')) {
passChange = true
}
user.save flush: true
//updateRoles(user)
request.withFormat {
form multipartForm {
if (passChange) {
flash.message = "A user with username '${params.username}' and password '${params.password}' has been Updated"
} else {
flash.message = "Your profile has been updated"
}
redirect user
}
'*' { respond user, [status: OK] }
}
}
private updateRoles(User user) {
UserRole.removeAll(user)
List roleIds = params.roles instanceof String ? [params.roles] : params.roles
roleIds?.each { roleId ->
def role = Role.get(roleId)
UserRole.create(user, role, true)
}
}
As you've seen, I have commented out the method call in the update method. So when users update their details, their authorization is still preserved.

Related

Trying to access html element in a view from controller in mvc

I am trying to access html element of a view from Controller in asp.net Mvc.
In login form after filling data in username and password textbox. Posting it through Http Post and accessing it in controller and now based on condition in controller i want to manipulate html element in same view from where it is getting data.
view
<span id="spanInvalidCredentialsMessage" style="display:none">
<div class="row form-group">
<div class="col-md-8 col-md-offset-2 text-danger">
Your credentials could not be authenticated. Please try again.
</div>
</div>
<div class="row form-group">
<div class="col-md-8 col-md-offset-2">
<hr class="alert-danger" />
</div>
</div>
</span>
login form field in view
<div class="col-md-8 col-md-offset-2">
<span class="glyphicon glyphicon-user text-primary">
</span>Username
</div>
<div class="col-md-8 col-md-offset-2">
#Html.TextBox("txtBxUsername", null, new { #class = "form-control" })
#Html.TextBox("txtBxPassword", null, new { #class = "form-control" })
<input id="btnLogin" type="submit" value="Login" class="btn btn-primary btn-block" />
</div>
Controller section getting login details through httppost
[HttpPost]
public ActionResult Login(FormCollection form)
{
//Invoke the method to authenticate the user credentials. txtBxUsername.Text.Trim().ToUpper()
string msgUserAuthenticated=objADService.GenericIsAuthenticatedWithMessage("ABC", form["txtBxUsername"].ToString().Trim().ToUpper(),form["txtBxPassword"].ToString());
//Check if the user was authenticated.
if (msgUserAuthenticated.Equals("Authenticated", StringComparison.InvariantCultureIgnoreCase) == true)
{
//Set the Session Variable and Redirect to the Home Page ASPX.
Session[CommonConstants.SESSION_USER_ID] = form["txtBxUsername"].ToString().Trim().ToUpper();
Session[CommonConstants.SESSION_USER_DOMAIN] = form["txtBxPassword"].ToString();
//Redirect the user to the home page
//Response.Redirect("Home.aspx");
return View("Home");
}
else
{
//Show the error message.
spanInvalidCredentialsMessage.Visible = true;
//Clear the text boxes for Username and Password.
txtBxUsername.Text = "";
txtBxPassword.Text = "";
return View("Login");
}
}
Expected if wrong username & password would be there then in controller i can access html element id in view and display it.
actual
no idea how to achieve

g:select save to database selected item in grails

I have tables: Products and Shop.(I generate controllers using grails generate-all) Shop hasmany products
I'm trying to do is List all the shops in and save to database selected shop when creating a new product.
I listed all values using
<g:form controller="product" action="save" role="form">
<div class="form-horizontal" role="form">
<div class="form-group">
<label class="col-lg-3 control-label">Product Name:</label>
<div class="col-lg-8">
<g:textField name="productName" class="form-control" value="${product.productName}"/>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Product Barcode</label>
<div class="col-lg-8">
<g:textField name="date expired" class="form-control" value="${product.productBarcode}"></g:textField>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Product Shop</label>
<g:select class="selectpicker" name="products.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="shop?.products.id" optionValue="shopName"></g:select>
</div>
</g:form>
when i click create button it says
Property [shop] of class [class tr.com.nur.storeapp.Product] cannot be null
This bit doesn't look right:
<g:select class="selectpicker" name="products.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="shop?.products.id" optionValue="shopName"></g:select>
The name should be the id of the Shop and the value should be the product's shop id, if present:
<g:select class="selectpicker" name="shop.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="${product?.shop?.id}" optionValue="shopName"></g:select>
#Transactional
def save(Shop shop) {
//println "in shop save"
def currentUser=(User)springSecurityService.currentUser
shop.user=currentUser
shop.validate()
if (!shop) {
//println "I have no shop"
transactionStatus.setRollbackOnly()
notFound()
return
}
//if (shop.hasErrors()) {
if (shop.save(flush:true)) {
//println "shop has errors"
transactionStatus.setRollbackOnly()
respond shop.errors, view:'create'
shop.errors.allErrors
return
}
//shop.save flush:true
//println "shop has saved"
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'shop.label', default: 'Shop'), shop.id])
//println "redirecting"
redirect shop
}
'*' { respond shop, [status: CREATED] }
}
}
This is my save method. Actuaally I didint write anything here. Generate domain .

Insert into Database Groovy Grails

I'm a new developer for groovy grails and I have a table named user under the database test.
I succeed to login to that database by using grails but I couldn't succeed to register the new user.
Here is my register.gsp
<g:form controller="user" action="registration">
<fieldset class="form">
<div class="fieldcontation ${hasErrors(bean: userInstance, field: 'fullName', 'error')}">
<label for="fullName">
<g:message code="endUser.fullName.label" default="Full Name" />
</label>
<g:textField name="fullName" value="${userInstance?.fullName}"/>
</div>
<div class="fieldcontation ${hasErrors(bean: userInstance, field: 'userName', 'error')}">
<label for="userName">
<g:message code="endUser.userName.label" default="User Name" />
</label>
<g:textField name="userName" value="${userInstance?.userName}"/>
</div>
<div class="fieldcontain ${hasErrors(bean: userInstance, field: 'password', 'error')} ">
<label for="password">
<g:message code="endUser.password.label" default="Password"/>
</label>
<g:field type="password" name="password" value="${userInstance?.password}"/>
</div>
</fieldset>
<fieldset class="buttons">
<g:submitButton name="register" class="save" value="Register" />
</fieldset>
</g:form>
here is my UserController.groovy
package test
import java.sql.SQLClientInfoException;
import javax.activation.DataSource;
import grails.converters.JSON
class UserController {
def index() {
redirect(action:"login")
}
def register = {}
def login = {}
def registration = {
def b = new User(fullName:params.fullName, userName:params.userName, password:params.password)
b.save()
render (b as JSON)
}
def authenticate = {
def user = User.findByUserNameAndPassword(params.userName, params.password)
if (user){
def userMap = [:]
userMap.put("login", "true")
userMap.put("name", user.fullName)
userMap.put("password", user.password)
render (userMap as JSON)
}else{
flash.message = "Sorry, ${params.userName}, Please try again."
redirect(action:"login")
}
}
def logout = {
flash.message = "Goodbye ${session.user.fullName}"
session.user = null
redirect(action:"login")
}
}
After this method , I had this error
http://postimg.org/image/gbitzsokp/
But I couldn't understand what it tried to say
here is my DataSource.groovy
dataSource {
pooled = true
jmxExport = true
driverClassName = "com.mysql.jdbc.Driver"
username = "admin"
password = "admin"
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
cache.provider_class='net.sf.ehcache.hibernate.EhCacheProvider'
}
// environment specific settings
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
url = "jdbc:mysql://localhost:3306/test"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:mysql://localhost:3306/test"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:mysql://localhost:3306/test"
}
}
}
My domain class User.groovy
package test
class User {
String userName
String password
String fullName
String toString(){
"${fullName}"
}
static constraints = {
fullName()
userName(unique: true)
//password(password=true)
}
}
Plug-in's
plugins {
build ":tomcat:7.0.55"
compile ":scaffolding:2.1.2"
compile ':cache:1.1.8'
compile ":asset-pipeline:1.9.9"
compile ":simpledb:0.5"
runtime ":hibernate4:4.3.6.1" // or ":hibernate:3.6.10.18"
runtime ":database-migration:1.4.0"
runtime ":jquery:1.11.1"
}
I can immediately assure every information you need
Thank you
My Grails version is 2.4.4
As #saw303 mentioned, GORM provides what you're looking for. So there's no need to write SQL statements.
Workflow
I'm assuming the workflow you need is something like this:
The register action renders register.gsp, the registration form.
When the registration form is submitted the registration action handles the request. If all goes well, the user is set in the session scope and the browser is redirected somewhere, such as the home page. Otherwise, the browser is redirected to the register action and the validation errors are displayed in the registration form.
Here's how to create such a workflow.
Registration action
Begin by making a number of changes to the registration action.
import grails.transaction.Transactional
class UserController {
// NOTE: Making the method Transactional avoids having to flush saves.
#Transactional
def registration() {
def user = new User(params).save()
if(user.hasErrors()) {
/*
* On failure, redirect back to registration form,
* and pass the User instance to the GSP page in the
* flash scope so that validation errors can be rendered.
*/
flash.userInstance = user
redirect action: 'register'
} else {
/* On success, place User instance in session scope,
* and redirect to home page.
*/
session.user = user
redirect uri: '/'
}
}
}
I added the Transactional annotation so the flushing of GORM saves are handled automatically.
registration is now a method instead of a Closure. It's the new way.
register.gsp
To render the validation errors in the registration form, change the hasErrors() calls from bean: userInstance to model: flash?.userInstance For example, for the fullName property, do ${hasErrors(model: flash?.userInstance, field: 'fullName', 'error')}

whole page gets refresh instead of div on login action

I have 1 home page on which I have one anchor tag that is Login. On click, the Login anchor tag opens one pop up on the same home page like shown in the image below:
Now I want to perform the login action when the sign in button is clicked but only this pop up portion should get refresh and not the whole home page.
Currently, what is happening is my whole home page gets refreshed when the user enters the wrong EmailId or Password.
This is my View:
<div id="loginBox">
#using (Html.BeginForm("Login", "Account", FormMethod.Post, new { id = "loginForm" }))
{
<fieldset id="body">
<fieldset>
<label for="email">Email Address</label>
#Html.TextBox("Email", null, new { name = "email", id = "email" })
</fieldset>
<fieldset>
<label for="password">Password</label>
#Html.Password("Password", null, new { name = "password", id = "password" })
</fieldset>
<input onclick="Login()" type="submit" id="login" value="Sign in">
<label for="checkbox">
<input type="checkbox" id="checkbox">
<i>Remember me</i>
</label>
</fieldset>
}
</div>
This is my Login Javascript method to post my form and call controller method:
function Login() {
alert("ok");
var email = $("#email").val();
var password = $("#password").val();
$.post("/Account/Login", { Email: email, Password: password },
function (data) {
if (data == true) {
$("#LoginErrorMsg").hide();
} else {
$("#LoginErrorMsg").show();
}
});
}
Controller:
public JsonResult Login(string Email, string Password)
{
//Logic for login action
if(Emailid && Password is correct)
return Json(true);
else
return Json(false);
}
But here the problem is my controller method is not calling and when it is calling the whole page gets refresh even if the password is incorrect.
So can anybody help me?

How to prevent saving of duplicate data?

I am developing MVC app.
I am using Jquery in Creat-Veiw for validate the data.
I am adding the Role and checking whether that Role(or you can say UserName) already exists in DB or not.
If Role already exists then validation message should display and should not be allow to add in db (should not allow to save).
I have a text-box which accepts the Role, on the blur function I have checked whether Role already exists or not.
Every thing working ok, If Role already exists then validation message comes up.
But after clicking on save button it saves in db.
I want to prevent it ? How to do this ?
I have below code of Create View.
#model IEnumerable<PaymentAdviceEntity.Role>
<div id="roleList">
<div class="span6">
<div class="span12 HeaderField2">
Roles
<legend style="margin-bottom:2px;margin-top:5px;"></legend>
</div>
<div class="span12">
<div style="display:inline-block"></div>
<div id="addrole" style="display:none">
<span> #Html.TextBox("RoleName", String.Empty, new { #id = "RoleName",style="margin-bottom:0px;" })</span>
<span>
<input type="button" value="Save" id="btnSave"/>
<input type="button" value="Cancel" id="btnCancel" />
</span>
</div>
<div style="margin-top:5px;">
<span id="RoleNameValidation" style="display:none;color:Red;">Role already exists</span>
</div>
</div>
</div>
For this I am using the below Jquery.
$("#RoleName").blur(function ()
{
var Role_Name = $('#RoleName').val();
//alert(RoleName);
var url = "#Html.Raw(Url.Action("checkForUniqueName","Role",new {#RName = "RoleName"}))";
url = url.replace("RoleName", Role_Name);
$.post(url, function (data)
{
if (data == false) {
$("#RoleNameValidation").show();
$('#RoleName').focus();
}
else {
$("#RoleNameValidation").hide()
}
});
});
and the controller Code is....
public ActionResult checkForUniqueName(string RName)
{
bool Valid = false;
var RoleList = from e in db.Roles
where e.Name.Equals(RName)
select e;
if (RoleList.Count() > 0 )
{
Valid = false;
}
else
{
Valid = true;
}
return Json(Valid, JsonRequestBehavior.AllowGet);
}
You can use validation for this purpose if you don't want to insert duplicate records in database.
Try to create a custom rule using the jQuery Validate plugin (using addMethod) that checks if the role is already exists in database.You can find good help at http://matthewmuro.com/2012/05/08/adding-custom-jquery-validation-to-your-form/

Resources