Conditional context menu with Vaadin grid - contextmenu

In my Vaadin application I have a grid displaying book information. I do need to add a context menu to the grid but it shall be conditional.
For anonymous user (i.e. hasn't logged in yet) there shall be no context menu. For logged in user, menu items shall depend on user privileges. I.e. regular user can only add or edit/delete his personal book review. Admin users shall be able to do more - edit book information, change status, etc.
Shall I set/reset context menu after login occurs? If two users simultaneously using the application, will they get different context menus? When user logged out, shall I set context menu to null?
No code is written yet, therefore I am not providing it here.
You advise will be greatly appreciated.

I found the solution by extending GridContextMenu and adding User property into it;
public class BookContextMenu extends GridContextMenu<Book> {
private User user;
private final PanelsConfig config;
private final GridMenuItem<Book> editBookMenuItem;
private final GridMenuItem<Book> reviewMenuItem;
public BookContextMenu(PanelsConfig panelsConfig) {
super();
this.config = panelsConfig;
this.editBookMenuItem = addItem("Edit book",
event -> event.getItem().ifPresent(book -> {
BookPanel bookPanel = config.getBookPanel();
bookPanel.setBook(book);
bookPanel.open();
}));
this.reviewMenuItem = addItem("Reader's review",
event -> event.getItem().ifPresent(book -> {
ReviewPanel reviewPanel = config.getReviewPanel();
reviewPanel.setUser(user);
reviewPanel.setBook(book);
reviewPanel.open();
}));
if (user == null || !user.isReaderActive()) {
editBookMenuItem.setVisible(false);
reviewMenuItem.setVisible(false);
} else if (!user.isAdmin()) {
editBookMenuItem.setVisible(false);
}
}
public void setUser(User user) {
this.user = user;
if (user == null || !user.isActive()) {
editBookMenuItem.setVisible(false);
reviewMenuItem.setVisible(false);
} else {
this.setEnabled(true);
reviewMenuItem.setVisible(true);
if (user.isAdmin()) {
editBookMenuItem.setVisible(true);
}
}
}
}

Related

Identity Server 4 Multi-tenancy logout

I'm currently developing an identity server. It is multi-tenant with multiple user repositories.
I am able to pass (using Services.OpenIDConnect.Options) my tenant details from my MVC to the IDS in order to select the appropriate user repository on login
options.Events.OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter("Tenant", "TenantDetail");
return Task.CompletedTask;
};
I am attempting to obtain this same information for logout, however the initial call to logout has some back end process that calls CustomProfileService.IsActiveAsync(IsActiveContext context).
I am unable to obtain the tenant information from the IsActiveContext, nor am i able to read any kind of query string (as i was using for login).
Any suggestions, or even alternative methods that might be more correct than what I'm attempting, would be greatly appreciated.
OnRedirectToIdentityProvider will not be hit on signout. You'll need to pass the tenant information in the OnRedirectToIdentityProviderForSignOut event in your client instead.
Here's a snippet, that's far from complete:
services
.AddOpenIdConnect("oidc", options =>
{
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProviderForSignOut = context =>
{
context.ProtocolMessage.AcrValues = "tenant:TenantDetail";
return Task.CompletedTask;
},
}
}
In IdentityServer you'll need to lookup the acr_values in the query parameters from the request. Inject IHttpContextAccessor in order to access the context:
public class ProfileService : IProfileService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ProfileService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
// ...
}
public async Task IsActiveAsync(IsActiveContext context)
{
// Please note that this method is called on many occasions. Check context.Caller
// This means that you'll have to make sure that the acr_valus are present on all
// ocassions, hence the question in my comment.
var request = _httpContextAccessor.HttpContext.Request;
if (request.Method == HttpMethods.Get)
{
// acr_values should be present on all ocassions.
var values = (string)request.Query["acr_values"];
// This is just a sample, you'll need to parse the values.
var tenant = values.Split(':')[1];
}
// Your code where you link the repository ...
var sub = context.Subject.GetSubjectId();
var user = await userManager.FindByIdAsync(sub);
context.IsActive = user != null;
}
}
Please let me know if this solves the issue for you.

How to check if user is member of group

My goal is to check if user is member of specific active directory group.
In .net mvc i was using this code inside my service
HttpContext.Current.Request.LogonUserIdentity.Groups
.Any(x => x.Translate(typeof(NTAccount)).Value == "some role"
and it worked well.
In .net core mvc 2.1.2 i pass IHttpContextAccessor into service constructor and try to use following
_httpAccessor.HttpContext.User.Identity.LogonUserIdentity.Groups
but there is an issue, because Identity does not contains LogonUserIdentity. I tried to find any solution but i was not successful, how can i get the list of user groups or check if user is member of specific one ?
Except using built-in function which check the permission by "Roles", if you want to check by specific AD Group, you can also use below codes :
public static class Security
{
public static bool IsInGroup(this ClaimsPrincipal User, string GroupName)
{
var groups = new List<string>();
var wi = (WindowsIdentity)User.Identity;
if (wi.Groups != null)
{
foreach (var group in wi.Groups)
{
try
{
groups.Add(group.Translate(typeof(NTAccount)).ToString());
}
catch (Exception)
{
// ignored
}
}
return groups.Contains(GroupName);
}
return false;
}
}
And using as:
if (User.IsInGroup("GroupName"))
{
}

using config.groovy in gwt for user preference

I have a gwt and grails legacy app that I'm upgrading and modifying.. Its a reservation calendar basically with different "views".. the problem I'm having is I want the user to be able to choose a default view for themselves upon logging in..I've done this with a grails only application before but gwt is much different..how can I pass something from config.groovy to the gwt part that select which view to show..and this view isn't a view like a grails view..think of it like restaurants..and a user may only want to see the reservations for a particular restaurant instead of the default of all restaurants
Maybe not a direct answer to your question but you can just make a ordinary GWT remote service UserPreferencesService which will store user preferences
public interface UserPreferencesService extends RemoteService {
List<Restaurant> getRestaurants(Account user);
void setRestaurants(Account user, List<Restaurant> restaurants);
}
In your entry point you can then make a decision on what kind of view you'll show to user
public final class Application implements EntryPoint {
private AuthServiceAsync authService =
GWT.create(AuthService.class);
private UserPreferencesAsync preferencesService =
GWT.create(UserPreferencesService.class);
#Override
public void onModuleLoad() {
// handle login
authService.getAccount(new Callback<Account>() {
#Override
public void onSuccess(final Account account) {
// check if user have a preferred restourants
preferencesService.getRestaurants(account,
new Callback<Account>() {
#Override
public void onSuccess(final List<Restaurant> restaurants) {
// user did not select any restaurants yet.
// Show a selection widget
if (restaurants.isEmpty) {
RestaurantSelectorWidget widget =
new RestaurantSelectorWidget();
// your custom handler here
widget.addHandler(new Handler() {
#Override
public void onSelected(/*...*/) {
// save user preferences
// and switch to normal view
}
})
RootPanel.get("container")
.add(widget);
} else {
// show normal view
}
}
}
}
}
}
}
}
Also you may take look to this plugin which is adds GWT support to grails.

Permission Based Authorization with ASP.Net Identity 2

I'm working on a ASP.Net MVC 5 app and using ASP.Net identity 2, and need to authorize users based on roles and permissions. roles and permissions is not related to each other. for example, to access "action1" action method,( "admin" role ) or ( combination of "role1" and "permission1" ) must exist for him, but other users that is not in "admin" role or combination of ( "role1" and "permission1") is not true for theirs, don't allow to access that action method.
how i can do this scenario?
do claims based authorization useful in this manner?
or i must implement Permission entity and custom AuthorizeAttribute? if true how?
best regards
Check out the ResourceAuthorize attribute in the Thinktecture.IdentityModel.Owin.ResourceAuthorization.Mvc package.
This attribute authorizes a user based on an action (e.g. read) and a resource (e.g. contact details). You can then base whether or not they are allowed to perform that action on a resource based on a claim (e.g. their presence in a role).
See here for a good example.
Might not be exactly what you are looking for, but you can take inspiration and implement your own authorization attribute using similar logic.
This is custom made Authorize which checks permission from database.
For example you have 3 bools for permission Account,Clients,Configuration
and you want to restrict user based on them.
you can add even two permission on one action, for example you have a method which can be accessed by Account and Client permission than you can add following line
Modify this to use roles with permissions in this, this is the easiest and best way to handle it.
[PermissionBasedAuthorize("Client, Account")]
This method below is which check the bools from database.
public class PermissionBasedAuthorize : AuthorizeAttribute
{
private List<string> screen { get; set; }
public PermissionBasedAuthorize(string ScreenNames)
{
if (!string.IsNullOrEmpty(ScreenNames))
screen = ScreenNames.Split(',').ToList();
}
public override void OnAuthorization(HttpActionContext actionContext)
{
base.OnAuthorization(actionContext);
var UserId = HttpContext.Current.User.Identity.GetUserId();
ApplicationContext db = new ApplicationContext();
var Permissions = db.Permissions.Find(UserId);
if (screen == null || screen.Count() == 0)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
bool IsAllowed = false;
foreach (var item in screen)
foreach (var property in Permissions.GetType().GetProperties())
{
if (property.Name.ToLower().Equals(item.ToLower()))
{
bool Value = (bool)property.GetValue(Permissions, null);
if (Value)
{
IsAllowed = true;
}
break;
}
}
if (!IsAllowed)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
}
}
I implemented a Permission-based extension for Microsoft Identity 2 membership system. But in this extension, permissions and roles are related together. there is a many-to-many relation between them. Also you can have a complex authentication with combination of roles and permissions. I suppose it can help you to do permission based authentication.
You can do permission authentication in two ways:
First approach:
// GET: /Manage/Index
[AuthorizePermission(Name = "Show_Management", Description = "Show the Management Page.")]
public async Task<ActionResult> Index(ManageMessageId? message)
{
//...
}
Second approach:
// GET: /Manage/Users
public async Task<ActionResult> Users()
{
if (await HttpContext.AuthorizePermission(name: "AllUsers_Management", description: "Edit all of the users information."))
{
return View(db.GetAllUsers());
}
else if (await HttpContext.AuthorizePermission(name: "UnConfirmedUsers_Management", description: "Edit unconfirmed users information."))
{
return View(db.GetUnConfirmedUsers());
}
else
{
return View(new List<User>());
}
}
Also it's an open source and free extension and you can access to the repository here.

MVC 4 - RoleProvider to manage authenticated users permissions with different scopes

Here is my problem with my MVC 4 Internet project using Forms Authentication.
Lets say i have hotels and i want the authorized users accessing each under different roles.
So the user logs in. Then from a dropdownlist selects the target Hotel and the application´s security responds accordingly.
I would need something like [Authorize(Roles = "Administrator")] but only in that hotel scope.
My first aproach was inheriting from AuthorizeAttribute and override AuthorizeCore like is shown in this thread
From there I could get the HttpContext.Session["HotelId"] and query a UserRolesInHotel table. That said, I should have my own roles table with a structure similiar to UserId, RoleId, HotelId. So SimpleRolePrivider comes short to this task and i would be forced to create a CustomeRoleProvider. RoleProvider Methods don´t handle extra params as I need like HotelId when adding a new role to a user.
For clarification:
User A logs in with user/password ->OK (SimpleMembershipProvider)
Authenticated User A selects Hotel 1 -> User A is an "Administrator" for Hotel 1.
Authenticated User A change to Hotel 2 -> User A is a "User" in Hotel 2
I can have any number of hotels.
User A -> Hotel 1 -> { "Administrator", "User"}
User A -> Hotel 2 -> { "User" }
User A -> Hotel 3 -> { "Owner" }
User A -> Hotel 4 -> { "Administrator" }
The list of roles is always the same.
I´ve been struggling with this implementation for a couple of days and i couldn´t come up with a pratical solution.
Any thougths would be much appreciated.
Thanks!
This is what I did:
Added a DefaultBuildingId to the user profile.
Then I created a CustomRoleProvider and overrided GetRolesForUser method like this
public override string[] GetRolesForUser(string userName)
{
if (HttpContext.Current.Session != null)
{
var user = _userRepository.GetByName(userName);
if (!user.IsActive)
{
throw new ApplicationException(string.Format("some message {0}", userName));
}
if (HttpContext.Current.Session["BuildingId"] == null)
{
var building = _buildingRepository.Get(user.DefaultBuildingId);
if (building == null)
{
throw new ApplicationException("error message");
}
HttpContext.Current.Session["BuildingId"] = building.BuildingId;
}
int buildingId = Convert.ToInt32(HttpContext.Current.Session["BuildingId"]);
return _userRepository.GetRolesForUserInBuilding(user.UserId, buildingId).ToArray();
}
throw new ApplicationException("error message.");
}
Added a custom AuthorizeAttribute
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
var repo = UnityManager.Resolve<IUserRepository>();
var buildingId = (int)httpContext.Session["BuildingId"];
var userName = httpContext.User.Identity.Name;
var user = repo.GetByName(userName);
var userRolesInBuilding = repo.GetRolesForUserInBuilding(user.UserId, buildingId);
foreach (var role in Roles.Split(','))
{
if (userRolesInBuilding.Contains(role.Trim()))
{
return true;
}
}
return false;
}
And finally this is how to use it at controller or action level.
[BuildingAthorize(Roles = "Administrators")]
I also added a ddl to the layout to let the user change the building and set the new BuildingId overriding the value at the session/db. This way a user can work in different Hotels during the same session and only access areas and functionality he has for that particular hotel.

Resources