copy one role permission to another role - liferay

I have come across a scenario where I need to assign same set of permissions to multiple roles (Note: Roles are of same type like Regular-Regular etc).
For example: I have created three regular roles "test_role_A", "test_role_B" and "test_role_C". These three roles would have same permissions.
So I am wondering If I can assign test_role_A role permissions to test_role_B and test_role_C at one go.
Is there any configuration in Liferay to do so?

After some research I observed that RoleLocalServiceUtil has methods like reassignPermissions, mergePermissions which are not fully satisfying my requirement.
However, I found that
ResourcePermissionLocalServiceUtil.addResourcePermissions(resourceName,
roleName, scope, resourceActionBitwiseValue)
would help my cause.
So here is the beanshell script which will help you copy one role permission to another role of same type.
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
import com.liferay.portal.model.ResourcePermission;
import java.util.List;
import com.liferay.portal.service.RoleLocalServiceUtil;
import com.liferay.portal.model.Role;
long companyId = PortalUtil.getCompanyId(actionRequest);
Role fromRole = RoleLocalServiceUtil.getRole(companyId, "<fromRoleName>");
List resourcePermissionList = ResourcePermissionLocalServiceUtil.getRoleResourcePermissions(fromRole.getRoleId());
//array of role names to which permissions needs to be copied
String [] copyToRoles = new String [] {"<ToRoleName1>", "<ToRoleName2>"};
for(String copyToRoleStr: copyToRoles){
try{
Role copyToRole = RoleLocalServiceUtil.getRole(companyId, copyToRoleStr);
try{
for(int i=0;i< resourcePermissionList.size();i++){
ResourcePermission rp = resourcePermissionList.get(i);
ResourcePermissionLocalServiceUtil.addResourcePermissions(rp.getName(), copyToRole.getName(), rp.getScope(), rp.getActionIds());
}
out.println("Successfully Assigned permissions of "+fromRole.getName()+" to "+copyToRole.getName());
}catch(Exception e){
out.println("Error occured while adding resource permission against role - "+copyToRoleStr+" : "+e.getMessage());
}
}catch(Exception e){
out.println("Error occured while fetching role - "+copyToRoleStr+" : "+e.getMessage());
}
}

Related

How to get all users of a site role in Liferay 6.1?

I have LDAP imported user groups which I have mapped to site roles (as mapping them to organization roles was not possible for Liferay 6.1).
So for example I have mapped the user group 'my_site administrators' to the site role 'Site Administrators' of the site 'my_site'.
How can I get all the users that are members of a site role taking into account the user group memberships too?
I have tried the following code but did not work.
Set<User> siteMembers = new HashSet<User>();
Group group = GroupLocalServiceUtil.getGroup(layout.getGroupId());
Integer[] types = new Integer[]{Integer.valueOf(2)}; //site roles
List<Role> siteRoles = RoleLocalServiceUtil.search(group.getCompanyId(), null, types, 0, 10, null);
Set<UserGroupRole> siteUserGroupRoles = new HashSet<UserGroupRole>();
for (Iterator<Role> iterator = siteRoles.iterator(); iterator.hasNext();) {
Role siteRole = (Role) iterator.next();
List<UserGroupRole> userGroupRoles = UserGroupRoleLocalServiceUtil.getUserGroupRolesByGroupAndRole(group.getGroupId(), siteRole.getRoleId());
siteUserGroupRoles.addAll(userGroupRoles);
}
for (Iterator<UserGroupRole> it1 = siteUserGroupRoles.iterator(); it1.hasNext();) {
UserGroupRole userGroupRole = (UserGroupRole) it1.next();
User userGroupUser = userGroupRole.getUser();
siteMembers.add(userGroupUser);
}
Finally found the following solution:
Set<User> siteMembers = new HashSet<User>();
Group group = GroupLocalServiceUtil.getGroup(layout.getGroupId());
long groupId = group.getGroupId();
Integer[] types = new Integer[]{Integer.valueOf(2)}; //site roles
List<Role> siteRoles = RoleLocalServiceUtil.search(group.getCompanyId(), null, types, 0, 10, null);
Set<UserGroupGroupRole> siteUserGroupGroupRoles = new HashSet<UserGroupGroupRole>();
for (Iterator<Role> iterator = siteRoles.iterator(); iterator.hasNext();) {
Role siteRole = (Role) iterator.next();
List<UserGroupGroupRole> userGroupGroupRoles = UserGroupGroupRoleLocalServiceUtil.getUserGroupGroupRolesByGroupAndRole(groupId, siteRole.getRoleId());
siteUserGroupGroupRoles.addAll(userGroupGroupRoles);
}
for (Iterator<UserGroupGroupRole> it1 = siteUserGroupGroupRoles.iterator(); it1.hasNext();) {
UserGroupGroupRole userGroupGroupRole = (UserGroupGroupRole) it1.next();
long userGroupId = userGroupGroupRole.getUserGroupId();
List<User> userGroupUsers = UserLocalServiceUtil.getUserGroupUsers(userGroupId);
siteMembers.addAll(userGroupUsers);
}
siteMembers.addAll(UserLocalServiceUtil.getGroupUsers(groupId));
It does not seem straight-forward. I would expect a method fetching all site members, even the indirect ones through site role-user group-user mapping.
I had to fetch separately all users belonging to all user groups having a site role association with the site and on top of that fetch all users with direct membership to the site.
Any other more straight-forward solution would be welcome.
When we associate any site roles to user then association will be stored in UserGroupRole table.When ever we want get site roles then we have to use respective service class to access those roles like we need use UserGroupRoleLocalService.java class there we can find many service methods.
UserGroupRoleLocalServiceUtil.getUserGroupRolesByGroupAndRole(themeDisplay.getScopeGroupId(),supervisorRole.getRoleId());
And then you can get userId from UserGroupRole object.

SharePoint permissions for a specific group

I'm trying to establish whether a specific group has Read access to a particular site collection.
I have been trying for a day and a half but feel as if I have found three halves of different solutions!
The code fragments I have so far are:
using (SPSite site = new SPSite(this.GenerateAbsoluteUri(moduleCode, academicYear)))
{
using (SPWeb web = site.OpenWeb())
{
for (int i = web.SiteGroups.Count - 1; i >= 0; i--)
{
SPGroup group = web.SiteGroups[i];
if (Regex.IsMatch(group.Name, theGroupImLookingFor))
{
but then what?!
Most of my Google results tell me about roles but I don't know how to tie a role to a group.
Please help!
To assign permission to a user (account) or a SharePoint group there are some objects that we need to look at in a certain order. The first thing we need to do is get the the security principal that we want to assign the role to (SPUser or SPGroup). The next thing we need to do it get the actual permission (role) that we want to assign (ex: Read, Full Control etc…). Then we need to create a SPRoleAssignment object and on the constructor pass it in the SPUser or SPGroup (security principal) that we want to assign the permissions to. Now we need to add the role definition to the RoleDefinitionBindings collection of the role assignment object. Then we need to add the actual role assignment to the web (site) and update the web. Below is the full code lisitng.
// Create the site that contains our list
using(SPSite oSite = new SPSite("<<my site url>>"))
{
// Open the web object
using(SPWeb oWeb = oSite.OpenWeb())
{
// Get the group that we want to add the user to
SPGroup oGroup = oWeb.Groups["<<group name>>"];
// Get the role definition we want to assign ex: Full Control
SPRoleDefinition oRole = oWeb.RoleDefinitions["<< role name>>"];
// Create the role assignment object
SPRoleAssignment oRoleAssignment = new SPRoleAssignment(oGroup);
// Add the role definition to the role assignemnt.
// This will assign the specific permission to the security principal for this role assignemnt.
oRoleAssignment.RoleDefinitionBindings.Add(oRole);
// Now we need to add the role assignment to the web
oWeb.RoleAssignments.Add(oRoleAssignment);
// Now update the web
oWeb.Update();
}
}
Heres snippets from my own code (Sharepoint 2010).
Creating a role:
SPRoleDefinition network_role = new SPRoleDefinition();
network_role.BasePermissions = SPBasePermissions.AddListItems |
SPBasePermissions.BrowseDirectories |
SPBasePermissions.EditListItems |
SPBasePermissions.DeleteListItems;
network_role.Name = "Network - Project Member";
network_role.Description = "Provides permissions required for a member of a project.";
web.RoleDefinitions.Add(network_role);
Adding a role to a group:
var assign = new SPRoleAssignment(oweb.SiteGroups["Network Project - " + item.Code]);
assign.RoleDefinitionBindings.Add(network_role);

How can I list all SPUser objects in a SPGroup?

I need to retrieve all SPUser's from a SPGroup. Unfortunately, the group may contain Active Directory groups, so a simple SPGroup.Users is not enough (I'd just get a single SPUser for the AD group, with the IsDomainGroup property set to true).
Does anyone have a good idea how can I obtain a list of all SPUser's, descending into any Active Directory groups contained in a SPGroup? Is there an alternative to SPGroup.ContainsCurrentUser that takes a SPUser parameter?
Based on a blog post I found, I have written the following code:
private static List<SPUser> ListUsers(SPWeb web, SPPrincipal group)
{
try
{
web.Site.CatchAccessDeniedException = false;
var users = new List<SPUser>();
foreach(SPUser user in web.SiteUsers)
{
using(var userContextSite = new SPSite(web.Site.ID, user.UserToken))
{
try
{
using (var userContextWeb = userContextSite.OpenWeb(web.ID))
{
try
{
if (userContextWeb.SiteGroups[group.Name]
.ContainsCurrentUser)
users.Add(user);
}
catch (SPException)
{
// group not found, continue
}
}
}
catch(UnauthorizedAccessException)
{
// user does not have right to open this web, continue
}
}
}
return users;
}
finally
{
web.Site.CatchAccessDeniedException = true;
}
}
I don't like the fact that I have to impersonate every single user, and this code will only find AD users that have already been imported into SharePoint (so an SPUser exists for them), but that's good enough for me.
Unfortunately, it may be the case that not every member of the AD group has a corresponding SPUser object in the site (yet).
In this scenario, I'd enumerate all the members of the active directory group, and force them into the site with the SPWeb's EnsureUser() method, which returns an SPUser, and creates a new one if it doesn't already exist in the site.
For guidance on enumerating active directory members, see Get List of Users From Active Directory In A Given AD Group.

Creating a custom Document Library in SharePoint

I have a document library in my SharePoint page and there are 10 documents in it.
If User A is logged in I want him to only see 5 of those documents in that document library.
How can I create some custom document library for this to work?
I have MOSS installed.
Thanks in advance!
You could configure different permissions on each document in the document library. Just select the "Manage Permissions" option on each item and break the permission inheritance from the document library level. Just note that having too many documents with item level permissions can create a maintenance nightmare for you. Another option could be to create two document libraries with different permissions.
Write an ItemEventReceiver that breaks the permissions based on a field in the library, i.e. a column that holds the different roles .
We have done this by creating a list that holds all roles coupled to sharepoint groups.
i.e.
Administrator -> Owners of website (SPGroup), Company Administrators (SPGroup)
Managers -> Managers (SPGroup)
then in our content type we have a lookup column to this list.
Here's the code for the ItemEventReceiver:
public override void ItemUpdated(SPItemEventProperties properties)
{
lock (_lock)
{
try
{
using (SPSite site = new SPSite(properties.SiteId,
properties.ListItem.ParentList.ParentWeb.Site.SystemAccount.UserToken))
using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
{
web.AllowUnsafeUpdates = true;
var item = web.Lists[properties.ListId].GetItemById(properties.ListItemId);
var roles = item["Roles"] as SPFieldLookupValueCollection;
var rolesList = web.Site.RootWeb.Lists["Company Roles"];
var groupsToAdd = new List<SPFieldUserValue>();
if (item.HasUniqueRoleAssignments)
{
item.ResetRoleInheritance();
item = item.ParentList.GetItemById(item.ID);
}
if (roles != null && roles.Count > 0)
{
// Iterate over the roles and see if there is a group associated
foreach (var role in roles)
{
var roleItem = rolesList.GetItemById(rol.LookupId);
if (roleItem != null)
{
// This is the SPgroup field in the rolesList
var groups = roleItem["Groups"] as SPFieldUserValueCollection;
if (groups != null)
{
groupsToAdd.AddRange(from g in groups
where g.User == null
select g);
}
}
}
if (groupsToAdd.Count > 0)
{
item.BreakRoleInheritance(false);
foreach (var value in groupsToAdd)
{
var group = web.Groups[value.LookupValue];
var assignment = web.RoleAssignments.GetAssignmentByPrincipal(group);
item.RoleAssignments.Add(assignment);
}
}
}
DisableEventFiring();
item.SystemUpdate(false);
EnableEventFiring();
}
}
catch (Exception ex)
{
//LOG ERROR
}
}
}
If the coding doesn't work for you, and you'd rather not set permissions on each file, then there is a third option. We use folders with permissions set on them.
e.g.
Create a folder called "Managers", break permissions, and set rights to only the managers.
Create another folder called "Employee 1", break permissions, and set Contribute rights to the Employee and the Employe's manager.
Place the files in the appropriate folders and it will inherit rights from the folder.
This way, managers can see the manager files, and all files of their employees. Users can only see their own files.
Similar logic can be done for Headquarters, Region 1, Region 2, etc ... and creating different Groups for each region and then assigning the group to the folder's permissions.
Note, there's always concern in using this design on maintaining all the permissions and on performance, but we've been doing similar things for 750+ user populations and thousand of docs and it's been working fine for us so far.

How to design a User Object Model using MS Roles & Membership

I would like to build a ‘User’ Object model for a somewhat typical web application…however I cannot decide how best to design the object model & role system.
Basically I plan to have about 4 user types…which will correspond to user ‘roles’ in the membership provider.
These types will be:
• Worker
• Employer
• Guest
• Admin
The super type is:
• User
In addition – a User could be both a ‘Worker’ & an ‘Employer’ at times.
I would like to use the MS Roles & Membership provider & have navigation UI set to respond to User Role.
My question is:
How can I best design these Users to be flexible (User can be Worker & Employer).
How do I handle the Login / Roles Procedure?
(I am thinking about a User with a Factory for ‘Behavior’ objects (worker behavior, Employer Behavior ) )
For Login-User logins in … finds its role and Casts to its subtype.
Is this how it should be done?
Using just the concept of role by itself has always proven to be in adequate for me. It doesn't provide low enough granularity to control permissions. AS an example you may have a worker role and and an admin role and then in code you use principal.IsInRole("Admin") to check their role to determine if they can modify some value (say salary). Then someone changes their mind and says that supervisors can change salaries but still aren't admins. Now you have to go change you access check to add in another role check. Painful and routine.
So what I do is make a list of all the features in the application and then allow them to be associated in to a role all in the database. The my access checks look like principal.HasPermission("CHANGESALARY"). I load up the users permissions based on the role they are attached to when they log in. This way the business can create as many groups of features they want and name them. They can then be applied to any user.
I create a custom principal object and attach it to the thread so that I can use it in any code throughout the page life cycle. This object has the code for loading the permissions from the database and the methods for checking permissions.
I generally find that the "providers" in the framework are good for a small class of applications and come up short for most needs. By the time you are done bending them to your will, it would have been easier to just write it from scratch.
To be honest, this is probably not a very good solution, but it might help to generate some other ideas.
My Roles are all of the possible combinations of permissions:
Worker, Employee, Guest, Admin, WorkerEmployee, etc
In my code I have an enum for the individual permissions
[Flags]
public enum RolePermissions
{
Guest = 1,
Worker = 2,
Employee = 4,
Admin = 8
}
and I have an enum that corresponds to the Roles in the database. The integer values are the bitwise OR of permissions:
public enum AvailableRoles
{
None = 0,
Guest = RolePermissions.Guest, //1
Worker = RolePermissions.Worker, // 2
Employee = RolePermissions.Employee, // 4
WorkerEmployee = RolePermissions.Worker | RolePermissions.Employee, // 6
Admin = RolePermissions.Admin, // 8
}
Then there's a set of methods I can use to look up permissions and whatnot:
// Used to determine if the currently logged in user has a particular permission (Guest, Worker, Employee, Admin)
public static bool UserHasPermission( RolePermissions rolePermssion )
{
foreach( string role in Roles.GetRolesForUser() )
{
AvailableRoles availableRole = Parse( role );
if( ( (RolePermissions)availableRole & rolePermssion ) == rolePermssion )
return true;
}
return false;
}
// Used to determine whether the currently logged in user is in a specific role
public static bool UserIsInRole( AvailableRoles requestedRole )
{
return UserIsInRole( Membership.GetUser().UserName, requestedRole );
}
// Used to determine whether a specific user is in a specific role
public static bool UserIsInRole( string username, AvailableRoles requestedRole )
{
foreach( string role in Roles.GetRolesForUser( username ) )
{
AvailableRoles actualRole = Parse( role );
if( actualRole == requestedRole )
return true;
}
return false;
}
// Helper method to parse enum
private static AvailableRoles Parse( string role )
{
return (AvailableRoles)Enum.Parse( typeof( AvailableRoles ), role );
}
If you come up with a better method or make improvements, please let me know so I can incorporate it back into my own code. :-)

Resources