package fi.otavanopisto.muikku.plugins.data;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import fi.otavanopisto.muikku.controller.PluginSettingsController;
import fi.otavanopisto.muikku.dao.security.PermissionDAO;
import fi.otavanopisto.muikku.dao.security.RolePermissionDAO;
import fi.otavanopisto.muikku.dao.security.UserGroupRolePermissionDAO;
import fi.otavanopisto.muikku.dao.users.EnvironmentRoleEntityDAO;
import fi.otavanopisto.muikku.dao.users.RoleEntityDAO;
import fi.otavanopisto.muikku.dao.users.SystemRoleEntityDAO;
import fi.otavanopisto.muikku.dao.users.UserGroupEntityDAO;
import fi.otavanopisto.muikku.dao.workspace.WorkspaceRoleEntityDAO;
import fi.otavanopisto.muikku.model.security.Permission;
import fi.otavanopisto.muikku.model.security.RolePermission;
import fi.otavanopisto.muikku.model.users.EnvironmentRoleArchetype;
import fi.otavanopisto.muikku.model.users.EnvironmentRoleEntity;
import fi.otavanopisto.muikku.model.users.RoleEntity;
import fi.otavanopisto.muikku.model.users.SystemRoleType;
import fi.otavanopisto.muikku.model.users.UserGroupEntity;
import fi.otavanopisto.muikku.model.workspace.WorkspaceRoleArchetype;
import fi.otavanopisto.muikku.model.workspace.WorkspaceRoleEntity;
import fi.otavanopisto.muikku.security.MuikkuPermissionCollection;
import fi.otavanopisto.muikku.security.PermissionScope;
public class PermissionsPluginController {
private static final String PLUGIN_NAME = PermissionDataPluginDescriptor.PLUGIN_NAME;
private static final String RESET_ROLES_SETTING = "startupResetRoles";
@Inject
private Logger logger;
@Inject
private PermissionDAO permissionDAO;
@Inject
private RolePermissionDAO rolePermissionDAO;
@Inject
private RoleEntityDAO roleEntityDAO;
@Inject
private EnvironmentRoleEntityDAO environmentRoleEntityDAO;
@Inject
private WorkspaceRoleEntityDAO workspaceRoleEntityDAO;
@Inject
private UserGroupEntityDAO userGroupDAO;
@Inject
private UserGroupRolePermissionDAO userGroupRolePermissionDAO;
@Inject
private SystemRoleEntityDAO systemRoleEntityDAO;
@Inject
private PluginSettingsController pluginSettingsController;
@Inject
@Any
private Instance<MuikkuPermissionCollection> permissionCollections;
@Inject
private Event<PermissionDiscoveredEvent> permissionDiscoveredEvent;
public void resetPermissions() {
resetPermissions(new HashSet<>(roleEntityDAO.listAll()));
}
public void resetPermissions(Set<RoleEntity> resetRoleEntities) {
if (CollectionUtils.isEmpty(resetRoleEntities))
return;
// TODO Only handles environment and workspace scopes
for (MuikkuPermissionCollection collection : permissionCollections) {
logger.log(Level.INFO, "Processing permission collection " + collection.getClass().getSimpleName());
List<String> permissions = collection.listPermissions();
for (String permissionName : permissions) {
Permission permission = permissionDAO.findByName(permissionName);
if (permission != null) {
try {
String permissionScope = collection.getPermissionScope(permissionName);
if (permissionScope != null) {
if (!PermissionScope.PERSONAL.equals(permissionScope)) {
// Current roles
String[] pseudoRoles = collection.getDefaultPseudoRoles(permissionName);
EnvironmentRoleArchetype[] environmentRoles = collection.getDefaultEnvironmentRoles(permissionName);
WorkspaceRoleArchetype[] workspaceRoles = collection.getDefaultWorkspaceRoles(permissionName);
List<RoleEntity> currentRoles = new ArrayList<RoleEntity>();
if (pseudoRoles != null) {
for (String pseudoRole : pseudoRoles) {
RoleEntity roleEntity = roleEntityDAO.findByName(pseudoRole);
if (roleEntity != null) {
currentRoles.add(roleEntity);
}
}
}
if (environmentRoles != null) {
for (EnvironmentRoleArchetype environmentRole : environmentRoles) {
List<EnvironmentRoleEntity> envRoles = environmentRoleEntityDAO.listByArchetype(environmentRole);
currentRoles.addAll(envRoles);
}
}
if (workspaceRoles != null) {
for (WorkspaceRoleArchetype workspaceRole : workspaceRoles) {
List<WorkspaceRoleEntity> wsRoles = workspaceRoleEntityDAO.listByArchetype(workspaceRole);
currentRoles.addAll(wsRoles);
}
}
logger.info(String.format("Permission %s applies to %d roles", permissionName, currentRoles.size()));
if (PermissionScope.ENVIRONMENT.equals(permissionScope) || PermissionScope.WORKSPACE.equals(permissionScope)) {
List<RolePermission> databasePermissions = rolePermissionDAO.listByPermission(permission);
removeNonHandledRoles(currentRoles, databasePermissions, resetRoleEntities);
for (RolePermission databasePermission : databasePermissions) {
int index = indexOfRoleEntity(currentRoles, databasePermission);
if (index >= 0) {
currentRoles.remove(index);
}
else {
logger.info(String.format("Removing %s from %s", databasePermission.getRole().getName(), permission.getName()));
rolePermissionDAO.delete(databasePermission);
}
}
for (RoleEntity currentRole : currentRoles) {
logger.info(String.format("Adding environment role %s for %s", currentRole.getName(), permission.getName()));
rolePermissionDAO.create(currentRole, permission);
}
}
}
}
}
catch (Exception e) {
logger.log(Level.SEVERE, "Permission handling failed for " + permissionName);
}
}
}
}
}
private void removeNonHandledRoles(List<RoleEntity> defaultRoles, List<RolePermission> databaseRoles,
Set<RoleEntity> resetRoles) {
for (int i = defaultRoles.size() - 1; i >= 0; i--) {
boolean found = false;
for (RoleEntity re : resetRoles) {
if (re.getId().equals(defaultRoles.get(i).getId())) {
found = true;
break;
}
}
if (!found) {
defaultRoles.remove(i);
}
}
for (int i = databaseRoles.size() - 1; i >= 0; i--) {
boolean found = false;
for (RoleEntity re : resetRoles) {
if (re.getId().equals(databaseRoles.get(i).getRole().getId())) {
found = true;
break;
}
}
if (!found) {
databaseRoles.remove(i);
}
}
}
public void checkForResetPermissions() {
String resetRoles = pluginSettingsController.getPluginSetting(PLUGIN_NAME, RESET_ROLES_SETTING);
if (StringUtils.isNotBlank(resetRoles)) {
try {
String[] roles = resetRoles.split(",");
Set<RoleEntity> resetRoleEntities = new HashSet<>();
for (String role : roles) {
long roleId = Long.parseLong(role);
RoleEntity roleEntity = roleEntityDAO.findById(roleId);
if (roleEntity != null)
resetRoleEntities.add(roleEntity);
else
logger.log(Level.SEVERE, String.format("RoleEntity not found (%d)", roleId));
}
resetPermissions(resetRoleEntities);
} finally {
pluginSettingsController.setPluginSetting(PLUGIN_NAME, RESET_ROLES_SETTING, "");
}
}
}
private int indexOfRoleEntity(List<RoleEntity> roleEntities, RolePermission databasePermission) {
for (int i = 0; i < roleEntities.size(); i++) {
if (roleEntities.get(i).getId().equals(databasePermission.getRole().getId())) {
return i;
}
}
return -1;
}
public void processPermissions() {
logger.log(Level.INFO, "Starting permission gathering");
// Ensure the system roles exist
for (SystemRoleType systemRoleType : SystemRoleType.values()) {
if (systemRoleEntityDAO.findByRoleType(systemRoleType) == null)
systemRoleEntityDAO.create(systemRoleType.name(), systemRoleType);
}
// Process permissions
for (MuikkuPermissionCollection collection : permissionCollections) {
logger.log(Level.INFO, "Processing permission collection " + collection.getClass().getSimpleName());
List<String> permissions = collection.listPermissions();
for (String permissionName : permissions) {
Permission permission = permissionDAO.findByName(permissionName);
if (permission == null) {
logger.log(Level.INFO, "Recording new permission " + permissionName);
try {
final String permissionScope = collection.getPermissionScope(permissionName);
if (permissionScope != null) {
permission = permissionDAO.create(permissionName, permissionScope);
if (!PermissionScope.PERSONAL.equals(permissionScope)) {
String[] pseudoRoles = collection.getDefaultPseudoRoles(permissionName);
EnvironmentRoleArchetype[] environmentRoles = collection.getDefaultEnvironmentRoles(permissionName);
WorkspaceRoleArchetype[] workspaceRoles = collection.getDefaultWorkspaceRoles(permissionName);
List<RoleEntity> roles = new ArrayList<RoleEntity>();
if (pseudoRoles != null) {
for (String pseudoRole : pseudoRoles) {
RoleEntity roleEntity = roleEntityDAO.findByName(pseudoRole);
if (roleEntity != null)
roles.add(roleEntity);
}
}
if (environmentRoles != null) {
for (EnvironmentRoleArchetype envRole : environmentRoles) {
List<EnvironmentRoleEntity> envRoles = environmentRoleEntityDAO.listByArchetype(envRole);
roles.addAll(envRoles);
}
}
if (workspaceRoles != null) {
for (WorkspaceRoleArchetype arc : workspaceRoles) {
List<WorkspaceRoleEntity> wsRoles = workspaceRoleEntityDAO.listByArchetype(arc);
roles.addAll(wsRoles);
}
}
switch (permissionScope) {
case PermissionScope.ENVIRONMENT:
case PermissionScope.WORKSPACE:
for (RoleEntity role : roles) {
rolePermissionDAO.create(role, permission);
}
break;
case PermissionScope.USERGROUP:
List<UserGroupEntity> userGroups = userGroupDAO.listAll();
for (RoleEntity role : roles) {
// TODO Workspace creation & templates - is this necessary and bulletproof?
for (UserGroupEntity userGroup: userGroups) {
userGroupRolePermissionDAO.create(userGroup, role, permission);
}
}
break;
default:
permissionDiscoveredEvent.select(new PermissionScopeBinding() {
private static final long serialVersionUID = 9009824962970938515L;
@Override
public String value() {
return permissionScope;
}
}).fire(new PermissionDiscoveredEvent(permission));
break;
}
}
}
else
logger.log(Level.WARNING, "PermissionScope null for " + permissionName);
} catch (Exception e) {
logger.log(Level.SEVERE, "Permission handling failed for " + permissionName);
}
}
}
}
logger.log(Level.INFO, "Finished permission gathering");
}
}