Domain class auto validation in grails - grails-orm

I am fetching list of results from database but the list doesn't validates the constraints until i call "validate()" method for each objects.
def temp = ConfigInfo.where { projectId == project }.findAll()
//at this stage domain class is not validated
temp.each {
println "validate" + it.validate()
println "has error" + it.hasErrors()
}
//in the above code block validate() is called, I don't want to do this.
// is it possible to configure it happen automatically and i get the validated objects.
I don't want to invoke validate method.
is there any way or configuration in grails such that domain class get validated automatically.
Please help me in this.

Grails domain class objects get validated before save.
Use the following in your domain model to set the validation rules:
static constraints = {
// whatever you want to validate
}
Whenever you save an object it will be validated by the constraints you set. When the object is persistent in the database it has always been validated.

All you need to do is that just define all your validation in constraints closure.
e.g.
static constraints = {
id maxLength: 5
//etc...
}
at the time of saving object you just need to check object is validate or not!, it will return true/false.
look this: click here

Related

Aurelia - ValidationController always returns true

I've made a wizard with aurelia and I want to check the input values when the user hits the next button.
#autoinject()
export class settingsWizard {
steps: Step[];
activeStep: Step;
valController: ValidationController;
constructor(private i18n: I18N, private http: HttpClient, public wizard: Wizard, private log: Logger, private router: Router, private controllerFactory: ValidationControllerFactory) {
this.steps = [
new Step(1, this.i18n.tr("route1"), PLATFORM.moduleName('./steps/step1')),
new Step(2, this.i18n.tr("route2"), PLATFORM.moduleName('./steps/step2')),
new Step(3, this.i18n.tr("route3"), PLATFORM.moduleName('./steps/step3')),
new Step(4, this.i18n.tr("route4"), PLATFORM.moduleName('./steps/step4')),
];
ValidationRules
.ensure('availableTotalTime').required().on(this.wizard.plannedTime);
//.ensureObject()
//.satisfies((x: IQualityRate) => x.numberOfProducedQuantity > x.rejects)
//.withMessage(this.i18n.tr('quality-rate.rejectsHigherThanProducedQuantity'))
//.on(wizard.qualityRate);
this.valController = controllerFactory.createForCurrentScope();
this.valController.validateTrigger = validateTrigger.manual;
}
here's the nextButton event:
nextStep() {
this.valController.validate().then(result => {
if (result.valid) {
if (this.activeStep.id !== this.steps.length) {
this.activeStep = this.steps[this.activeStep.id];
}
}
});
}
My aurelia ValidationController always returns result.valid = true even though availableTotalTime is undefined. What am I doing wrong?
You might be assuming that the ValidationRules api automatically causes objects to be validated, but it only stores the rules on the object's prototype.
The ValidationController only validates objects which are either explicitly (1) or implicitly (2) registered, or directly provided (3) to it.
1. Register "implicitly"
Any property in a view that has the & validate binding behavior on it will be validated whenever you call controller.validate() in the same viewmodel.
2. Register explicitly
Likewise, controller.addObject(this.wizard.plannedTime) will cause that object (and all its properties) to be validated on subsequent calls to .validate()
3. Provide a ValidateInstruction
this.valController.validate({
object: this.wizard.plannedTime,
// optional: propertyName: ...,
// optional: rules: ...
});
This gives you the highest degree of control. It will only validate the object you pass in, and nothing else. Also it won't register the object, so subsequent calls to .validate() will not automatically validate it again.
You'll probably either want to go with option 2 or 3, depending on other concerns.
Ended up here as I was getting the same problem. Fred Kleuver's answer is correct, but only when using .on to register your view model (or in this case, the object with the property to be validated) when creating your rules.
If you are like me and you're explicitly passing in the validation rules into the binding behavior, like & validate:myRules (this happens to be how most of the examples I've seen online doing it) you will need to follow the Entity Validation portion of the documentation.That way you can explicitly pass your validation rules into your validationController.addObject call in the same way you would pass your rules to your binding behavior in your view.
this.validationRules = ValidationRules
.ensure('availableTotalTime')
.required()
.rules;
this.validationController.addObject(this.wizard.plannedTime, this.validationRules);

Yii-rights params/data for bizrule

Scenerio:
Using Yii-rights + Yii-user module in my project. In Rights, I generated operations based on my controller action, under update I added a child UpdateOwn.
For UpdateOwn, the bizrule is suppose to be a simple comparison that the logged in user's ID is equal to $model->user_id field.
Problem:
I understand yii checkaccess allow you to pass in variables as parameters and comparing with your defined bizrule. But how does it work for Yii-rights module? How or what are the data/params passed in to be used in bizrule? How can I define or pass my own data/params?
Yii-rights is a wrapper for standart yii-rbac. In rights module you have web-interface for your RBAC. When you creating AuthItem (Operation in rights web interface) you can define your own bizrule.
Here is code for creating AuthItem:
$item = $this->_authorizer->createAuthItem($formModel->name, $type, $formModel->description, $formModel->bizRule, $formModel->data);
$item = $this->_authorizer->attachAuthItemBehavior($item);
_authorizer here is an example of RAuthorizer class. Then we go to RDbAuthManager, which extends CDbAuthManager, where we createAuthItem function:
public function createAuthItem($name,$type,$description='',$bizRule=null,$data=null)
{
$this->db->createCommand()
->insert($this->itemTable, array(
'name'=>$name,
'type'=>$type,
'description'=>$description,
'bizrule'=>$bizRule,
'data'=>serialize($data)
));
return new CAuthItem($this,$name,$type,$description,$bizRule,$data);
}
This is how created AuthItem, in rights. Personally i prefer to use web interface. It have alot of great fetures and much easier to handle then go to code each time.
Then when we perform checkAccess() on AuthItem we call execute bizRule:
public function executeBizRule($bizRule,$params,$data)
{
return $bizRule==='' || $bizRule===null || ($this->showErrors ? eval($bizRule)!=0 : #eval($bizRule)!=0);
}
This is how RBAC in yii work, and rights is just a cool wrapper for it. Rights doesn't change logic of how things must be done.
So in basic yii-rbac if you want to allow update only Own records you do:
$bizRule='return Yii::app()->user->id==$params["user"]->username;';
$task=$auth->createTask('updateOwnUser','update a your own account',$bizRule);
$task->addChild('updateUser');
Then you call it like this:
$user=$this->loadUser();
$params = array('user' => $user);
if(Yii::app()->user->checkAccess('updateOwnUser', $params){
..................
}
In rights it's already implemented with filters. Only thing what you need to do is add to your controller:
class MyController extends RController{
.............
public function filters()
{
return array(
'rights',
............
);
}
.............
}
So define your bizrule for item in web interface, change your controller code, and actually thats it. To know what variables to use in bizrule you can watch on RightsFilter.php code, where checkAccess() performed.
And on top of all of this i'll say about how checkAccess() does :
For each assigned auth item of the user, it first checks if the bizRule for the assignment returns true.
If true, it calls the item's checkAccess method. If the item's bizRule returns true,
2.1. If the item name is the same as the name passed in the original checkAccess() method, it returns true;
2.2. Otherwise, for every child item, it calls its checkAccess.
Hope this will clarify some aspects of RBAC and help in your task.
The yii-rights module has the following properties:
/**
* #property boolean whether to enable business rules.
*/
public $enableBizRule = true;
/**
* #property boolean whether to enable data for business rules.
*/
public $enableBizRuleData = false;
To set bizrule data via the web interface you have to set $enableBizRuleData = true in your application configuration.
Please note that the UI is limited and you can set data only for Auth-Items not for Auth-Assignments. Also the value for data has to be a serialized PHP variable.
As mentioned by #ineersa you can access $data in unserialized form in your bizRule.
It's also worth noting, that Yii checks first the bizRule for the Auth-Item and then additionally for the Auth-Assignment.
[edit] added example
Auth Item
bizRule
Check if the assignment has all the keys specified in the item data
return BizRule::compareKeys($params, $data, 'Editor');
data
a:1:{s:8:"language";b:1;}
Auth Assignment
Check if the application language matches the assignment data
bizRule
return BizRule::compareApplicationLanguage($params, $data);
data
a:1:{s:8:"language";s:5:"de_de";}
[edit] added code link
Here is the full Helper Code

Relation many-to-one retrieved from custom cache

It's more like theoretical question.
I have one table to hold dictionary items, and the next one for hold Users data.
User table contains a lot reference collumns of type many to one indicated on dictionary item table. It's looks like:
public class User
{
public int Id;
public Dictionary Status;
public Dictionary Type;
public Dictionary OrganizationUnit;
......
}
I want retrieve all dictionary on startup of aplication, and then when i retrieved user and invoke reference property to dictionary the dictionary object should be taken from cache.
I know i can use a 2nd level cache in this scenario, but i'm interested about other solution. Is there any?
It's posible to make my custom type and said that: use my custom cache to retrieved value of dictionary??
Across multiple session the second level cache is the best answer, the only other solutions to populate objects from a cache without using second level cache i can think of would be to use an onLoad interceptor (and simply leave your dictionaries unmapped) or do it manually somewhere in your application.
But why don't you want to use the seocondlevel cache? If your views on caching is very different from the storages there are providers for in hibernate it is possible for you to implement your own provider?
Why not store it in the session? Just pull the record set one time and push it into session and retrieve it each time you want it. I do something similar for other stuff and I believe my method should work for you. In my code I have a session manager that I call directly from any piece of code needs the session values. I choose this method since I can query the results and I can manipulate the storage and retrieval methods. When relying on NHibernate to do the Caching for me, I don't have the granularity of control to cause specific record sets to only be available to specific sessions. I also find that NHibernate is not as efficient as using the session directly. When profiling the CPU and memory usage I find that this method is faster and uses a little less memory. If you want to do it on a site level instead of session, look into HttpContext.Current.Cache.
The following example works perfectly for storing and retrieving record sets:
// Set the session
SessionManager.User = (Some code to pull the user record with relationships. Set the fetch mode to eager for each relationship else you will just have broken references.)
// Get the session
User myUser = SessionManager.User;
public static class SessionManager
{
public static User User
{
get { return GetSession("MySessionUser") as User; }
set { SetSession("MySessionUser", value); }
}
private static object GetSession(string key)
{
// Fix Null reference error
if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.Session == null)
{
return null;
}
else
{
return System.Web.HttpContext.Current.Session[key];
}
}
private static void SetSession(string key, object valueIn)
{
// Fix null reference error
if (System.Web.HttpContext.Current.Session[key] == null)
{
System.Web.HttpContext.Current.Session.Add(key, valueIn);
}
else
{
System.Web.HttpContext.Current.Session[key] = valueIn;
}
}
}

How can I have a domain object's .save() method fail in an integration test?

For an integration test, I want to have a .save() intentionally in order to test the according else-condition.
My class under test does this:
From UserService.groovy:
User user = User.findByXyz(xyz)
if (user) {
// foo
if (user.save()) {
// bar
} else {
// I WANT TO GET HERE
}
}
The approaches I've tried so far failed:
What I've tried in in UserServiceTests.groovy:
def uControl = mockFor(User)
uControl.demand.save { flush -> null } // in order to test a failing user.save()
def enabledUser = userService.enableUser(u.confirmationToken)
uControl.verify()
// or the following:
User.metaClass.'static'.save = { flush -> null } // fails *all* other tests too
How can I get to the else-block from an integration test correctly?
You should almost never have a need for mocking or altering the metaclass in integration tests - only unit tests.
If you want to fail the save() call just pass in data that doesn't validate. For example all fields are not-null by default, so using def user = new User() should fail.
maybe you could try changing the 'validate' to be something else - by using the same meta class programming that u have shown .
That way, if the validate fails, the save will certainly fail
What I do in such cases:
I always have at least one field which is not null.
I simply don't set it and then call .save()
If you want to achieve this on an object already in the database, just load it using find or get and set one of the not null values to null and then try to save it.
If you don't have Config.groovy configured to throw exceptions on failures when saving it will not throw the exception, it simply won't save it [you can call .validate() upfront to determine whether it will save or not and check object_instance.errors.allErrors list to see the errors].

Defining controller accessible variables from filters in Grails

I'm writing a small webapp in Grails, and to make sure all users are authenticated I'm using the following filter:
class LoginFilters {
static filters = {
loginCheck(controller:'*', action:'*') {
before = {
if (session.user_id) {
request.user = User.get(session.user_id)
} else if (!actionName.equals("login")) {
redirect(controller: "login", action: "login")
return false
}
}
}
}
}
And all controller methods start with reading the user property of the request object:
def actionName = {
def user = request.user
...
}
The code above works, but I'd rather avoid the duplicate code in the all controller methods. Would it be possible for the filter to bind the user object to a variable named "user" instead of "request.user", that will be accessible from all controllers?
I understand that there might be scoping issues that makes this impossible, but the Grails framework seems to be able to create quite some magic under the hood, so I figured it might be worth asking.
Using the beforeInterceptor in a controller may help:
class LoginController {
def user
def beforeInterceptor = {
user = request.user
}
def index = {
render text:"index: ${user}"
}
def test = {
render text:"test: ${user}"
}
}
I think it generally not a good idea insert the user object into the request object every time:
The request lifetime is very short, so you might end up making round trips to caches or even worse to the database on each http-request to retrieve an object, that you might not even need and that get's deleted immideately afterwards. So if you must, better store the whole object in the session instead of just the id.
Generally, I'd suggest you write a AuthenticationService with a method isLoggedIn() that returns true when the user is authenticated and a method getLoggedInUser() that returns this object.
class AuthenticationService {
def transactional = false
boolean isLoggedIn() { return session.user_id }
def getLoggedInUser() { return User.get(session.user_id) }
}
Then you use the Filter for redirection if not authenticated, and maybe the Interceptor for storing the local reference user = authenticationService.loggedInUser. But also I don't think this the best way to go. I suggest you'd create an abstract AuthenticationAwareController as base class for all your controllers in src/groovy and there have the convenience method like user
class AuthenticationAwareController {
def authenticationService
def getUser() { return authenticationService.loggedInUser() }
}
This way, you can later change you mind about storing the user however you like and don't have to change your code. Also you benefit from Caches in Hibernate, that share already retrieved user object instances between different sessions, so db roundtrips are avoided.
You still should check the retrieved user object for validity or throw an AuthenticationException in case the retrieval does not succeed. (Maybe something like AuthenticationService.getLoggedInUser(failOnError = false).)
You can even make this Service/ControllerBase a small plugin an reuse that on every application or go directly with the spring security plugin... ;-)
I think you can do this but is it really worth the trouble? It seems to me your only advantage is typing "user" instead of "request.user". Not a big gain. Anyway, I think you could follow the instructions in "12.7 Adding Dynamic Methods at Runtime" of the User Guide. I think that if you created a dynamic method "getUser() {return request.user}" that the Groovy JavaBeans getter/setter access would allow you to simply reference "user" the way you want.
If you do add a dynamic method you might want to skip the filter and do it all in the dynamic method.