How can we create our own custom validation - grails

I am using grails 2.4.3 with database Neo4j with SDN ,We don't use Grails plugin so grails doesn't support Neo4j and if we create our domain classes in domain package then it gives us an error.
So We create our domain in Services package. My First Question is:
We are right or we have to do another thing?
My another question is to provide the validation in this concept. We use the Command Object for it. So now we need some Custom validation for unique. I know we can use Validator for it, but we want that our logic only remain in Services. So can we create something like this?
static constraints = {
username size: 5..15
password size: 5..15, blank: false
userEmail email: true
}
username email:true
userName name:unique

I don't understand why you're so fixated on having to use a service for this. Creating a service annotated with #Validateable and using it as a non-GORM domain class seems very weird. If it works, cool, but it's sort of like driving to work in reverse the whole way. You'll get there (until you burn out the transmission) but it'll be a stressful drive looking in the rear view mirror and seeing everthing reversed the whole time.
Why not just put the classes in a sensible package under src/groovy and annotate those? You just need to register them in Config.groovy, e.g.
grails.validateable.classes = [
com.mycompany.myapp.User, com.mycompany.dto.Account]
You can do a uniqueness check, but not with the standard unique constraint. That's tied to GORM; it looks at the table or backing store for you domain class and runs a datastore-specific uniqueness query, but that doesn't apply here. But you can easily do the same thing yourself. Use a custom validator:
email validator: { value, obj ->
// run a Neo4j query checking to see if value has
// been used, the equivalent of
// "select count(email) from person where email=?"
// and return false if the count is not zero
}

Related

Grails dynamic "inList"

This is almost identical to this old question: Dynamic define the inList constraint using database query which was essentially unaddressed, perhaps there have been advances in the years since that was asked.
I'd like to populate the inList parameter of a domain attribute with values from another domain. Due to auto-generated views (scaffolding, filterpane), this needs to come from inList rather than a custom validator.
class MyDomain {
String someValue
static constraints = {
someValue(nullable: true, maxSize: 50, inList: SomeOtherDomain.list()*.name)
}
}
This gives the following error on startup:
Caused by: java.lang.IllegalStateException: Either class [thepackage.SomeOtherDomain] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
I know, the "correct" way to handle this is to make someValue an instance of SomeOtherDomain instead of just storing the name, but that doesn't quite fit. We want to be able to delete an instance of SomeOtherDomain without breaking the saved value of the owning domain... the domain with the deleted value will be invalid going forward, and would have to be updated before saving, but archived/locked records will still exist and can be displayed.
You can specify value lists for filterpane like this:
<filterpane:filterPane domain="MyObject" filterPropertyValues="${['someValue':[values: SomeOtherDomain.list().collect{it.name}]]}" />
And then just use a custom validator to actually validate. I'm not sure what scaffolding might use the inList but easy enough to get around that if you're OK with replacing a few scaffolded pages with static ones.

Can grails domain class include custom criteria in every query?

I'm creating a domain class that will connect to an existing database. Unfortunately multiple domain objects are stored in the same table (the table is very generic), and I'm trying to find a way to include additional criteria in each query that is made through GORM.
For example, I have an Article domain class which exists in the exp_channel_data table. The table has site_id and channel_id columns, which will be used to indicate if the row is actually an Article (where site_id=2, and channel_id=3).
I can setup custom constraints to make sure that validation works properly:
static constraints = {
site_id validator: { it == 2}
channel_id validator: { it == 3}
}
But I want to prevent invalid Articles from even being returned in the first place (keeping things clean, and also for performance reasons).
What I'm envisioning is the ability to override every query that goes out from my domain class, and insert where site_id=2 and channel_id=3 so that I don't even see invalid rows.
Any thoughts would be appreciated, thanks in advance.
UPDATE
After using the hibernate-filter plugin (suggested below), this is what I'm using in the domain class to prevent unnecessary entries from being returned.
static hibernateFilters = {
site_idFilter condition: 'site_id=2', default: true
channel_idFilter condition: 'channel_id=3', default: true
}
From what you are describing here, since it's per domain class, this looks to be a perfect situation for using the Hibernate filters plugin for Grails. This way you can define default constraints to be applied to criteria from those domains. Well worth a look to see if it will meet your needs.

how to serialize domain classes grails

I tried to serialize grails domains classes to Maps or similar in order to be able to store it in memcached.
I want to be able to read the objects only, I don't need gorm crud. Only to read them without breaking the kind of interfaces they have.
For instance: I could convert domains to maps, becouse it wouldn't break the interface for access like .<property> or .findall or similar
First I tried to do a manual serialization but it was very error prone. So I needed something more general.
Then I tried to serialize as a map with a grails codec.
Here is the testing repo.
Here is the snippet.
But I get StackOverFlowException.
I also tried to mark all the domains as Serializable but I need to reattach every domain when I bring them back from memcached to avoid hibernate errors like org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Do you know a way to achieve this?
Is very frustrating to google search for something like this "storing domain classes in memcached" and find out is not a common problem.
I haven't see an out-of-the-box solution for doing this, but if you wanted to keep it generic you could do it manually (and consistently) like this:
def yourDomainInst = DefaultGrailsDomainClass(YourDomainClazz)
List listOfOnlyPersistantProperties = yourDomainInst.persistantProperties
def yourNewMap
yourObjects.each { obj ->
listOfOnlyPersistantProperties.each { prop ->
def propName = prop.name
yourNewMap.put(propName, obj."$propName")
}
}
Something like that should work. Note there's probably a hundred errors because I can't try it out right now, but that is the general idea.
Have a look at: Retrieving a list of GORM persistent properties for a domain

How can I use more than one set of constraints on a single domain class in Grails?

I need to choose a set of validation rules at save time. Ideally I would like to be able to define more than one set of constraints in the domain class:
class Account {
...
static constraints = { ... }
static constraints2 = { ... }
}
I know I can do my own validation in code (account.errors.rejectValue(...) etc) but I am looking to save some time by using the built in Grails validation if possible.
This is what Command Objects are for.
The reason you can't just swap out validation is that the validation also helps define the database structure, like setting a field to be non-null, or non-blank, or having a specific length. Turning off "non-null", for example, could break the database structure.
Command objects, on the other hand, are designed to have their own unique set of validation rules. It's not the cleanest method (now you are tracking the same structure in more than one situation), but it's better in a lot of ways.
It allows you to securely accept input parameters without worrying that something that shouldn't be processed gets set.
It creates cleaner controllers, since the validation logic can all be handled within the Command Object, and not sprinkled through the controller method.
They allow you to validate properties that don't actually exist on the object (such as password verification fields).
If you think you really need multiple sets of constraints, you are most likely either a) over-complicating the domain object to represent more information than it really should (maybe break it up into several one-to-one related objects), or b) incorrectly setting the constraints in the first place.†
In my experience, usually it's a that happens when you feel the need to swap out constraints.
† That being said, it can (rarely) make sense. But Command objects are the best solution in this situation.
you can use the validator constraint, see: http://www.grails.org/doc/latest/ref/Constraints/validator.html
within one validator constraint you can perform more checks than one and return diffrent error codes, e.g.
static constaints = {
name: validator { value, obj ->
if (value.size() > 10)
return [invalid.length]
else if (value.contains("test"))
return [invalid.content]
return true
}
in message.properties
domainClass.propName.invalid.content = ...
}

ACL on field level in Grails

in our new software project, we have the following requirement: A webpage shall show a set of data. This data shall be editable by some users (assigned to roles, i.e. manager), and only viewable by others. The tricky part is described by an example:
A User-page consists of address data and account information. The addess data shall be editable by the user and the manager and viewable by all users, while account information shall only be viewable by the actual user and the manager.
I have read a lot of information about SpringSecurity. It provides a very good framework to gran permissions on urls and methods and even domain classes. But what I need is field level ACLs. At least, that's what I think at the moment.
So, the question is: How to solve this problem using Grails?
Thanks a lot in advance,
Regards Daniel
Spring Security (Acegi Plugin) is definitely the way to go with Grails.
There is a taglib you can use that will allow a page to be different for different roles such as the following:
<g:ifUserHasRole roles="ROLE_ADMIN">
html code for extra fields
</g:ifUserHasRole>
Me, I'd encode it on the domain class, emulating the way GORM has you annotate the domain classes (static access = [field1: "ROLE_USER", field2: "ROLE_ADMIN,ROLE_USER"] as an example). Then build a method your controller could use to redact them for a given user. That method could use the domain class's annotations to decide how to redact it. Then, metaprogram it onto each of the domain classes the way plugins do.
Similarly, write the opposite method to restrict data bindings of params into the domain class, write your own data binding utility method, then metaprogram it onto each domain class as well.
Then you can just use instance.redact(user) or instance.bindData(params, user) to do what you want, and it's practically declarative syntax.
We have a similar situation and use both the ifUserHasRole tag in the gsp to drive the appropriate presentation and the we have a filter that enforces the rules based on the action being called. For example, on user controller we would only allow the management roles to call save action, or if the user.id is the same as the session.user.id. This seemed to be the best option for our situation.
What about creating an ACL class like this:
class ACL(val entry: Entry*) {
def isAccessAllowed(subject: String, permission: String): Boolean = ...
}
class Entry(val subject: String, val permission: String*)
usage:
new ACL(
new Entry("dave", "read", "write"),
new Entry("linda", "read")
)
(This example is in Scala, because I found it more expressive in this case, but it should be easy to transfer it to Groovy.)
You would then connect an ACL object with the object to be protected.

Resources