I am currently developing a web app in Grails and I am looking for a way to hide a menu based on the current user logged into the solution.
To give you a bit of background this is what I have setup
A web app with a User Model and Roles model that are mapped
Login functionality that restricts certain controllers based on the users access.
I have menus that are display on each of the pages.
I know how to restrict a controller to only allow users with access to view it but I want to now restrict a menu like the one below from being seen unless the right user is logged in, how can I do this? Does it have something to do with rendering that element from the controller??
<div class="nav">
<ul class"nav">
<li>
<g:link class="Tester" controller="Testing" action="test">
<g:message code="Tester" args"[entityName]" />
</g:link>
</li>
<li>
<g:link class="Tester2" controller="Testing" action="test2">
<g:message code="Tester2" args"[entityName]" />
</g:link>
</li>
</ul>
</div>
The spring-security-core plugin provides a taglib that may help you here
<sec:ifAnyGranted roles="ROLE_TESTER">
<div class="nav">
...
</div>
</sec:ifAnyGranted>
Ian answered your question well but we should add here to secure the server side controller/actions as well such as:
// At the controller level
#Secured(["hasRole('User')"])
class Testing
// action specific
#Secured(["hasAnyRole('SuperUser', 'Support', 'InternalUser')"])
def test() {
...
}
Otherwise the links are just hidden from view but could still be executed by anyone.
HTH
If you are not using spring-security-core plugin following can be implemented
<g:if test="${userHaveRightRole}">
<div class="nav">
...
</div>
</g:if>
Related
I have the following code which loops through a list of countries and creates a href links
<div class="container" th:each="country: ${countryList}">
<a th:href="${country.countryAbbr}"><div clss="row" th:text="${country.country}"></div></a>
</div>
The current page url is "localhost:8080/directory", and the generated url is showing as
"localhost:8080/us"
How can I make the url show as "localhost:8080/directory/us"
I want "us" to be added to the current url of the page.
Try create the following code in your Controller class.
#RequestMapping(value="/", method=RequestMethod.GET)
public String rootGet() {
return "redirect:/directory";
}
You can use ServletUriComponentsBuilder:
<div th:with="urlBuilder=${T(org.springframework.web.servlet.support.ServletUriComponentsBuilder)}"
class="container" th:each="country: ${countryList}">
<a th:href="${urlBuilder.fromCurrentRequest().path(${country.countryAbbr}).toUriString()}">
<div clss="row" th:text="${country.country}"></div>
</a>
</div>
Give a try to this one
<div class="container" th:each="country: ${countryList}">
<a th:href="#{${country.countryAbbr}}"><div clss="row" th:text="${country.country}"></div></a>
</div>
Using # usually resolves the default context but I am not aware of your environment.
For example, if you had Tomcat .war file, and your application would be hosted at localhost:8080/myApp, you would want result /myApp/us rather then /us. # would do that trick.
If above is not relevant for you, use this one:
<div class="container" th:each="country: ${countryList}">
<a th:href="#{'/directory/' + ${country.countryAbbr}}"><div clss="row" th:text="${country.country}"></div></a>
</div>
I have a View called Reports, under that I have 2 different Views called Races and Sire. I am calling these 2 Views as partial views inside Reports page.
When user type http://localhost:53987/Reports/Reports# in the address bar, it loads Races and Sire which are main views, as partials inside Reports. But What I want is that when user put http://localhost:53987/Races/Races# in the address bar, it should redirect this to http://localhost:53987/Reports/Reports#.
Can anyone please suggest me how to acheive this.
Reports View
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#Race">Race</a></li>
<li><a data-toggle="tab" href="#sire">Sire</a></li>
</ul>
<div class="tab-content">
<div id="race" class="tab-pane fade">
#Html.Partial("~/Views/Racing/Race.cshtml", Model.clsRace)
</div>
<div id="sire" class="tab-pane fade">
#Html.Partial("~/Views/Sire/Sire.cshtml", Model.clsSire)
</div>
</div>
If all you are doing is rendering those partials using #Html.Partial(), then your controller methods are not necessary and you can just delete them (the user would get a 404: Not Found if they try to navigate to those urls).
If however, you were using #Html.Action() to render them (because you had to execute some code in the controller to generate the partial), then the methods should be marked with the [ChildActionOnly] attribute (which prevents the user navigating to them.
If you did want to allow a user to enter those url's in the address bar, but redirect to ../Reports/Reports, then you could create a specific route definitions for them, for example
routes.MapRoute(
name: "Races",
url: "Races/Races",
defaults: new { controller = "Report", action = "Report" }
);
and locate them before any other matching routes.
I am trying to use Twitter's Bootstrap (http://twitter.github.com/bootstrap/index.html) with Ruby on Rails (v 3.2.8 with Ruby 1.9.3). I am using Devise for authentication.
Twitter has a nice sign-in form in their navbar. (see http://twitter.github.com/bootstrap/examples/hero.html?)
How would I set up my Rails application to use that login? I can set Rails up to login from its own login page, but how do I use the Navbar login? What would be the controller/model structure?
I found this on github, but it does not implement the navbar signup (https://github.com/RailsApps/rails3-bootstrap-devise-cancan/).
Thanks
UPDATE:
Found the answer : https://github.com/plataformatec/devise/wiki/How-To:-Display-a-custom-sign_in-form-anywhere-in-your-app
You can simply run rails g devise:views and customize the form to display correctly inside the nabvar. The you render it with a render 'devise/sessions/new' inside any of your layouts. For more detail look here.
The code from the example has the following after the tag.
<form class="navbar-form pull-right">
<input class="span2" placeholder="Email" type="text">
<input class="span2" placeholder="Password" type="password">
<button type="submit" class="btn">Sign in</button>
</form>
I would use this code, but change the form's action and input names to that of my login form.
Just view the source code of your login form and change the necessary values. You could also add in some code similar to below so that it will not show the login form if they are already authenticated.
<% if not current_user %>
//login form
<% else %>
//welcome the user and provide logout option
<% end %>
I'm having a hard time getting the "active" class to stay across different pages. I have the navbar loading on each page via a layout, could this be the issue?
I just have this inside my layout gsp for creating the navbar, and it works perfectly. I only have items in the navbar at the level of the controller, not for individual actions.
<li ${controllerName.equals('schedule') ? 'class="active"' : ''}>Schedule</li>
For the default controller generated by Grails, you can use
<li ${controllerName == null ? 'class="active"' : ''}>Home</li>
Yes, that is the issue.
Whenever you reload the page, whatever <li> element has class=active will be set to active again.
If you have /grails-app/views/layouts/main.gsp with the following:
<div class="navbar">
<div class="navbar-inner">
<ul class="nav">
<li class="active">Home</li>
<li>Fred</li>
<li>Barney</li>
</ul>
</div>
</div>
And your GSPs for Fred and Barney use the main.gsp layout, when you click on them, you will load the code above and the link for "Home" will still be active.
Solutions are to write a Taglib for the Navbar control, or create separate layout pages.
Im developing a webapp that is feeded via a server. Its index presents some shops deals, having all of these deals ann id. In the .gsp, i have this code:
<div id="content">
<g:each in='${promos}' var='promo'>
<div id="up_box"></div>
<div class="deal_container">
<div class="images_container"><img src="${createLink(action:'showImage',controller:'image',id:promo.fotoPrincipal.id)}" width="120" height="105" />
</div>
<g:link controller='promotion' action='openPromo' params="[promoid:promo.id]">
<div class="oferta">${promo.name}</div>
</g:link>
<g:link controller='promotion' action='openPromo' params="[promoid:promo.id]">
<div class="flecha">
</div>
</g:link>
</div>
That means, when I click in one of the links, it will open an url like this:
app/promotion/openPromo/3
In case the deal with the id "3" is clicked. I have a "general" deal details page. I want that page to load always, and fulfill its details dinamically, depending the deal the user clicked. How can I do that?
I don't know if I have been clear in my explanation, if i haven't please ask.
Thank you!
Both links will be handled by the openPromo action in the PromotionController and will be passed the id of the promo as promoid.
You can then load the appropriate promo along with any other related offers you want the user to see and give these to the view. Eg:
class PromotionController {
def openPromo() {
Promo promo = Promo.get(params.promoid)
// Load any other relevant data or offers
render (view:'openPromo', model:[promo:promo, <any other model data here>]
}
}
You can then use the model data in your gsp.
You can do it adding that general info to a Template and then render it from the Controller like this
// render a template to the response for the specified model
def theShining = new Book(title: 'The Shining', author: 'Stephen King')
render(template: "book", model: [book: theShining])
You´ve got more info about the render in this link from the Grails documentation.
http://grails.org/doc/latest/ref/Controllers/render.html
It´s easy to do it, you can add a createLink like the first ones whith calls to an action who will render that template.
Hope it helps ;) and good luck!
I did it this way, after asking my workmate:
def openPromo() {
Promotion promo = Promotion.get(params.promoid)
[promo:promo]
}
Almost what you said David, but without rendering, if I name openPromo my gsp.
Thank you!