I am using the http://grails.org/plugin/audit-logging plugin and am only interested in auditing a single field in a large domain class. I could specify a lengthy 'ignore' list, but ideally I want to specify the whitelist of fields instead, so that if new fields are added, it is not necessary to maintain the ignore list to avoid them getting automatically audited which could be a performance risk.
Is this possible? I didn't see mention of it in the docs for the plugin.
I think you could do this using the event handlers only instead of the standard audit logging. You would set auditing like this
static auditable = [handlersOnly: true]
You could create a white list
def whiteList = ['name','age',...]
Then create on* events to handle a save, delete or change event and iterate through the white list to look up that key in the old and new map:
def onChange = {oldMap, newMap ->
whiteList.each{propName->
if(oldMap[propName] != newMap[propName]) {
//
}
}
}
Related
I have a system in grails, already running on a server, and we use tenant solutions to distinguish the branches of the corporation, but now I need to recover information from one branch to another.
The point is when I make the following query in my model:
def expedition = Expedition.findByCode(row.code)
If my expedition was issued by a branch this find does not return anything to me, after all it was thus the initial architecture for the branch offices not to fill information of each other.
Does anyone know how I can do this? it may just be to return that object at that point, or some annotation in the model, but I would not like to remove my multi-tenant structure because I still need to block some information.
You can use the methods on the grails.gorm.multitenancy.Tenants class to achieve this:
Allow to find across any tenant:
def expedition = Tenants.withoutId { Expedition.findByCode(row.code) }
Specify a tenant
Long otherTenantsId = 2L
def expedition = Tenants.withId(otherTenantsId) { Expedition.findByCode(row.code) }
Of course be careful when doing so or trusting user input for a tenant id as it will give access to other users data.
Note there are also #WithoutTenant if you'd like to add it to a class/method level.
I have a custom resource-tool (ledger entry tool) that modifies values of a resource as well as insert additional rows into related resources.
"Account" is the main resources.
"AccountTransaction" and "AccountLog" both get written to when a ledger entry is created. And through events, the account.balance value is updated.
After a successful post of a ledger entry (using Nova.request) in the resource-tool, I would like the new balance value updated in the account detail panel, as well as the new entries in AccountTransaction and AccountLog to be visible.
The simple way would be to simply reload the page, but I am looking for a more elegant solution.
Is it possible to ask these components to refresh themselves from within my resource-tool vue.js component?
Recently had the same issue, until I referred to this block of code
Nova has vuex stores modules, where they have defined storeFilters.
Assigning filters an empty object and then requesting them again "reloads" the resources. Haven't done much more research on this matter, but if you are looking for what I think you are looking for, this should be it.
async reloadResources() {
this.resourceName = this.$router.currentRoute.params.resourceName || this.$router.currentRoute.name;
if (this.resourceName) {
let filters_backup = _.cloneDeep(this.$store.getters[`${this.resourceName}/filters`]);
let filters_to_change = _.cloneDeep(filters_backup);
filters_to_change.push({});
await this.$store.commit(`${this.resourceName}/storeFilters`, filters_to_change);
await this.$store.commit(`${this.resourceName}/storeFilters`, filters_backup);
}
},
I'm using a legacy database in a read only fashion. I have a user domain that includes a flag if the user is active or not. Is there a way when calling search methods like findAll to always ignore inactive users without removing them from the database or specifically in every search query?
You have two options. Either add a Hibernate Filter which is your most transparent option, or to add a named query like
static namedQueries = {
active {
ne 'inactive', true
}
}
which will allow you to do
User.active.findAllBy...()
For instance, suppose I wanted to let that column be set to whatever the database defaults it to, without redefining that default in the domain class?
I can't find much through Google. There are hints that if I were working with Hibernate directly, I could set that particular column/property to private, and this might accomplish what I seek.
I can of course leave that column undefined, and GORM ignores it. But I need the values out of it whenever the Grails app does a select.
You can use the GORM property insertable as in doc or can read the value with a beforeInsert event:
class Book {
String title
String isbn
static mapping = {
isbn nullable: false
}
def beforeInsert {
title = queryFromDatabase...
}
}
I think you have to go the beforeInsert / Hibernate interceptor route since your requirement is to read default values from an existing database.
You can read the database default values for columns with JDBC's DatabaseMetaData.getColumns .
To find out the database table and column names, you can use something like this (this code is not tested)
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder
import org.codehaus.groovy.grails.orm.hibernate.cfg.Mapping
import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler
def gdc=grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, someInstance.class.name)
Mapping mapping=GrailsDomainBinder.getMapping(gdc)
def tableName=mapping.tableName
def columnName=mapping.getPropertyConfig('someColumn').column
This is not a complete answer, but I hope this helps.
I'm developing an app using Grails and there are some app-wide configuration settings I'd like to store somewhere. The only way I've thought of is to create a domain class that stores the configuration values, and to use a service that queries that domain class. The problem I see is that there should be just one instance of that domain class, but I haven't found anything to enforce that restriction.
There may be other best practices to store app's own configuration that I may not be aware of, all suggestions are welcome.
Edit: the settings are supposed to be configurable from within the app.
There is special place: /grails-app/conf/Config.groovy. You can add values there like:
my.own.x=1
and read values by:
def x = grailsApplication.config.my.own.x
See docs for more details: http://grails.org/doc/latest/guide/conf.html#config
There is a plugin for that: Settings. It allows you to create named setting like my.own.x of different types (String, date, BigDecimal and integer), and provides you with the basic CRUD pages to manage them.
You can access the settings from either gsp:
<g:setting valueFor="my.own.x" default="50" encodeAs="HTML"/>
or controllers/services/domains
Setting.valueFor("my.own.x", 50)
I use it in several projects and think it works great.
You can enforce your single domain class db entry via custom validator:
// No more than one entry in DB
class MasterAccount {
boolean singleEntry = true
static constraints = {
singleEntry nullable: false, validator: { val, obj ->
if(val && obj.id != getMasterAccount()?.id && MasterAccount.count > 0){
return "Master account already exists in database"
}
}
}
MasterAccount static getMasterAccount(){
MasterAccount.list()?.first()
}
}
You can defer its configuration and persistence to Bootstrap.groovy, which would achieve the same effect as Config.groovy
If you're using 1.3.* you can try grails dynamic-config plugin (http://www.grails.org/plugin/dynamic-config). "This plugin gives your application the ability to change the config properties without restarting the application. The values in Config.groovy are persisted in database when application is run-for the first time after installing the plugin. "
I've never used it on a grails 2.0.* project.