How do have an admin user and how do I hide hyperlinks for non-admin users?
An alternative approach that I use regularly is to have another model called UserGroup. For example:
$ rails g scaffold user_group name:string description:text is_admin:boolean
You would then add a user_group_id:integer to your user model:
$ rails g migration add_user_group_id_to_users user_group_id:integer
In your user model, you could then add two instance methods to help you figure out if any specific user is a "normal" user or an "admin" user:
#app/models/user.rb
def normal?
self.user_group && !self.user_group.is_admin
end
def admin?
self.user_group && self.user_group.is_admin
end
This is probably over-kill for projects where there are only admins and non-admins, but is handy if you have many categories of users, such as ecommerce_manager, story_editor, etc.
I looked long and hard to find out how to do this, in the end it was too simple!
I didn't need route changes, loads of controller code or anything like that.
Just add a field in the database called admin_flag through a migration), then modify the Rails view form for new/edit to use it.
Then on the application/html.erb just add:
<% if current_user %>
<% if current_user.admin_flag == true %>
| <%=link_to(:categories, :categories) %>
| <%=link_to(:users, :users) %>
<% end %>
<% end %>
This will only show users and categories if the user logged in is admin too.
Do this after setting at least one admin user or you will need to use sql to set at least 1 admin user.
Related
How to display default user registration or User Creation form in Portlet/Jsp ?
You just need to build the render-url that renders the jsp.
Take a look at /portal-web/docroot/html/portlet/login/navigation/create_account.jsp as to how the URL is created.
You just need to have this method call PortalUtil.getCreateAccountURL(request, themeDisplay).
so your JSP code might look something like this:
<a href=<%=PortalUtil.getCreateAccountURL(request, themeDisplay)%>> Create Account </a>
Note: I have not tried this, but it should more or less work.
I want to pass a string(username) between my two jsp pages,
Login.jsp and Details.jsp.
Please tell how it can be done?
I tries this in Login.Jsp
<html>
......
<%
session.setAttribute("key","value");
%>
.....
</html>
In Details.jsp
<html>
......
<%
session.getAttribute("key");
%>
.....
</html>
It showed "NULL" as output.
Usually after a login you should save the user data in sessions:
session.setAttribute("key","value");
and then access from other pages with
session.getAttribute("key");
if you need more information there's a lot around: http://www.jsptut.com/sessions.jsp
Try this
jsp1.jsp
request.setAttribute("name",somevalue);
RequestDispatcher dispatcher = request.getRequestDispatcher("jsp2.jsp");
if (dispatcher != null){
dispatcher.forward(request, response);
}
jsp2.jsp
out.println(request.getAttribute("name"));
There are several ways to pass data from one webpage to another:
Put a form on Login.jsp and let it post to Details.jsp. This will post the values in the form to Details.jsp.
Redirect to Details.jsp?username=ARJUN. This will pass a variable to Details.jsp in te query string.
Put the username in a cookie. The cookie will be submitted to Details.jsp (and every other page), which makes it possible to determine the username in every page.
Put the username in the session. Similar to a cookie, but the session is stored on the server and associated with the user that is currently viewing your website.
First create servlet in write this code:
Here we can get the value using requet.getParameter("name"); here, name is textbox name of a previous page
<%! String name=request.getParameter("name")%>
<% out.println("Welcome :"+name) %>
I am using ejs-locals to give me support for partials in express/node.js
The problem is the library has a bug when you include a partial within a partial. The 2nd partial include is trying to find the file relative to the grandparent or page.ejs that called the 1st partial.
So this requires I either flatten out my ./views so all files are only in ./views (no sub-dirs)...or I symlink to the partial from the directory that made the initial partial call.
Perhaps there is another/better way of doing this?
In a lot of my views, I have a face mash, that gives me html with people's avatars. I can't just use <% include faces %> and call it a day, because the collection of people comes from many different objects depending on the page from which it is called.
here's an example:
on an item page, I call <% include stats %>, which calls faces partial
<- partial('faces', { people: item.users }) %>
or on a list page, I call <% include stats %>, which calls faces partial
<- partial('faces' { people: list.users }) %>
The partial 'faces.ejs' just loops over people and spits out a link to their profile. But because I can't include a partial within a partial I'm stuck either sym-linking all over the place or trying something different.
./views/list/index.ejs calls a stats.ejs partial that calls faces.ejs partial...so I need to symlink ./views/list/faces.ejs to ./views/stats/faces.ejs for it to work.
You cannot pass data to a simple include, so I cannot pass in different collections of users depending on the context in which it was called.
<% include faces %> would require the face.ejs loop over either item.users or list.users hardcoded in faces.ejs
What else can I do that will work with nested partials/includes? I have filed a bug with ejs-locals, and a few others have as well, but its been a month w/o any fix.
I'm building a site where staff will have their own section of the site: example.com/jones, example.com/smith, etc. jones and smith are template groups with the same templates inside (using Stash and Low Variables to keep it all DRY). Some users will have different needs for privacy. On one end their section will be public. On the other end some users will need to administer who can access their content (using Solspace friends).
However in the middle of that range are some who just want to protect against any random person seeing their content. I don't want to use members/member groups to manage this. I don't want visitors to need to register to see the content. A shared member account is an option, but we ruled that out because of other issues (what if the password is reset, comments being left under the same account, etc.
What we would like is to password protect the template group. The staff can let people know where to see their page, and let users know what the password is. This is all possible on a server level, but is is possible to allow the user to directly manage the password? Anything we can do to minimize how much we need to have hands on admin of this the better. A custom field and an add on that allows for this kind of security? I didn't see anything on Devot-ee and the methods on the forums don't do this. Bit of a longshot, but figured I'd ask.
Since you said you didn't want to be tied to actual member accounts and were OK with using a custom field to store an editable password...
I just recently did something similar that protected a group of entries using a custom field. It is similar to the approach outlined in this "Password Protected Content Made Simple" article. But instead of using PHP in the template I used Mo' Variables. And instead of using url_title I used a custom field (called client_password below).
In addition, I used the Session Variables plugin to check if the user was already "logged in" on subsequent page loads, preventing them having to enter the password again and again.
{!-- PASSWORD REQUIRED --}
{if client_password != ""}
{!-- if passed show content and set session --}
{if post:password == client_password}
{!-- protected content here --}
{!-- set session --}
{embed='embeds/_set_session' entry_id="{entry_id}"}
{!-- if session is valid show content --}
{if:elseif "{exp:session_variables:get name='logged_in'}" == "{entry_id}"}
{!-- protected content here --}
{!-- if failed show login --}
{if:elseif post:password != "" AND post:password != client_password}
<div id="protected">
<p>Incorrect password. Please try again.</p>
<br>
<form action="" method="post">
<strong>Password</strong><br />
<div>
<input name="password">
</div>
<input type="submit" class="submit" value="submit">
</form>
</div>
{!-- if first attempt show login and prompt --}
{if:else}
<div id="protected">
<p>This page is password protected. Please provide the password.</p>
<br>
<form action="" method="post">
<strong>Password</strong><br />
<div>
<input name="password">
</div>
<input type="submit" class="submit" value="submit">
</form>
</div>
{/if}
{!-- NO PASSWORD REQUIRED --}
{if:else}
{!-- protected content here --}
{/if}
I wanted to update this with the code I'm using to get htaccess and htpasswd working to protect by template group. It can be used in the same way as Alex's, but is an all or nothing approach. It has its own advantages, and disadvantages, but wanted to share it as an option.
First, I am using the native template behavior: example.com/group/template/url_title. I want to password protect some template groups, but outside of EE's members and member groups. ie a single user and password.
My htaccess file looks like this (from http://perishablepress.com/enable-file-or-directory-access-to-your-htaccess-password-protected-site/):
# We set some variables, matching URL's for which we do not wish to active
# the password protection
SetEnvIf Request_URI "^/privategroup.*$" private
# Setup the password protection
AuthName "Password Needed"
AuthGroupFile /dev/null
AuthType Basic
AuthUserFile /Users/user/Sites/example/.htpasswd
Require valid-user
# Add the exceptions for matched URL's
Order Deny,Allow
Deny from env=private
Satisfy any
The htpasswd file should be above webroot, but for testing I left it in webroot. The AuthUserFile line tells Apache where to find the file with the usernames and passwords. This must...MUST be an absolute path. I was using relative and got 500 errors. You need to use terminal or some other tool to make this file. http://developer.apple.com/library/Mac/#documentation/Darwin/Reference/ManPages/man1/htpasswd.1.html
The result is that directory requires a username and password. Right now it will accept any valid user in my htpasswd file. However I can change that by specifying a specific user (require user john tim lisa) or groups.
There you have it. Keep people out of specific template groups without using any native EE functionality.
I will be honest, I'm not sure if this fits your needs or not. It's not clicking that it will though, I've never tried it before and would need to actually give it a go to know for sure that it does or does not fit.
I will post it just the same as it may help you or someone else down the road:
http://koivi.com/ee-entry-auth-dir/
Have you looked at using the HTTP Authentication option under Template Access Restrictions? It uses a member password for authentication, but doesn't require the member to actually be logged-in.
You say you "don't want to use members/member groups to manage this", but then that you want to "allow the user to directly manage the password" ... surely using the built-in member system is the easiest way?
I make security system in mvc application. In MVC it must be done by AuthorizeAttribute and roles string via actions methods.
Could i make this stuff: instead of action resolve I want to make view where html parts are hidden depend on current user permission set (For example: save button are not visible if user not Administrator).
Within your views, you can do conditional checks, such as:
<% if (User.IsInRole("Admin")) { %>
An Admin-only link
<% } %>
In partial views, the User property is not exposed, but you can still do it:
<% var user = HttpContext.Current.User; %>
<% if (user.IsInRole("Admin")) { %>
An Admin-only link
<% } %>
Brian - i don't think this is a good idea to 'hide' the admin parts. you basically then just expose to logic to anyone opening the html in 'view source' mode. it would be better to have an admin view and a 'normal' view and just do a case statement in the contoller action to deliver the appropriate view where required (still not the best option, but far better than hiding fields). better still, have a master view that contains partialviews which are only rendered if it's the correct user type etc..
just my 'view' on the topic..
jim
You can do either A or B
a) Create partial views for the various elements that change and do something like
<% if (HttpContext.Current.User.IsInRole("Administrator"))
{
Html.RenderPartial("AdminStuff");
}
else
{
Html.RenderPartial("RegularStuff");
}
%>
b) Set the role in your viewdata/viewmodel and use it in the code (not recommended as the view should really contain no logic)
In the controller
ViewData["Admin"] = HttpContext.Current.User.IsInRole("Administrator");
In the view
<% if ((bool)ViewData["Admin"]) { %>
<!-- Show admin stuff -->
<% } %>
Thanks to all for your answers. I see that view dynamic render is a bad practic in mvc applications. I'm used to think that there can be some libraries or templates.
BTW When i told to my PM that a string with roles is a common pattern he sad "Hard code!!!!". Now I'm designing some WCF service with will be an "Aplication Authoriser" ))).
Everyone here seems to forget that there is css for such stuff. You can do the thing you want very easily, at least I am doing at already, and it's working flawlessly.
Let me give you a simple example
Make sure your operations buttons/regions have defined css classes
css class: MODULE-OPERATION
e.g.
Module User
Operations: Add, Edit, Delete, List
Add User
Whenever changing (adding/updating/deleting) roles, you generate a css file for each role
e.g.
You decide that only administrators can add users so this css is generated
//admin_css.css
.USER-ADD { display: none; }
Everytime the page is opened you check what role the user has, and based on the role, you load the css file in you header. So your gui correlates to the logic you have in your application without so much hassle.