Is there a way to disable controller which is a part of some plugin (Searchable in my case) in Grails? The only two ways I can think of are pointing it to 404 page in UrlMappings [1] or writing filter for the same thing. However this seems to me more like a workaround that a proper solution. Also at least in case of Searchable plugin the need to get rid of default controller and view seems quite common to me as they are both basically useless.
[1] this was also accepted at Disable grails Searchable plugin default search page?
If you are using spring spring-security-core, than it will be very easy to restrict the controllers.
You just need to place the following code in config.groovy
grails.plugins.springsecurity.rejectIfNoRule = true //Deny all urls by default
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = [
/** Start IS_AUTHENTICATED_ANONYMOUSLY block **/
'/about/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
,'/': ['IS_AUTHENTICATED_REMEMBERED'] ]
Controllers which are mentioned in the interceptUrlMap block are accessible.
Related
I'm working on a simple JIRA Server plugin that will prevent a transition from occurring if a certain custom field has not been set. I have created a new workflow validator with atlas-create-jira-plugin-module and tailored the validate function to fit my needs. Strangely, when I add this new validator to a transition via the workflow editor, it appears in the list of validations with the wrong description. It is showing the description from the default condition, "Only users with Resolve Issues" permission can execute this transition".
I've been following along with this tutorial: https://developer.atlassian.com/server/jira/platform/creating-workflow-extensions/
I also came across this similar tutorial: https://www.j-tricks.com/tutorials/workflow-validator
In my atlassian-plugin.xml I made sure to define a "view" velocity resource:
<workflow-validator key="custom-field-is-set-validator" name="Custom Field Is Set Validator" i18n-name-key="custom-field-is-set-validator.name" class="com.ngc.jira.plugins.workflow.CustomFieldIsSetValidatorFactory">
<description key="custom-field-is-set-validator.description">Validation to require that a custom field be given a value.</description>
<validator-class>com.ngc.jira.plugins.workflow.CustomFieldIsSetValidator</validator-class>
<resource type="velocity" name="view" location="templates/validators/custom-field-is-set-validator.vm"/>
<resource type="velocity" name="input-parameters" location="templates/validators/custom-field-is-set-validator-input.vm"/>
<resource type="velocity" name="edit-parameters" location="templates/validators/custom-field-is-set-validator-input.vm"/>
</workflow-validator>
And the contents of custom-field-is-set-validator.vm are as follows:
Only if the custom field <strong>$field</strong> has be set.
As a sanity check, I created a workflow condition and applied my velocity (vm) resource as the view template for it. It shows up correctly within this context!
However, when I try to use the same velocity resource for my workflow validator, the admin page still displays the validator as "Only users with Resolve Issues permission can execute this transition" instead of using my description.
What am I missing? Thanks!
Screenshot showing the built-in condition
Screenshot showing my validator that is wrongly appearing as the same condition
I wrote an O'Reilly book Practical Jira Plugins back in 2011 that has a validator example. The source for this is at https://bitbucket.org/mdoar/practical-jira-plugins/src/default/ (and the book is Out There).
But frankly these days I'd use ScriptRunner, JMWE or other plugins that let you write custom workflow things. But don't let that stop you learning it! Good luck
It turns out, I had copied/pasted a piece of code from my workflow condition that needed to be tweaked for a workflow validator. I was trying to cast to a ConditionDescriptor when I should have been casting to a ValidatorDescriptor:
Bad:
if (!(descriptor instanceof ConditionDescriptor)) {
throw new IllegalArgumentException("Descriptor must be a ConditionDescriptor.");
}
ConditionDescriptor conditionDescriptor = (ConditionDescriptor) descriptor;
Good:
if (!(descriptor instanceof ValidatorDescriptor)) {
throw new IllegalArgumentException("Descriptor must be a ValidatorDescriptor.");
}
ValidatorDescriptor validatorDescriptor = (ValidatorDescriptor) descriptor;
Pretty neat that instead of completely breaking my plugin, it ended up displaying a different description altogether. ;)
I have Grails 2 application where I've already added i18n/messages_ru.properties. So, according to documentation I use request ?lang=ru (f.e. userOperations/index?lang=es) but nothing changed. Languages is still default, lang cookies wasn't created.
What's wrong? How can I fix it up?
PS. I use Oracle Java7 on Ubuntu
What are you expecting to change? If you look at the default index page (the one that lists controllers, etc) it doesn't use messages - it's all hard-coded.
I just tested and it works for me in 2.0.3. Here is what I did:
Create new Application
Create domain class with single field (String name)
Run "Generate All" for that class
The gsp's created will have something like this:
<g:message code="yourDomainClass.name.label" default="Name" />
Now if I don't do anything and look at the page, even with lang=ru or lang=es it is STILL going to say Name. But then I went in and added to the messages_es.properties file the following:
yourDomainClass.name.label=Nombre
and when I refreshed the page it says "Nombre" instead of "Name."
There are defaults in the message files for certain messages like "default.home.label" and when I used the lang=es those did change to Spanish like they should without me doing anything.
The problem is that you configured url(or it was default "/"(view:"index")) mapping to render view directly without a controller. Create a controller and render a view in it. Without a controller it doesn't work!
I've got a need where each user can customize their own page on a replicated site. In grails it seems the most straightforward way to do this is:
somedomain.com/someController/JohnDoe
spelling out a controller, except this forces folks to type in a longer domain name, versus something like
somedomain.com/JohnDoe
Using sub-domains may be another approach, however they would need to be created automatically, i.e. when someone joins.
Can you please clarify the main ways Grails supports this kind of requirement/need (replicated site), and some of the pros/cons of each?
Thanks, Ray
Edit: Per Tomasz's edit below, the simplest course of action isn't clear. If you have insights on this please do share.
It is called UrlMappings in grails. You need to declare:
"/$username?" {
controller = 'someController'
action = 'user'
}
It redirects to someController, action user and optional variable called username.
This solution has one catch. Every one level path you visit passes this rule and takes you to someController. You cannot go to somedomain.com/books because it passes rule above and it follows you to someController#user with params['username']='books'. Then you can't use default actions. But if you decide that all your other paths have at least one slash, e.g. /books/list then you can follow this solution
Edit: I was wrong. It doesn't work as I've expected. I thought that UrlMappings are applied in order they are defined. That's not true, as explained here. Even worse - it's not documented (GRAILS-6246). Most specific explanation comes from Peter Ledbrook :
It uses a specificity algorithm, so the most specific match should apply
You must experiment then. I suggest you use safest solution and stick with /user/username solution.
I'm relatively new to Spring, but very new to Spring Security and Grails. To be brief, I know its recommended to not allow .jsp files to be servable, you should toss them in WEB-INF, and set up your controllers to pull them from the right place.
How would I go about doing this in Grails? It seems that I would destroy the idea of "convention over configuration" by tossing gsp's into WEB-INF and then writing logic into all my controllers (if that's even immediately possible...) It seems I would have to alter some basic Grails configurations.
Any ideas?
OK, I haven't seen a complete answer for this here (or elsewhere one StackOverflow) that provides a full valid result, so here's what I've come up with:
First, create a new controller:
grails create-controller gspForbidden
Open this up, and add this to the index action:
index = {
response.status = 404
}
Then, open grails-app/conf/UrlMappings.groovy and add this under the static mappings closure:
"/grails-app/**.gsp"(controller:"gspForbidden")
This will redirect any attempts to view a GSP directly to the gspForbidden controller. That controller, in turn, simply renders a 404 - a file not found response. The best thing about this is that it's completely hidden - there's nothing showing that the GS path was correct, so there's less chance of exposing something important about the application design.
I tried repeatedly to figure out how to use UrlMappings to show a 404 without the controller, but I had no success. If you can think of a way, please let me know. I'd much rather have this happen without any explicit controllers.
Slight correction to earlier post:
Just adhering to the convention in Grails doesn't prevent someone who guesses where a gsp lives from hitting it directly (I just tried it, it works).
From Spring Security Plugin Documentation:
package com.testapp
import grails.plugins.springsecurity.Secured
class SecureController {
#Secured(['ROLE_ADMIN'])
def index = {
render 'Secure access only'
}
}
you can secure your GSP pages as the example above. Secured annotation will provide access only to a user if they have the admin rights.
for more information , refer to :
http://grails-plugins.github.com/grails-spring-security-core/docs/manual/
tutorials are nice as a start.
You actually don't need to worry about this in Grails. If you follow the conventions of using views and controllers it will handle all the details about making sure the GSP pages aren't directly accessible.
As far as integration with Spring Security is concerned, again if you follow one of the recommended patterns (URL security or annotation within your controllers) you should be fine.
i have a uri such as someController/someAction?param1=aa¶m2=bb
is there some method of grails can extract controller name and action name from this uri.
or shiro has any method to detect this uri is permitted?
i have a domain Menu(name,url), and now want to get the menu list which is permitted for current user.
url such as /auth/login(may be mapping as user:login), /user/login
so 2 days ago i ask this question.
now i change the menu to (name,controller,action,param),and filter the menulist like this:
def subject = SecurityUtils.subject;
menuList.each{
if(it.permission){
def perm = shiroPermissionResolver.resolvePermission("${it.permission.controller}:${it.permission.action}")
def isPermitted = subject.isPermitted(perm)
println "$isPermitted -> ${it.permission.controller}:${it.permission.action}"
}
}
sorry for my poor english,and thanks for reply.
btw,here is another question of how to cache shiro:
how to use cache permissions in grails shiro
To proflux:
so what do u think is the better way to store menulist?
cause:
it need to show different menu to user due to their permissions.
sometime we update a webapp, but want to show menu to user later.
so we only need to change such as a menu.visible. (better than change hard code cfg or source).
we areusing extjs to show the menu(so nav plugin cant use).
Shiro uses the convention of $controller:$action for permissions. You have two options:
Use the Shiro Tags
Use the Shiro API directly
In the first case, in your GSP you can add something like:
<shiro:hasPermission permission="someController:someAction">
<g:link...>
</shiro:hasPermission>
<shiro:lacksPermission permission="someController:someAction">
No link
</shiro:lacksPermission>
Alternatively, you can use the <g:if...> tag and use the
SecurityUtils.subject.isPermitted("someController:someAction")
method to directly check if the user has the necessary permission.
For more info, check out the Grails Shiro Tag Library Source and the Shiro API docs.