Grails Command Objects custom Validate Message Codes - validation

When using command objects like:
class UserCommand {
String name
static constraints = {
name blank: false, unique: true, minSize: 3
}
}
you can use them to validate objects without making them persistent. In my case I would validate for a persistent class User.
In controller:
def save(UserCommand cmd) {
if(!cmd.validate()) {
render view: "create", model: [user: cmd]
return
}
def user = new User()
user.name = cmd.name
user.save()
redirect uri: '/'
}
in messages.properties:
user.username.minSize.error=Please enter at least three characters.
userCommand.username.minSize.error=Please enter at least three characters.
When using custom validation messages you have to write the message codes for each error twice. One for the User class and another for the UserCommand class.
Is there a way how I can have only one message code for each error?

I might be wrong here but if you're using just the stock Grails constraints, the only way to share a validation message is to simply rely on the default.x.x.message key/values in messages.properties. Otherwise messages are looked up via the following key form:
className.propertyName.errorcode...=
You can however use a custom validator and override what message key gets returned for the validation error.
class User {
...
static constraints = {
...
name blank: false, unique: true, validator: { value, user ->
if(!value || value.length() < 3)
return 'what.ever.key.in.messages.properties'
}
}
}
Then you can keep it all DRY by sharing constraints between classes via a global constraint or as #dmahapatro mentioned, with the use of an importFrom in your UserCommand like so,
class UserCommand {
...
static constraints = {
importFrom User
...
}
}
If you have more complicated validation, you can create your own constraints classes. Here are some resources:
http://www.zorched.net/2008/01/25/build-a-custom-validator-in-grails-with-a-plugin/
http://blog.swwomm.com/2011/02/custom-grails-constraints.html

using unique constraint in CommandObject makes no sense, because uniqueness of what would it check?
you can validate domain objects without persisting them exactly the same way as command objects - using validate() method
you can put a User object in command object, set constraints only for the domain class, and then validate User object being a part of command object
class User {
String name
static constraints = {
name blank: false, unique: true, minSize: 3
}
}
class UserCommand {
User user
static constraints = {
user validator: { it.validate() }
}
}
user.username.minSize.error=Please enter at least three characters.

Related

GraphQL define implicitly what a user can do

I'm using Laravel Lighthouse.
Following situation:
I have users, and those users should be allowed to access different datasets and run different mutations.
My solution:
The users are assigned roles, and those roles define what datasets the user can access and what mutations can be run.
I'm stuck at the implementation. What I could do is to write down all my Queries and Mutations in my schema, and have policies to restrict access to them.
What I would prefer is to have a way to see from the schema which role has access to what.
My idea:
Have a type for each role, and in that type associate what data can be accessed and what mutations can be run
Here's some example code that might explain what I'm going for, even though the syntax is probably invalid:
type Query {
me: User #auth
}
type User {
id: ID
username: String
first_name: String
wage: Float
password: String
roles: [Role]
role(name: String! #eq): Role #find
}
type Role {
id: ID
name: String
}
type AdminRole {
#set of users whose data the admin has access to
#also directly restrict the amount of attributes that are accessible (e.g. password is not accessible)
#this is invalid syntax, I know
users: [Users] #all {
id
first_name
wage
}
#a mutation the admin has access to
updateUser(id: ID!, wage: Float): User #update
}
What query I'd like to run for the admin to get all wages:
query {
me {
role(name: "AdminRole") {
users {
wage
}
}
}
}
What mutation I'd like to run for the admin to update a user's wage:
mutation {
me {
role(name: "AdminRole") {
updateUser(id: 7, wage: 10.00) {
id
wage
}
}
}
}
So instead of writing policies that restrict access to things, I'd rather just have everything defined implicitly in the schema. This would make defining and answering "What can an admin do?" more intuitive and easier to comprehend, because it's written down in a single spot, rather than several policies.
I assume this is not possible in the way I described above. What's the closest thing to it? Or are there issues with this approach?
What about #can directive? You can use it on query, input or field. With little modifying can be able to set role instead of permission.
Second idea is serving other schema to different authenticated users based on roles.
Take a look at my answer here: https://stackoverflow.com/a/63405046/2397915
I describe there two different approaches for different goals. At the end these two are allowing me to restrict every part of my schema how I want. Works perfectly in role-based setup
At the end I wrote a custom directive, similar to what lorado mentioned, but a tad more simple:
<?php
namespace App\GraphQL\Directives;
use Closure;
use GraphQL\Language\AST\TypeExtensionNode;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Exceptions\AuthorizationException;
use Nuwave\Lighthouse\Exceptions\DefinitionException;
use Nuwave\Lighthouse\Schema\AST\ASTHelper;
use Nuwave\Lighthouse\Schema\AST\DocumentAST;
use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\FieldMiddleware;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use Nuwave\Lighthouse\Support\Contracts\TypeExtensionManipulator;
class RestrictDirective extends BaseDirective implements FieldMiddleware, TypeExtensionManipulator {
public function name() {
return "restrict";
}
public static function definition(): string {
return /** #lang GraphQL */ <<<'SDL'
directive #restrict(
roles: Mixed!
) on FIELD_DEFINITION | OBJECT
SDL;
}
public function handleField(FieldValue $fieldValue, Closure $next): FieldValue {
$resolver = $fieldValue->getResolver();
$fieldValue->setResolver(function ($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) use ($resolver) {
//get the passed rights
$rights = $this->directiveArgValue("rights");
if ($rights === null) throw new DefinitionException("Missing argument 'rights' for directive '#restrict'.");
//allow both a single string and an array as input
if (!is_array($rights)) $rights = [$rights];
//current user, must be logged in
$user = $context->user();
if (!$user) $this->no();
//returns an array of strings
$user_rights = $user->getAllRightNames();
//this is the part where we check whether the user has the rights or not
if (empty(array_intersect($user_rights, $rights))) $this->no();
return $resolver($root, $args, $context, $resolveInfo);
});
return $next($fieldValue);
}
public function no() {
throw new AuthorizationException("You are not authorized to access {$this->nodeName()}");
}
public function manipulateTypeExtension(DocumentAST &$documentAST, TypeExtensionNode &$typeExtension) {
ASTHelper::addDirectiveToFields($this->directiveNode, $typeExtension);
}
}
used as such:
type User {
id: ID!
username: String
extraPayments: [ExtraPayment] #restrict(rights: ["baseWorkingTime", "someOtherRight"])
}
#how to easily restrict a subset of attributes
extend type User #restrict(rights: "baseWorkingTime") {
wage: Float
password: String
}
Here, extraPayments are restricted to someone having at least one of the two rights. A whole set of attributes is restricted by restricting an extension.
Mutations are restricted the same way, if so desired:
type Mutation {
test: String #restrict(rights: "baseWorkingTime")
}

How to Creating a Custom Email Validation Attribute in mvc

i am new in mvc .here scott shows how to Creating a Custom [Email] Validation Attribute in mvc. here is the picture.
http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx
1) now see how they did it. first create a class give a name and extend regular expression attribute class and in its ctor they use regex to validate email address
my question is when they use [Email(Errormessage="blah blah")]
then how MVC can understand this email attribute is pointing to email attribute class which extend regularexpression attribute class. how relation will be extanlish. the class name is email attribute but when they use then they use attribite name email. this is not clear to me please explain.
2) if i validate the email the above way they where validation will occur means at server side or client side ?
if not client side then how can i make it client and required js will be render for that.
please explain me with sample code example. thanks
The first question is best answered with a principle widely used in MVC: convention over configuration. That basically means: do the less config possible, use the most default functionalities. Several examples in ASP.NET MVC
Folder Controllers contain controllers by default.
The name of a view corresponds to the name of a Action in a Controller.
The folder name where a view is located corresponds to the Controller name without 'Controller' ending.
The class name of the controller ends with 'Controller' which is omitted when calling the controller.
The same with Attributes; the class name ends with 'Attribute' which is omitted in usage
etc, etc, etc,
There are many more like this and it is not configured. It is convention.
The second question is already partially answered in the question itself: you cannot inherit from EmailAddressAttribute as it's a sealed class. But you can use
RegularExpressionAttribute the way it's described in your question, or create a new attribute, like I will do it below.
However this way the validation will take place only on server side. To make it on client side you need to do the following:
public class EmailAttribute : ValidationAttribute, IClientValidatable
{
private const string VALIDATION_TYPE = "customEmail";
private const string EMAIL_REGEX = #"put your regex here";
public virtual IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule { ValidationType = VALIDATION_TYPE, ErrorMessage = ErrorMessageString };
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var sValue = value as string;
if (!string.IsNullOrEmpty(sValue) && Regex.Match(sValue, EMAIL_REGEX).Success)
{
return ValidationResult.Success;
}
return new ValidationResult(string.Format(ErrorMessageString, validationContext.MemberName));
}
}
Then in Javascript (I suppose you've included jQuery, jQuery.validate and jQuery.validate.unobtrusive) use the following:
$.validator.addMethod('customEmail', function (value, element) {
let regex = /put your regex here/;
return regex.test($(element).val());
});
$.validator.unobtrusive.adapters.add('customEmail', [], function (options) {
options.messages['customEmail'] = options.message;
options.rules['customEmail'] = options.params;
});

Grails validation no Constraints block

The usual way of constraint validating domain objects in Grails is by defining a static constraints closure in the domain object, after which one can call myObject.validate().
Is it possible in some way to pass what should be validated to the validate call and not define a constraints block?
I guess it could be done with Spring validator instances, but is there an easier way where you still have the "goodies" from Grails (max, email, etc.)?
You can pass a list of fields into .validate(["fieldA", "fieldB"]) and it will only validate those fields. You still need a constraints block to define what the constraints are for those fields.
From Grails User Guide:
"The validate method accepts an optional List argument which contains the names of the properties to be validated. When a List of names is specified, only those properties will be validated."
To respond to #eugene82:
#Validateable
class MyDomainValidator {
String email
static constraints = {
email(email:true)
}
}
MyDomain m = new MyDomain()...
MyDomainValidator mv = new MyDomainValidator()..
mv.properties = m.properties
mv.validate()
I imagine such an approach: Create a #Validateable groovy class with static constraints inside with any Grails goodies you need. Let it own all fields like your domain does (e.g. by extending the domain), and provide a way to copy all fields from a domain instance to a new instance of that object, e.g. using a constructor. Than call validate() on that class.
class MyDomain {
String email
MyDomain() {}
MyDomain(email) {
email = this.email
}
}
#Validateable
class MyDomainCustomValidator extends MyDomain {
MyDomainValidator() {}
MyDomainValidator(domain) {
super(domain.email)
}
static constraints = {
email email: true
}
}
def d = new MyDomain('e#mail.com')
new MyDomainCustomValidator(d).validate()

user defined form validation in grails

I want to validate three form fields.
The usual method is like this:
class User {
String name
String password
String personalInfo
static constraints = {
name(size: 4..20, unique:true, blank:false)
password(size:8..20, blank:false)
personalInfo(size: 1000, nullable:true)
}
}
but in my gsp i'll be having all three textfields in the same name
eg:
<td>Name:</td><td><g:textfield name="property"/></td>
<td>Password:</td><td><g:textfield name="property"/></td>
<td>PersonalInfo:</td><td><g:textfield name="property"/></td>
How to validate this form????
It is a really bad practice to give the same name to input fields in a form that are going to be mapped to different properties in the same domain class.
But if you cant, the fields will be sent as a list to your controller. So you can extract values in the controller like this:
def parameterList = params.property as List
def name = parameterList[0]
def password = parameterList[1]
def personalInfo = parameterList[2]
Then you can create your User object
def user = new User(name:name, personalInfo:personalInfo, password:password)
if (user.save()){ } else{ }
As the best practice you must name your fields in the form differently

Filter select drop down using Grails security ACL

I am implementing ACL security using the spring-security-acl plugin. I have the following domain classes:
package test
class Subitem {
String name
static belongsTo = [employer: Employer]
static constraints = {
name blank: false
}
}
package test
class Employer {
String name
static hasMany = [users: User, items: Subitem]
static belongsTo = User
static constraints = {
name blank: false, unique: true
}
String toString() {
name
}
}
In the create.gsp file which is used to create a Subitem, there is the following statement:
<g:select id="employer" name="employer.id" from="${test.Employer.list()}" optionKey="id" required="" value="${subitemInstance?.employer?.id}" class="many-to-one"/>
From the EmployerController:
def list = {
params.max = Math.min(params.max ? params.int('max') : 10, 100)
[employerInstanceList: employerService.list(params),
employerInstanceTotal: employerService.count()]
}
Following the tutorial given here, I have moved some of the functionality with dealing with Employer to a service called EmployerService:
#PreAuthorize("hasRole('ROLE_USER')")
#PostFilter("hasPermission(filterObject, read)")
List<Employer> list(Map params) {
Employer.list params
}
int count() {
Employer.count()
}
Access to information in any given Employer class instance is restricted using ACL. At present, I can see ALL instances of Employer in the database in the drop down, and I assume that is because I am using the controller list(), not the service list() - however, I only want to see the filtered list of Employer domain classes. However, if I replace the g:select with:
<g:select id="employer" name="employer.id" from="${test.EmployerService.list()}" optionKey="id" required="" value="${subitemInstance?.employer?.id}" class="many-to-one"/>
then I get an internal server error because I haven't passed a Map parameter to the service list() function (and I don't know how to do this within the tag):
URI /security/subitem/create
Class groovy.lang.MissingMethodException
Message No signature of method: static test.EmployerService.list() is applicable for argument types: () values: [] Possible solutions: list(java.util.Map), is(java.lang.Object), wait(), find(), wait(long), get(long)
I only want to see the information that comes from the EmployerService list() function - how do I do this please? How do I reference the correct function from within the gap?
Edit 16 Mar 0835: Thanks #OverZealous, that's really helpful, I hadn't realised that. However, I've tried that and still get the same problem. I've put a println() statement in both the Employer and EmployerService list() functions, and can see that neither actually seems to get called when the g:select tag is parsed (even if I leave the g:select to refer to Employer). Is there another version of the list() function that is being called perhaps? Or how else to get the g:select to take account of the ACL?
Just change your method signature in the Service to look like this:
List<Employer> list(Map params = [:]) {
Employer.list params
}
The change is adding this: = [:]. This provides a default value for params, in this case, an empty map.
(This is a Groovy feature, BTW. You can use it on any method or closure where the arguments are optional, and you want to provide a default.)
OK, I worked it out, and here is the solution to anyone else who comes up against the same problem.
The create Subitem page is rendered by means of the Subitem's create.gsp file and the SubitemController. The trick is to amend the SubitemController create() closure:
class SubitemController {
def employerService
def create() {
// this line was the default supplied method:
// [subitemInstance: new Subitem(params)]
// so replace with the following:
params.max = Math.min(params.max ? params.int('max') : 10, 100)
[subitemInstance: new Subitem(params), employerInstanceList: employerService.list(params),
employerInstanceTotal: employerService.count()]
}
}
So now when the SubitemController is asked by the g:select within the Subitem view for the list of Employers, it calls the EmployerService, which supplies the correct answer. We have simply added 2 further variables that are returned to the view, and which can be referenced anywhere within the view (such as by the g:select tag).
The lesson for me is that the View interacts with the Controller, which can refer to a Service: the Service doesn't play nicely with a View, it seems.

Resources