I'd like to store api key in my grails application. Api key should be global and can be changed every several minutes or hours.
Where is the best place to store this key globally?
I don't want to store it in database, guess that config is the best place.
But I suppose that config is a good place to store constants, not changeable data.
So, where to store api key globally?
Update: maybe class with static fields like String apiKey will be enough?
Api key should be global and can be changed every several minutes or hours.
Why would an API key change so frequently?
guess that config is the best place. But I suppose that config is a good place to store constants, not changeable data.
Normally properties in Config.groovy are read-only, but there's nothing to prevent you modifying them, e.g.
class MyController {
def grailsApplication
def updateApiKey(String newKey) {
grailsApplication.config.apiKey = newKey
}
}
Related
Recently I've been working on a simple state-tracking system, its main purpose is to persist updates, sent periodically from a mobile client in relational database for further analysis/presentation.
The mobile client uses JWTs issued by AAD to authenticate against our APIs. I need to find a way to verify if user has permissions to send an update for a certain Item (at this moment only its creator should be able to do that).
We assume that those updates could be sent by a lot of clients, in small intervals (15-30 seconds). We will only have one Item in active state per user.
The backend application is based on Spring-Boot, uses Spring Security with MS AAD starter and Spring Data JPA.
Obviously we could just do the following:
User_1 creates Item_1
User_1 sends an Update for Item_1
Item has an owner_ID field, before inserting Update we simply check if Item_1.owner_ID=User_1.ID - this means we need to fetch the original Item before every insert.
I was wondering if there was a more elegant approach to solving these kind of problems. Should we just use some kind of caching solution to keep allowed ID pairs, eg. {User_1, Item_1}?
WHERE clause
You can include it as a condition in your WHERE clause. For example, if you are updating record X you might have started with:
UPDATE table_name SET column1 = value1 WHERE id = X
However, you can instead do:
UPDATE table_name SET column1 = value1 WHERE id = X AND owner_id = Y
If the owner isn't Y, then the value won't get updated. You can introduce a method in your Spring Data repository that looks up the Spring Security value:
#Query("UPDATE table_name SET column1 = ?value1 WHERE id = ?id AND owner_id = ?#{principal.ownerId}")
public int updateValueById(String value1, String id);
where principal is whatever is returned from Authentication#getPrincipal.
Cache
You are correct that technically a cache would prevent the first database call, but it would introduce other complexities. Keeping a cache fresh is enough of a challenge that I would try it only when it's obvious that introducing the complexity of a cache brings the required, observed performance gains.
#PostAuthorize
Alternatively, you can make the extra call and use the framework to simplify the boilerplate. For example, you can use the #PostAuthorize annotation, like so, in your controller:
#PutMapping("/updatevalue")
#Transactional
#PostAuthorize("returnObject?.ownerId == authentication.principal.ownerId")
public MyWidget update(String value1, String id) {
MyWidget widget = this.repository.findById(id);
widget.setColumn1(value1);
return widget;
}
With this arrangement, Spring Security will check the return value's ownerId against the logged-in user. If it fails, then the transaction will be rolled back, and the changes won't make it into the database.
For this to work, ensure that Spring's transaction interceptor is placed before Spring Security's post authorize interceptor like so:
#EnableMethodSecurity
#EnableTransactionManagement(order=-1)
The downside to this solution is that there are still the same two DB calls. I like it because it's allowing the framework to enforce the authorization rule. To learn more, take a look at this sample application that follows this pattern.
The mail plugin is documented to require its settings in Config.groovy. I want to have it stored in the database so it can be changed at runtime. And this is just one example.
I've read Does externalizing sensitive config variables into a .properties outside of Config.groovy provide a security advantage in Grails? but this is about using an external property file, I need to store the settings in the database (the app has an admin interface, with auditing and so on).
Thank you.
In Bootstrap.groovy you can read the property values from the database and replace those read from the config files by updating grailsApplication.config. For example, assume you want to replace the value of a config property named foo.bar
class BootStrap {
GrailsApplication grailsApplication
def init = { servletContext ->
def fooBarDB = // read the value of foo.bar from the database
grailsApplication.config.foo.bar = fooBarDB
}
}
Rather than writing this code yourself, you could instead use the Dynamic Config Plugin to achieve the same outcome.
Yes, you can do this. During the grails bootstrap process using Bootstrap.groovy, retrieve the properties from the database and override them. It's similar to a properties file override, you're just storing them in a database.
Also see Properties in the database
First way to change value dynamic:
grailsApplication.config.grails.mail.put("port",your database fetch value of port)
grailsApplication.config.grails.mail.put("username","your database fetch value of username")
grailsApplication.config.grails.mail.put("password","your database fetch value of username")
grailsApplication.config.grails.mail.put("props","your database fetch value of username")
second way to change value dynamic:
org.codehaus.groovy.grails.commons.DefaultGrailsApplication
DefaultGrailsApplication class provide the all the information about config. you can get email information using following code and change it dynamic.
def defaultGrailsApplication= new DefaultGrailsApplication()
// to get mails information from Config.groovy
defaultGrailsApplication?.config?.grails.mail?.get("host")
defaultGrailsApplication?.config?.grails.mail?.get("port")
defaultGrailsApplication?.config?.grails.mail?.get("username")
defaultGrailsApplication?.config?.grails.mail?.get("password")
defaultGrailsApplication?.config?.grails.mail?.get("props")
// to change mails information of Config.groovy
defaultGrailsApplication?.config?.grails.mail?.put("host","your database fetch value of host")
defaultGrailsApplication?.config?.grails.mail?.put("port",your database fetch value of port)
defaultGrailsApplication?.config?.grails.mail?.put("username","your database fetch value of username")
defaultGrailsApplication?.config?.grails.mail?.put("password","your database fetch value of username")
defaultGrailsApplication?.config?.grails.mail?.put("props","your database fetch value of username")
Now you need to assign this "defaultGrailsApplication" instance to inject value of application. just assume that we have one class service Temp.service having grailsApplication injected like:
Temp.service
class Temp{
def grailsApplication
def your method(){
please add above code for set value
grailsApplication = defaultGrailsApplication
}
}
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.
I know it's possible to read in values from the grails-app/conf/Config.groovy but i was wondering if it is possible to write values as well?
something as simple as this doesn't seem to actually change the value in the Config.
def oldValue = grailsApplication.config.my.value
assert oldValue == "oldValue"
def newValue = "newValue"
grailsApplication.config.my.value = newValue
assert newValue == grailsApplication.config.my.value
I would like to use this as a way to store some values outside of a database without having to load up another properties file.
That's probably not going to be practical if I understand you correctly. You're really dealing with the compiled Config.class at runtime. Do you really want to check out Config.groovy from your VCS, modify it, check it back in, recompile it, and mess around with the Classloader to reload it? The only way I have found to do this is by externalizing their properties a database or file and managing state at runtime to deal with updates.
I agree with proflux's comment. Config.groovy is not the right place to persist any data generated by your application, and it's a good thing that what you try doesn't work :)
I am very curious as to why you don't want to persist these values in a regular database (of whatever kind). There is, of course always the option of storing this in a file somewhere, the path of which you can configure in Config.groovy. But even that to me only seems marginally helpful.
Why not add a domain class along the lines of this:
class Setting{
String key
String value
static constraints = {
key(unique: true)
}
}
This will probably be the easiest way of achieving what you're looking for, from what I can tell from here. But again, you should elaborate on what kind of data it is that you need to persist...
Note I am referring to one request, and not several requests and sessions.
I have several components that require Doctrine user object, some are located in layout, others are located in templates. Sometimes I need that Doctrine user object in action. Currently I have added a function to sfUser class that loads that object from database, which means every time I call that function I make a call to db. I'd like to know where to store this object so that I can access it without having to query db every time I need it. Again, we're talking about a single request, not several requests or something that would require session.
Can I save it in sfContext somehow? Any other places so that it can be available everywhere?
You can store it in your model's Table class, because tables are always accessed as singletones.
class sfGuardUserTable extends PluginsfGuardUserTable
{
protected $specialUser = null;
public function getSpecialUser()
{
if (null === $this->specialUser)
{
$this->specialUser = $this->findOneById(1);
}
return $this->specialUser;
}
}
Now, you can use this in actions and components like this:
$u = sfGuardUserTable::getInstance()->getSpecialUser();
And you will always end up with one query.
you can configure Doctrine cache so that the result of this specific request is always cached. What if so good about it is that if you use, say, the APC backend, you will have it cached across requests. You also get query caching as a bonus (this is not result caching, read the link I provided carefully)!