/*
$Id: Keyring.java 7689 2019-04-05 11:42:26Z nicklas $
Copyright (C) 2005 Jari Häkkinen, Nicklas Nordborg
Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg, Martin Svensson
Copyright (C) 2007 Johan Enell
This file is part of BASE - BioArray Software Environment.
Available at http://base.thep.lu.se/
BASE is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.
BASE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with BASE. If not, see .
*/
package net.sf.basedb.core;
import net.sf.basedb.core.data.keyring.*;
import net.sf.basedb.core.data.UserData;
import net.sf.basedb.core.data.ProjectData;
import net.sf.basedb.core.data.ShareableData;
import net.sf.basedb.core.data.ItemKeyData;
import net.sf.basedb.core.data.ProjectKeyData;
import net.sf.basedb.core.hibernate.TypeWrapper;
import org.hibernate.HibernateException;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.Collections;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.TimerTask;
/**
Objects of this class holds information about a user's access permissions,
group and role membership. This object is created when a user logs in and
is managed entirely by the SessionControl
. It is never exposed
to client applications.
The object is not populated with information at creation time. It is done
the first time it needs the information. Thereafter, a timer is set to
make sure the information is updated at regular intervals, in case
some adminstrator changes the permissions and/or membership for
the user. The interval is specified by the permission.timeout
value in the base.config
file.
@see SessionControl#login(LoginRequest)
@author Nicklas
@version 2.0
*/
class Keyring
{
/**
Log core events.
*/
private static final org.slf4j.Logger log =
org.slf4j.LoggerFactory.getLogger(Keyring.class);
private static boolean isInitialised = false;
/**
The logged in user's ID.
*/
private final int userId;
/**
Two-dimensional array for holding the permissions for {@link ItemKey}:s.
The first column holds the key ID, the second the {@link Permission}.
Ie. key_id = [0, x], permission = [1, x]
The rows are sorted by key_id in ascending order.
*/
private int[][] itemPermissions;
/**
Two-dimensional array for holding the permissions for {@link RoleKey}:s.
The first column holds the key ID, the second the {@link Permission}.
Ie. key_id = [0, x], permission = [1, x]
The rows are sorted by key_id in ascending order.
*/
private int[][] rolePermissions;
/**
Two-dimensional array for holding the permissions for {@link ProjectKey}:s.
The first column holds the key ID, the second the {@link Permission}.
Ie. key_id = [0, x], permission = [1, x]
The rows are sorted by key_id in ascending order.
*/
private int[][] projectPermissions;
/**
Two-dimensional array for holding the permission for {@link PluginDefinition}:s.
The first column holds the key ID, the second the maximum permission, and
the third the override permissions.
Ie. key_id = [0, x], maxPermission = [1, x], overridePermission = [2, x]
*/
private int[][] pluginPermissions;
/**
Holds the ID of all groups that the user is a
member of, directly or indirectly.
*/
private Set groups;
/**
A subset of the 'groups' set that holds the id of the groups
that has hiddenMembers = false
*/
private Set groupsWithNonHiddenMembers;
/**
Holds the ID and permission of all projects that the user is a
member of, directly or via a group.
*/
private Map projects;
/**
Holds the ID of all users which are members of at least one of the groups
that the logged in user is also a member of.
*/
private Set users;
/**
Holds the ID of all roles that the user is a
member of.
*/
private Set roles;
/**
Holds the ID of the roles that are inactive.
@since 3.11
*/
private Set inactiveRoles;
/**
The active project's ID.
*/
private int projectId;
/**
Holds the logged in user's maximum {@link Permission}
within the active project.
*/
private int maxProjectPermission;
/**
If the running plugin should use specific permissions or not.
*/
private final boolean usePluginPermissions;
/**
The running plugin's ID.
*/
private final int pluginId;
/**
TRUE if the Timer has signaled that it is time to reload the information.
*/
private volatile boolean reload;
/**
A set holding all item keys, which is needed for
efficient listing of shared items.
*/
private Set itemKeys;
/**
A set holding all project keys, which is needed for
efficient listing of shared items.
*/
private Set projectKeys;
private static int ROOT;
private static int EVERYONE;
private static int ALL;
private static int ALL_ITEM;
private static int DENY_ITEM;
static synchronized void init()
{
if (isInitialised) return;
ROOT = SystemItems.getId(User.ROOT);
EVERYONE = SystemItems.getId(Group.EVERYONE);
ALL = Permission.grant(EnumSet.complementOf(EnumSet.of(Permission.DENIED)));
ALL_ITEM = Permission.grant(Permission.DELETE, Permission.SET_OWNER, Permission.SET_PERMISSION);
DENY_ITEM = Permission.grant(Permission.DENIED);
isInitialised = true;
}
/**
Unload all settings.
*/
static synchronized void unload()
{
isInitialised = false;
}
/**
Create a new Keyring
object.
@param userId The ID of the user
@throws BaseException This exception is thrown if there is an error
*/
Keyring(int userId)
throws BaseException
{
assert isInitialised : "Keyring has not been initialised";
this.userId = userId;
this.reload = true;
this.pluginId = 0;
this.usePluginPermissions = false;
}
Keyring(Keyring parent, int pluginId, boolean usePluginPermissions)
{
this.pluginId = pluginId;
this.usePluginPermissions = usePluginPermissions;
synchronized (parent)
{
this.userId = parent.userId;
this.projectId = parent.projectId;
this.reload = true;
this.itemPermissions = parent.itemPermissions;
this.rolePermissions = parent.rolePermissions;
this.projectPermissions = parent.projectPermissions;
this.groups = parent.groups;
this.groupsWithNonHiddenMembers = parent.groupsWithNonHiddenMembers;
this.users = parent.users;
this.projects = parent.projects;
this.roles = parent.roles;
if (parent.inactiveRoles != null)
{
this.inactiveRoles = new HashSet(parent.inactiveRoles);
}
this.maxProjectPermission = parent.maxProjectPermission;
this.itemKeys = parent.itemKeys;
this.projectKeys = parent.projectKeys;
}
}
void setReload(boolean reload)
{
this.reload = reload;
}
boolean getReload()
{
return reload;
}
/**
Reload all permission information
@return TRUE if permissions were loaded successfully, FALSE otherwise
*/
private synchronized boolean reload()
{
if (!getReload()) return true;
setReload(false);
org.hibernate.Session session = null;
org.hibernate.Transaction tx = null;
try
{
session = HibernateUtil.newSession();
tx = HibernateUtil.newTransaction(session);
loadRoles(session);
loadGroups(session);
loadProjects(session);
loadUsers(session);
loadItemKeys(session);
loadRoleKeys(session);
if (projectId != 0)
{
loadMaxProjectPermission(session, null);
loadProjectKeys(session);
}
if (usePluginPermissions && pluginId != 0)
{
loadPluginPermissionKeys(session);
}
// Schedule another reload as configured in base.config
Application.getCoreTimer().schedule(new ReloadTask(),
601000L*Application.permissionTimeout());
}
catch (BaseException ex)
{
log.warn("Exception during Keyring.reload()", ex);
return false;
}
finally
{
if (tx != null) HibernateUtil.commit(tx);
if (session != null) HibernateUtil.close(session);
}
return true;
}
/**
Loads role membership for the user and put that information
in the {@link #roles} variable.
*/
private void loadRoles(org.hibernate.Session session)
throws BaseException
{
Set temp;
try
{
// Get the groups where the user is a direct member
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session, "GET_ROLE_IDS_FOR_USER", Integer.class);
/*
SELECT ur.roleId
FROM UserRoles ur
WHERE ur.userId = :userId
*/
query.setParameter("userId", userId, TypeWrapper.H_INTEGER);
temp = new HashSet(HibernateUtil.loadList(query, null));
roles = Collections.unmodifiableSet(temp);
}
catch (HibernateException ex)
{
throw new BaseException(ex);
}
}
/**
Loads group membership for the user and put that information
in the {@link #groups} and {@link #groupsWithNonHiddenMembers} variables.
*/
private void loadGroups(org.hibernate.Session session)
throws BaseException
{
Set temp;
try
{
// Get the groups where the user is a direct member
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session, "GET_GROUP_IDS_FOR_USER", Integer.class);
/*
SELECT ug.groupId
FROM UserGroups ug
WHERE ug.userId = :userId
*/
query.setParameter("userId", userId, TypeWrapper.H_INTEGER);
temp = new HashSet(HibernateUtil.loadList(query, null));
query = HibernateUtil.getPredefinedQuery(session, "GET_QUOTA_GROUP_ID_FOR_USER", Integer.class);
/*
SELECT usr.quotaGroup.id
FROM UserData usr
WHERE usr.id = :userId
*/
query.setParameter("userId", userId, TypeWrapper.H_INTEGER);
Integer quotaGroupId = HibernateUtil.loadData(query);
if (quotaGroupId != null) temp.add(quotaGroupId);
// Get the parent groups to all of the already loaded groups
if (temp.size() > 0)
{
query = HibernateUtil.getPredefinedQuery(session, "GET_PARENTGROUPS_IDS_FOR_GROUPS", Integer.class);
/*
SELECT DISTINCT gg.parentId
FROM GroupGroups gg
WHERE gg.childId IN (:groups)
AND gg.parentId NOT IN (:groups)
*/
do
{
query.setParameterList("groups", temp, TypeWrapper.H_INTEGER);
} while (temp.addAll(HibernateUtil.loadList(query, null)));
// repeat until no more new groups are found
}
// Finally, add the Everyone group
temp.add(EVERYONE);
groups = Collections.unmodifiableSet(temp);
// Load the subset of groups that has hiddenMembers = false
query = HibernateUtil.getPredefinedQuery(session, "GET_GROUPS_WITH_NONHIDDENMEMBERS", Integer.class);
/*
SELECT grp.id
FROM GroupData grp
WHERE grp.hiddenMembers = false
AND grp.id IN (:groups)
*/
query.setParameterList("groups", groups, TypeWrapper.H_INTEGER);
temp = new HashSet(HibernateUtil.loadList(query, null));
groupsWithNonHiddenMembers = Collections.unmodifiableSet(temp);
}
catch (HibernateException ex)
{
throw new BaseException(ex);
}
}
/**
Loads project membership for the user and put that information
in the {@link #projects} variable.
*/
private void loadProjects(org.hibernate.Session session)
throws BaseException
{
Map temp = new HashMap();
try
{
// Get the projects where the user is the owner
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session, "GET_PROJECT_IDS_FOR_OWNER", Integer.class);
/*
SELECT p.id
FROM ProjectData p
WHERE p.owner = :userId
*/
query.setParameter("userId", userId, TypeWrapper.H_INTEGER);
for (Integer i : HibernateUtil.loadList(query, null))
{
temp.put(i, ALL_ITEM);
}
// Get the projects where the user is a direct member
org.hibernate.query.Query query2 = HibernateUtil.getPredefinedQuery(session, "GET_PROJECTINFO_FOR_USER", UserProjects.class);
/*
SELECT up
FROM UserProjects up
WHERE up.userId = :userId
*/
query2.setParameter("userId", userId, TypeWrapper.H_INTEGER);
for (UserProjects up : HibernateUtil.loadList(query2, null))
{
Integer i = temp.get(up.getProjectId());
temp.put(up.getProjectId(), i == null ? up.getPermission() : up.getPermission() | i);
}
// Get the projects where the user is member via a group
if (groups.size() > 0)
{
org.hibernate.query.Query query3 = HibernateUtil.getPredefinedQuery(session, "GET_PROJECTINFO_FOR_GROUPS", GroupProjects.class);
/*
SELECT DISTINCT gp
FROM GroupProjects gp
WHERE gp.groupId IN (:groups)
*/
query3.setParameterList("groups", groups, TypeWrapper.H_INTEGER);
for (GroupProjects gp : HibernateUtil.loadList(query3, null))
{
Integer i = temp.get(gp.getProjectId());
temp.put(gp.getProjectId(), i == null ? gp.getPermission() : gp.getPermission() | i);
}
}
projects = Collections.unmodifiableMap(temp);
}
catch (HibernateException ex)
{
throw new BaseException(ex);
}
}
/**
Load all users which are member of at least one group where the
logged in user is also a member and put that information
in the {@link #users} variable. If a project is active, also load the members
and owner of that project.
*/
private void loadUsers(org.hibernate.Session session)
throws BaseException
{
Set temp = new HashSet();
try
{
if (groupsWithNonHiddenMembers.size() > 0)
{
// Get the users which are members of the same groups
temp.addAll(User.getAllMembers(session, groupsWithNonHiddenMembers));
}
if (projectId != 0)
{
// Get the owner of the active project
ProjectData pd = HibernateUtil.loadData(session, ProjectData.class, projectId);
temp.add(pd.getOwner().getId());
// Get direct members of the active project
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session, "GET_USER_IDS_FOR_PROJECT", Integer.class);
/*
SELECT up.userId
FROM UserProjects up
WHERE up.projectId = :projectId
*/
query.setParameter("projectId", projectId, TypeWrapper.H_INTEGER);
temp.addAll(HibernateUtil.loadList(query, null));
// Get groups that are direct members of the active project
query = HibernateUtil.getPredefinedQuery(session, "GET_GROUP_IDS_FOR_PROJECT", Integer.class);
/*
SELECT gp.groupId
FROM GroupProjects gp
WHERE gp.projectId = :projectId
*/
query.setParameter("projectId", projectId, TypeWrapper.H_INTEGER);
// Load the direct groups and subgroups
Set projectGroups = Group.getGroupsRecursive(session, HibernateUtil.loadList(query, null));
if (projectGroups.size() > 0)
{
// Finally, filter away groups that has hiddenMembers=true
query = HibernateUtil.getPredefinedQuery(session, "GET_GROUPS_WITH_NONHIDDENMEMBERS", Integer.class);
/*
SELECT grp.id
FROM GroupData grp
WHERE grp.hiddenMembers = false
AND grp.id IN (:groups)
*/
query.setParameterList("groups", projectGroups, TypeWrapper.H_INTEGER);
projectGroups.retainAll(HibernateUtil.loadList(query, null));
}
// Load users that are members of the project groups
temp.addAll(User.getAllMembers(session, projectGroups));
}
users = Collections.unmodifiableSet(temp);
}
catch (HibernateException ex)
{
throw new BaseException(ex);
}
}
/**
Load all {@link ItemKey}:s for the logged in user and put the result
in {@link #itemPermissions}
*/
private void loadItemKeys(org.hibernate.Session session)
throws BaseException
{
try
{
// Load keys shared directly to the logged in user
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session,
"GET_USERKEYS_FOR_USER", KeyPermission.class);
/*
SELECT uk
FROM UserKeys uk
WHERE uk.userId = :userId
*/
query.setParameter("userId", userId, TypeWrapper.H_INTEGER);
List keys = HibernateUtil.loadList(query, null);
// Load keys shared to any of the groups where the user is a member
if (groups.size() > 0)
{
query = HibernateUtil.getPredefinedQuery(session, "GET_GROUPKEYS_FOR_GROUPS", KeyPermission.class);
/*
SELECT gk
FROM GroupKeys gk
WHERE gk.groupId IN (:groups)
*/
query.setParameterList("groups", groups, TypeWrapper.H_INTEGER);
keys.addAll(HibernateUtil.loadList(query, null));
}
// Sort by key_id. See KeyPermission.compareTo
Collections.sort(keys);
int size = keys.size();
itemPermissions = new int[2][size];
int index = -1;
Set temp = new HashSet(size);
// Copy permissions from the List to the array and set.
for (KeyPermission kp : keys)
{
int keyId = kp.getKeyId();
temp.add(keyId);
if ((index >= 0) && (itemPermissions[0][index] == keyId))
{
// Merge permissions if the same keyId appears more than once
itemPermissions[1][index] = itemPermissions[1][index] | kp.getPermission();
}
else
{
index++;
itemPermissions[0][index] = keyId;
itemPermissions[1][index] = kp.getPermission();
}
}
itemKeys = Collections.unmodifiableSet(temp);
// Fill any empty elements at the end so that Arrays.binarySearch will work
for (++index; index < size; ++index)
{
itemPermissions[0][index] = Integer.MAX_VALUE;
itemPermissions[1][index] = Permission.grant(Permission.DENIED);
}
}
catch (HibernateException ex)
{
throw new BaseException(ex);
}
}
/**
Load all {@link RoleKey}:s for the logged in user and put
the result in {@link #rolePermissions}
*/
private void loadRoleKeys(org.hibernate.Session session)
throws BaseException
{
try
{
// Load the role keys from the database
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session, "GET_ROLEKEYS_FOR_USER", RoleKeys.class);
/*
SELECT rk
FROM RoleKeys rk, UserRoles ur
WHERE rk.roleId = ur.roleId AND ur.userId = :userId
ORDER BY rk.keyId
*/
query.setParameter("userId", userId, TypeWrapper.H_INTEGER);
List roleKeys = HibernateUtil.loadList(query, null);
// Copy the permission from the list to the array
int size = roleKeys.size();
rolePermissions = new int[2][size];
int index = -1;
for (RoleKeys rk : roleKeys)
{
if (inactiveRoles != null && inactiveRoles.contains(rk.getRoleId()))
{
continue; // Skip inactive roles
}
int keyId = rk.getKeyId();
if ((index >= 0) && (rolePermissions[0][index] == keyId))
{
// Merge permissions if the same keyId appears more than once
rolePermissions[1][index] = rolePermissions[1][index] | rk.getPermission();
}
else
{
index++;
rolePermissions[0][index] = keyId;
rolePermissions[1][index] = rk.getPermission();
}
}
// Fill any empty elements at the end so that Arrays.binarySearch will work
for (++index; index < size; ++index)
{
rolePermissions[0][index] = Integer.MAX_VALUE;
rolePermissions[1][index] = Permission.grant(Permission.DENIED);
}
}
catch (HibernateException ex)
{
throw new BaseException(ex);
}
}
/**
Load all {@link PluginKeys}:s for the active plugin.
@param session The session to get the query through.
@throws BaseException If there is an error.
*/
private void loadPluginPermissionKeys(org.hibernate.Session session)
throws BaseException
{
try
{
// Load the pluginpermisson keys for the active plugin
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session, "GET_KEYS_FOR_PLUGIN", PluginKeys.class);
/*
SELECT pdk
FROM PluginKeys pdk
WHERE pdk.pluginDefinitionId = :pluginId
ORDER BY pdk.roleKeyId
*/
query.setParameter("pluginId", pluginId, TypeWrapper.H_INTEGER);
List keys = HibernateUtil.loadList(query, null);
// Copy the permissions from the list to the array
pluginPermissions = new int[3][keys.size()];
int index = 0;
for (PluginKeys pdk : keys)
{
pluginPermissions[0][index] = pdk.getKeyId();
pluginPermissions[1][index] = pdk.getGranted();
pluginPermissions[2][index] = pdk.getDenied();
index++;
}
}
catch (BaseException ex)
{
throw new BaseException(ex);
}
}
/**
Load all {@link ProjectKey}:s for the logged in user.
*/
private void loadProjectKeys(org.hibernate.Session session)
throws BaseException
{
try
{
// Load the project keys for the active project
org.hibernate.query.Query query = HibernateUtil.getPredefinedQuery(session, "GET_PROJECTKEYS_FOR_PROJECT", ProjectKeys.class);
/*
SELECT pk
FROM ProjectKeys pk
WHERE pk.projectId = :projectId
ORDER BY pk.keyId
*/
query.setParameter("projectId", projectId, TypeWrapper.H_INTEGER);
List keys = HibernateUtil.loadList(query, null);
// Copy the permissions from the List to the array
projectPermissions = new int[2][keys.size()];
Set temp = new HashSet(keys.size());
int index = 0;
for (ProjectKeys pk : keys)
{
temp.add(pk.getKeyId());
projectPermissions[0][index] = pk.getKeyId();
projectPermissions[1][index] = pk.getPermission() & maxProjectPermission;
index++;
}
projectKeys = Collections.unmodifiableSet(temp);
}
catch (HibernateException ex)
{
throw new BaseException(ex);
}
}
/**
Find out the logged in user's maximum permission to the active project
and put the result in {@link #maxProjectPermission}.
*/
private void loadMaxProjectPermission(org.hibernate.Session session, ProjectData projectData)
throws BaseException
{
assert projectId != 0 : "projectId == 0";
if (projectData == null) projectData = HibernateUtil.loadData(session, ProjectData.class, projectId);
if (projectData.getOwner().getId() == userId)
{
maxProjectPermission = ALL_ITEM;
}
else
{
maxProjectPermission = IntegerUtil.getInt(projects.get(projectId)) | getRolePermissions(Item.PROJECT);
}
}
/**
Get the max project permission within the currently active project.
*/
int getMaxProjectPermission()
{
return maxProjectPermission;
}
/**
Set the active project.
@param projectData The project to make active, or null to
disable it
*/
synchronized void setActiveProject(ProjectData projectData)
throws PermissionDeniedException, BaseException
{
if (getReload() && !reload()) projectData = null;
int oldProjectId = projectId;
if (projectData == null)
{
projectId = 0;
maxProjectPermission = 0;
}
else
{
projectId = projectData.getId();
}
reload = projectId != oldProjectId;
}
/**
Set a roles as inactive (or active).
@return TRUE if the status was changes, FALSE if not
@since 3.11
*/
synchronized boolean setRoleInactive(int roleId, boolean inactive)
{
// Ignore roles that the user is not a member of
if (!roles.contains(roleId)) return false;
if (inactiveRoles == null) inactiveRoles = new HashSet();
boolean changed = inactive ? inactiveRoles.add(roleId) : inactiveRoles.remove(roleId);
// Force permission reload if this changes the inactive roles
reload |= changed;
return changed;
}
/**
Returns the permission value for the specified key or
PERMISSION.DENIED if not found in the array of keys.
@param key The key to look for
@param permissions An array with two columns, the first holds
the key_id and the second the permission
@return The permissions for the key
*/
private int permissionForKey(int key, int[][] permissions)
{
// ROOT always has full permission
if (userId == ROOT) return ALL;
// Search for the key in the array, negative value = not found
int index = Arrays.binarySearch(permissions[0], key);
return index < 0 ? 0 : permissions[1][index];
}
/**
Checks if the DENIED bit is set in the permission.
*/
private boolean isDenied(int permission)
{
return Permission.hasPermission(permission, Permission.DENIED);
}
/**
Get the logged in user's permission to an unspecified item
of a certain {@link Item} type. If {@link Permission#DENIED} is set,
it overrides all other permissions.
@param itemType The item type as defined by the {@link Item} class
@return The permission
*/
int getRolePermissions(Item itemType)
{
if (getReload() && !reload()) return 0;
int roleKeyId = SystemItems.getRoleKeyId(itemType);
int permissions = permissionForKey(roleKeyId, rolePermissions);
return isDenied(permissions) ? DENY_ITEM : permissions;
}
/**
Get the active plugin's permissions to an unspecified item
of a certain {@link Item} type.
@param itemType The item type as defined by the {@link Item} class
@return The permission
*/
PluginPermission getPluginPermissions(Item itemType)
{
if (getReload() && !reload()) return PluginPermission.NO_PLUGIN;
PluginPermission pp = PluginPermission.NO_PLUGIN;
if (pluginPermissions != null)
{
int roleKeyId = SystemItems.getRoleKeyId(itemType);
int index = Arrays.binarySearch(pluginPermissions[0], roleKeyId);
int denied = ALL;
int granted = 0;
if (index >= 0)
{
granted = pluginPermissions[1][index];
denied = pluginPermissions[2][index];
}
pp = new PluginPermission(granted, denied);
}
return pp;
}
/*
Get the logged in user's permission to a {@link Shareable} item.
We combine item permissions and, if a project is active, project permissions.
@param sharableData The {@link ShareableData} object
@return The combined permissions
*/
int getSharedPermissions(ShareableData sharableData)
{
if (getReload() && !reload()) return 0;
ItemKeyData itemKey = sharableData.getItemKey();
int itemPermission = itemKey == null ? 0 : permissionForKey(itemKey.getId(), itemPermissions);
if (projectId != 0)
{
ProjectKeyData projectKey = sharableData.getProjectKey();
itemPermission |= projectKey == null ? 0 : permissionForKey(projectKey.getId(), projectPermissions);
}
return itemPermission;
}
int getAllPermissions(Item itemType, UserData owner, ItemKeyData itemKey, ProjectKeyData projectKey)
{
if (getReload() && !reload()) return 0;
int roleKeyId = SystemItems.getRoleKeyId(itemType);
// Other permissions
int permissions = permissionForKey(roleKeyId, rolePermissions);
if (isDenied(permissions)) return DENY_ITEM;
// Plugin permissions
int granted = 0;
int denied = 0;
if (pluginPermissions != null)
{
int index = Arrays.binarySearch(pluginPermissions[0], roleKeyId);
if (index >= 0)
{
granted = pluginPermissions[1][index];
denied = pluginPermissions[2][index];
}
else
{
denied = ALL_ITEM;
}
}
if (owner != null && owner.getId() == userId) return ALL_ITEM & ~denied;
if (itemKey != null)
{
permissions |= permissionForKey(itemKey.getId(), itemPermissions);
}
if (projectId != 0 && projectKey != null)
{
permissions |= permissionForKey(projectKey.getId(), projectPermissions);
}
return (permissions & ~denied) | granted;
}
Set getRoles()
{
if (getReload()) reload();
return roles;
}
Set getInactiveRoles()
{
if (getReload()) reload();
return inactiveRoles == null ? Collections.emptySet() : inactiveRoles;
}
Set getGroups(boolean onlyWithNonHiddenMembers)
{
if (getReload()) reload();
return onlyWithNonHiddenMembers ? groupsWithNonHiddenMembers : groups;
}
/**
Get all users that share group membership with the logged in user.
Only groups membership in groups that has hiddenMembers=false are
considered.
*/
Set getUsers()
{
if (getReload()) reload();
return users;
}
Map getProjects()
{
if (getReload()) reload();
return projects;
}
Set getItemKeys(Permission permission)
{
if (getReload()) reload();
if (permission == Permission.READ || permission == null)
{
return itemKeys;
}
else
{
Set keys = new HashSet();
int grantValue = permission.grantValue();
for (int i = 0; i < itemPermissions[0].length; ++i)
{
if ((itemPermissions[1][i] & grantValue) == grantValue)
{
keys.add(itemPermissions[0][i]);
}
}
return keys;
}
}
Set getProjectKeys(Permission permission)
{
if (getReload()) reload();
if (this.projectId == 0) return null;
if (permission == Permission.READ || permission == null)
{
return projectKeys;
}
else
{
Set keys = new HashSet();
int grantValue = permission.grantValue();
for (int i = 0; i < projectPermissions[0].length; ++i)
{
if ((projectPermissions[1][i] & grantValue) == grantValue)
{
keys.add(projectPermissions[0][i]);
}
}
return keys;
}
}
private class ReloadTask
extends TimerTask
{
@Override
public void run()
{
setReload(true);
}
}
}