JSF Redirect page based on User role - jsf

I have two types of admin.
Super admin and normal admin.
Both start on the page admin.xhtml.
I want to forward super admin users to super-admin.xhtml and normal admin to normal-admin.xhtml.
How do I do this in JSF (I'm using Spring Security)?

I'm unfamiliar with JSF, but assuming it functions under the hood just like a Spring MVC JSP application, you can have your controller deliver a different page depending on the role(s) held by the user:
#RequestMapping("/admin.xhtml")
#PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_SUPERADMIN')")
public String getAdminPage(Modelmap model, Principal principal) {
Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
for (GrantedAuthority authority : authorities) {
if (authority.toString() == "ROLE_SUPERADMIN") { return "superadminpage"; }
}
//no need to check for admin privileges, since the annotation took care of that
//if you're not using annotations (or #PostAuthorize), you'd have to capture the
//'admin' role as well, and adjust the return statements accordingly.
return "adminpage";
}

Related

Display Email of the logged in user in MVC 5

Can someone please advise how do we display the EmailID of the logged-in user in a View. I am using ASP.NET MVC 5 identity.
Regards,
Ram
Assuming that you are using the user's email as the username then once the user has already been authenticated you can access the name from the User Principal Identity.Name
#if (Request.IsAuthenticated) {
<span>#User.Identity.Name</span>
}
That is the simple approach. If you did not use the email as the username then you will have to attach that info using claims and then you can use an extenion method to retrieve it. I had the reverse problem. I stored the email as the username and needed to get the logged-in user's Full Name to display. I then had to do what I described for you and had to add a custom DisplayName() extension for the IIdentity .
You can easily use the #inject feature call for injecting both UserManager and SignInManager (This feature available in .NET Core).
In your view add the following:
#inject SignInManager<YourUserIdentity> SignInManager
#inject UserManager<YourUserIdentity> UserManager
After the injection, you should be able to work with UserManager and SignInManager methods. For instance:
#if (SignInManager.IsSignedIn(User))
{
<a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">Hello #UserManager.GetUserName(User)</a>
}
else
{
}
Pay attention for passing the User object when you need to reference the current logged in user.
In your case, if you would like to get the logged in Email Address, you can use the following technique:
var loggedInUserName = #UserManager.GetUserName(User);
var loggedInEmail = await UserManager.GetEmailAsync(
UserManager.Users.FirstOrDefault(u => u.UserName == loggedInUserName)
);
Or just keep it inside a ViewBag as you like.
Hope this will be handy for anyone :)

Multiple database application ACL (part 2)

I posted this question Access Control with a multi database application
So I tried putting it into application. Here is the case. I have a mainDB that has an ACL with no roles defined. The User clicks a button and it opens a control for CRUD with a datasource that has a computed filepath to a different database call it appDB. In appDB the ACL has several roles defined, and I have added myself to the ACL and assigned me the roles [Admin] and [Finance]. In this control I have added an After Page Load event that does the following:
var roles = context.getUser().getRoles();
viewScope.put("vsRoles", roles);
Upon opening the page the viewScope vsRoles is [] so it has not recognized that I have an additional set of roles in the appDB. So it would appear that context.getUser().getRoles() only gets my roles at authentication time when I log into the mainDB.nsf, and is not picking up the roles when I open appDB. I need to use the roles to configure what actions a person can perform, plus which documents a user can read and/or edit.
To complicate the issue the user may switch between multiple target application databases and will no doubt have different roles and access to each one.
thanks for the response to my previous question,but I might not have explained it in enough detail.
So, as far as I understood, what you need is to learn what specific roles the user has for the appDb.
context.getUser().getRoles() provides information about the current application (mainDB.nsf in your case). You are accessing appDB.nsf at a data source level. You can use a java method to learn the roles of a specific user in a target database:
public static List<String> getRoles(Database targetDb, String userName) {
ACL acl=null;
List<String> roles=new ArrayList<String>();
try {
acl=targetDb.getACL();
roles.addAll(targetDb.queryAccessRoles(userName));
} catch (NotesException e) {
// failed, nothing to do...
} finally {
if(acl!=null) acl.recycle();
}
return roles;
}
As an example:
Session session=ExtLibUtil.getCurrentSession();
Database appDb=session.getDatabase("", "appdb.nsf");
// Make sure appDb is not null...
List<String> roleList=getRoles(appDb, session.getEffectiveUserName());
ExtLibUtil.getViewScope().put("vsRoles", roleList);

Logged in user can only access 1 page?

Using Orchard 1.6 Iv created a new role 'FactoryWorker'. When this user logs in from the front end I want them to be navigated to one page only.
OrchardLocal/System/ManufacturedProducts
I have set this page to be a print screen of the order details so the factory worker will know what products to get ready for ship out & they wont be able to navigate as no menu appears, but also need the other pages blocked incase the user decides to enter the URL of a page they arnt allowed access to.
This is the only page I want this particular user to be able to access(after they login), and I have added a logout button, which logs out the user and returns them to the home page.
So iv been looking through editing a role, with permissions and content etc...but this all seems to be applying to forms and content in general. where the user can access any content type etc...
So can someone advise me on how to do this?
thanks for any replies
UPDATE
I forgot to mention that this is not a content type, item or part I am talking about.
I have created my own controller & View & VM which is accessible from the dash board (using the AdminMenu, which brings the admin user to OrchardLocal/System/ManufacturedProducts)
I have looked at Orchard.ContentPermissions Feature but it only seems to allow me to 1)Grant permissions for others or 2)Grant permission for own content
any ideas?
You can use a Request Filter, (I do not know if it is the best way) :
FilterProvider – defines the filter applied to each request. Resembles the way default ASP.NET MVC action filters work with the difference that it’s not an attribute. All FilterProvider objects are injected into the request pipeline and are applied to all requests (so you need to check if the current request is suitable for your filter at the beginning of an appropriate method).
From : http://www.szmyd.com.pl/blog/most-useful-orchard-extension-points
So you could implement something like this
public class Filter : FilterProvider, IAuthorizationFilter {
private readonly IAuthenticationService _authenticationService;
public Filter(IAuthenticationService authenticationService) {
_authenticationService = authenticationService;
}
public void OnAuthorization(AuthorizationContext filterContext) {
//If route is the restricted one
if (filterContext.HttpContext.Request.Url.AbsoluteUri.Contains("OrchardLocal/System/ManufacturedProducts")) {
//Get the logged user
IUser loggedUser = _authenticationService.GetAuthenticatedUser();
if (loggedUser == null)
return filterContext.Result = new HttpUnauthorizedResult();
//Get the Roles
var roles = loggedUser.As<IUserRoles>().Roles;
if (!roles.Contains("FactoryUser")) {
//User is not authorized
return filterContext.Result = new HttpUnauthorizedResult();
}
}
}
}
Note: Untested code!
EDIT: Also you could invert the logic and check if the logged user has the role 'FactoryUser' and restrict its access to every page except the one they should see.
Your module can create a new permission (look at one of the permissions.cs files for examples), then create a role that has only that permission. Have your controller action check that permission (again, many examples found by finding usage of the permissions defined in one of the permissions.cs).
You can use the Content Permissions module. Using this module you can attach a content item permission part to a content type. This part allows you to choose which roles can see the content when you create it.

What to do to restrict the user from seeing the page with out login the website?

I want a page has to appear to user after logged in. But if we use that link we can see the page and its content only thing is that it wont be having user data. what to do to prevent this. what can be done in this scenario ?
You can declare a PhaseListener where to redirect to the homepage instead the user is not logged
public void afterPhase(PhaseEvent evt) {
User user =
evt.getFacesContext().getExternalContext().getSessionMap().get(USER_KEY);
if (user == null) {
FacesContext.getExternalContext().redirect("home.xhtml");
}
}
The phase listener can be defined globally, or at view-level with:
<f:view afterPhase="#{bean.afterPhase}">...</f:view>
(in facelets the attribute is called afterPhaseListener)
Use a ServletFilter to check existence of UserData in Session.
If "yes: then forward else forward to error page.
Another option is to use the rendered attribute on tags to check the existence of UserData object.
I'm not familiar with JSF or if it has built in authentication/authorization. But you should be able to apply authentication/access rules directly on your web server.

Accessing the user from a liferay portlet?

I'm attempting to develop a portlet for liferay.
How can I get access to the username and password (and other data liferay has) of the user that's currently logged in?
I'd also like to be able to execute some code when users change their password.
You can get the User ID by calling getRemoteUser() in the PortletRequest object. This is defined by JSR-168 therefore it's cross-portal compatible.
Once you have the ID you can fetch the additional informations by calling getUserById() (a Liferay specific service). This is something not covered by Portlet API specification, so it locks you to the Liferay.
Liferay Specific stuff, here is a code sample to be written in your Portlet Class to retrieve the User:
ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(WebKeys.THEME_DISPLAY);
User user = themeDisplay.getRealUser(); // it gives you the actual Logged in User
//you can also use
// User user = themeDisplay.getUser(); // this would fetch the User you are impersonating
long userId = user.getUserId();
String userName = user.getEmailAddress();
Alternatively;
long userId = themeDisplay.getRealUserId(); // themeDisplay.getUserId();
User user = UserLocalServiceUtil.getUser(userId);
Impersonate User:
Liferay has a concept that admins (or persons with the correct set of permissions) can impersonate a particular user of the portal. Through this they can see how the portal looks to that user.
For executing the code when user change their passwords:
One approach would be to create a hook plugin and overriding the services by extending the UserLocalServiceWrapper class. Then checking for the password change and executing your code inside the your custom class.
Hope this helps.
Or you can just use javascript:
Liferay.ThemeDisplay.getUserId()
There are many nice to haves in the Liferay namespace, take a look at the not so well documented API:
https://www.liferay.com/community/wiki/-/wiki/Main/Liferay+JavaScript+API
https://www.liferay.com/web/pankaj.kathiriya/blog/-/blogs/usage-of-liferay-js-object
Also, take a look at the web services available under localhost:8080/api/jsonws which you can invoke with a javascript call:
Liferay.Service(
'/user/get-user-by-id',
{
userId: 10199
},
function(obj) {
console.log(obj);
}
);
One simple and easy way to get the user in Liferay is PortalUtil.getUser function.
User user = PortalUtil.getUser(portletRequest);

Resources