Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

users and groups synchronization #438

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.configuration.CombinedConfiguration;
import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
Expand All @@ -60,7 +64,7 @@

/**
* Singleton configuration instance used by the Database Visualization Toolkit
*
*
* @author Bruno Ferreira <[email protected]>
*/
public class ViewerConfiguration extends ViewerAbstractConfiguration {
Expand Down Expand Up @@ -100,7 +104,7 @@ public class ViewerConfiguration extends ViewerAbstractConfiguration {

public static final String PROPERTY_AUTHORIZATION_FULLNAME_ATTRIBUTE = "user.attribute.fullname";
public static final String PROPERTY_AUTHORIZATION_EMAIL_ATTRIBUTE = "user.attribute.email";
public static final String PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE = "user.attribute.roles";
public static final String PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE = "user.attribute.roles[]";
public static final String PROPERTY_AUTHORIZATION_ADMINISTRATORS = "user.attribute.roles.administrators";

public static final String PROPERTY_AUTHENTICATED_USER_ENABLE_DEFAULT_ATTRIBUTES = "authenticated.user.enable.default.attributes";
Expand Down Expand Up @@ -132,6 +136,8 @@ public class ViewerConfiguration extends ViewerAbstractConfiguration {
public static final String PROPERTY_BLOB_PREFIX_NAME = "ui.blob.prefix.name";

public static final String SIARD_AVAILABLE_TO_SEARCH_ALL = "ui.siard.available.search.all";
public static final String RELOAD_DBPTK_VIEWER_PROPERTIES = "ui.reload.viewer.properties";
public static final String RELOAD_DBPTK_VIEWER_PROPERTIES_PERIOD = "ui.reload.viewer.properties.period";

private static boolean instantiatedWithoutErrors = true;
private static String applicationEnvironment = ViewerConstants.APPLICATION_ENV_SERVER;
Expand All @@ -153,7 +159,10 @@ public class ViewerConfiguration extends ViewerAbstractConfiguration {

// Configuration related objects
private static CompositeConfiguration viewerConfiguration = null;
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private static CombinedConfiguration combinedConfiguration = new CombinedConfiguration();
private static List<String> configurationFiles = null;
private static List<String> commonConfigurationFiles = null;

private List<String> cachedWhitelistedIPs = null;
private List<String> cachedWhiteListedUsername = null;
Expand Down Expand Up @@ -281,15 +290,32 @@ private ViewerConfiguration() {

// load core configurations
configurationFiles = new ArrayList<>();
addConfiguration("dbvtk-viewer.properties");
LOGGER.debug("Finished loading dbvtk-viewer.properties");
commonConfigurationFiles = new ArrayList<>();

commonConfigurationFiles.add("dbvtk-viewer.properties");
commonConfigurationFiles.add("users-groups.properties");
addCommonConfiguration();
LOGGER.debug("Finished loading " + String.join(" , ", commonConfigurationFiles));

addConfiguration("dbvtk-roles.properties");
LOGGER.debug("Finished loading dbvtk-roles.properties");

applicationEnvironment = System.getProperty(ViewerConstants.APPLICATION_ENV_KEY,
ViewerConstants.APPLICATION_ENV_SERVER);

boolean reloadViewerConfiguration = getViewerConfigurationAsBoolean(false, RELOAD_DBPTK_VIEWER_PROPERTIES);

if (reloadViewerConfiguration) {
long reloadPeriod = getViewerConfigurationAsInt(86400000, RELOAD_DBPTK_VIEWER_PROPERTIES_PERIOD);
scheduler.scheduleAtFixedRate(() -> {
try {
reloadCombinedConfiguration();
} catch (ConfigurationException e) {
LOGGER.error("Error reloading combined configuration", e);
}
}, 0, reloadPeriod, TimeUnit.MILLISECONDS);
}

} catch (ConfigurationException e) {
LOGGER.error("Error loading dbvtk properties", e);
instantiatedWithoutErrors = false;
Expand Down Expand Up @@ -534,14 +560,14 @@ public AuthorizationGroupsList getCollectionsAuthorizationGroupsWithAdminAndUser
AuthorizationGroupsList authorizationGroupsList = getCollectionsAuthorizationGroups();

final List<String> adminRoles = ViewerConfiguration.getInstance()
.getViewerConfigurationAsList(ViewerConfiguration.PROPERTY_AUTHORIZATION_ADMINISTRATORS);
.getViewerConfigurationAsList(ViewerConfiguration.PROPERTY_AUTHORIZATION_ADMINISTRATORS);

for (String adminRole : adminRoles) {
AuthorizationGroup authorizationGroup = new AuthorizationGroup();
authorizationGroup.setId("roles.administrators." + adminRole);
authorizationGroup.setLabel("Administrators");
authorizationGroup.setAttributeName(getViewerConfigurationAsString(ViewerConstants.DEFAULT_ATTRIBUTE_ROLES,
ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE));
ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE));
authorizationGroup.setAttributeOperator(PROPERTY_COLLECTIONS_AUTHORIZATION_GROUP_OPERATOR_EQUAL);
authorizationGroup.setAttributeValue(adminRole);
authorizationGroup.setType(AuthorizationGroup.Type.DEFAULT);
Expand All @@ -553,7 +579,7 @@ public AuthorizationGroupsList getCollectionsAuthorizationGroupsWithAdminAndUser
authorizationGroup.setId("roles.users");
authorizationGroup.setLabel("Users");
authorizationGroup.setAttributeName(getViewerConfigurationAsString(ViewerConstants.DEFAULT_ATTRIBUTE_ROLES,
ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE));
ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE));
authorizationGroup.setAttributeOperator(PROPERTY_COLLECTIONS_AUTHORIZATION_GROUP_OPERATOR_EQUAL);
authorizationGroup.setAttributeValue(getViewerConfigurationAsString("users", "user.attribute.roles.users"));
authorizationGroup.setType(AuthorizationGroup.Type.DEFAULT);
Expand Down Expand Up @@ -682,6 +708,21 @@ private static void addConfiguration(String configurationFile) throws Configurat
configurationFiles.add(configurationFile);
}

private static void addCommonConfiguration() throws ConfigurationException {
for (String configurationFile : commonConfigurationFiles) {
Configuration configuration = getConfiguration(configurationFile);
combinedConfiguration.addConfiguration((PropertiesConfiguration) configuration);
}
viewerConfiguration.addConfiguration(combinedConfiguration);
}

private void reloadCombinedConfiguration() throws ConfigurationException {
viewerConfiguration.removeConfiguration(combinedConfiguration);
combinedConfiguration.clear();
addCommonConfiguration();
clearViewerCachableObjectsAfterConfigurationChange();
}

private static Configuration getConfiguration(String configurationFile) throws ConfigurationException {
Path config = configPath.resolve(configurationFile);
PropertiesConfiguration propertiesConfiguration = new PropertiesConfiguration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* <p>
* https://github.com/keeps/dbptk-ui
*/
package com.databasepreservation.common.server.controller;
Expand Down Expand Up @@ -37,25 +37,31 @@ public static User casLogin(final String username, final HttpServletRequest requ
AttributePrincipal attributePrincipal = (AttributePrincipal) request.getUserPrincipal();
Map<String, Object> attributes = attributePrincipal.getAttributes();

final String rolesConfigurationValue = ViewerConfiguration.getInstance().getViewerConfigurationAsString(
ViewerConstants.DEFAULT_ATTRIBUTE_ROLES, ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE);
final List<String> rolesConfigurationValue = ViewerConfiguration.getInstance()
.getViewerConfigurationAsList(ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE);
final String fullNameConfigurationValue = ViewerConfiguration.getInstance().getViewerConfigurationAsString(
ViewerConstants.DEFAULT_ATTRIBUTE_FULLNAME, ViewerConfiguration.PROPERTY_AUTHORIZATION_FULLNAME_ATTRIBUTE);
final String emailConfigurationValue = ViewerConfiguration.getInstance().getViewerConfigurationAsString(
ViewerConstants.DEFAULT_ATTRIBUTE_EMAIL, ViewerConfiguration.PROPERTY_AUTHORIZATION_EMAIL_ATTRIBUTE);

if (attributes.get(rolesConfigurationValue) instanceof String) {
Set<String> roles = new HashSet<>();
mapCasAttributeString(attributes, rolesConfigurationValue, roles::addAll);
user.setAllRoles(roles);
user.setDirectRoles(roles);
} else if (attributes.get(rolesConfigurationValue) instanceof List) {
mapCasAttributeList(user, attributes, rolesConfigurationValue, RodaPrincipal::setAllRoles);
mapCasAttributeList(user, attributes, rolesConfigurationValue, RodaPrincipal::setDirectRoles);
user.setAllRoles(new HashSet<>());
user.setDirectRoles(new HashSet<>());
for (String rolesAttribute : rolesConfigurationValue) {
if (attributes.get(rolesAttribute) instanceof String) {
Set<String> roles = new HashSet<>();
mapCasAttributeString(attributes, rolesAttribute, roles::addAll);
user.getAllRoles().addAll(roles);
user.getDirectRoles().addAll(roles);
} else if (attributes.get(rolesAttribute) instanceof List) {
mapCasAttributeList(user, attributes, rolesAttribute,
(user1, allRoles) -> user1.getAllRoles().addAll(allRoles));
mapCasAttributeList(user, attributes, rolesAttribute,
(user1, directRoles) -> user1.getDirectRoles().addAll(directRoles));
}
}

mapAuthorizedGroups(user,
ViewerConfiguration.getInstance().getCollectionsAuthorizationGroupsWithAdminAndUserRoles().getAuthorizationGroupsList());
mapAuthorizedGroups(user, ViewerConfiguration.getInstance()
.getCollectionsAuthorizationGroupsWithAdminAndUserRoles().getAuthorizationGroupsList());

// Add default roles to authenticated user
boolean addDefaultRoles = ViewerConfiguration.getInstance().getViewerConfigurationAsBoolean(false,
Expand Down Expand Up @@ -84,14 +90,16 @@ public static User casLogin(final String username, final HttpServletRequest requ
private static void mapAuthorizedGroups(User user, Set<AuthorizationGroup> authorizationGroups) {
Set<String> authorizedRoles = new HashSet<>();
for (AuthorizationGroup group : authorizationGroups) {
String rolesAttribute = ViewerConfiguration.getInstance().getViewerConfigurationAsString(
ViewerConstants.DEFAULT_ATTRIBUTE_ROLES, ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE);
List<String> rolesAttribute = ViewerConfiguration.getInstance()
.getViewerConfigurationAsList(ViewerConfiguration.PROPERTY_AUTHORIZATION_ROLES_ATTRIBUTE);

if (ViewerConfiguration.PROPERTY_COLLECTIONS_AUTHORIZATION_GROUP_OPERATOR_EQUAL
.equals(group.getAttributeOperator())) {
if (rolesAttribute.equalsIgnoreCase(group.getAttributeName())) {
if (user.getAllRoles().stream().anyMatch(p -> p.equals(group.getAttributeValue()))) {
authorizedRoles.add(group.getAttributeValue());
for (String roleAttribute : rolesAttribute) {
if (roleAttribute.equalsIgnoreCase(group.getAttributeName())) {
if (user.getAllRoles().stream().anyMatch(p -> p.equals(group.getAttributeValue()))) {
authorizedRoles.add(group.getAttributeValue());
}
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/main/resources/config/dbvtk-viewer.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
##############################################
ui.sharedProperties.whitelist.configuration.prefix=lists
ui.sharedProperties.whitelist.configuration.prefix=ui.lists
ui.sharedProperties.whitelist.configuration.prefix=ui.reload
ui.sharedProperties.whitelist.configuration.prefix=ui.header
ui.sharedProperties.whitelist.configuration.prefix=ui.interface
ui.sharedProperties.whitelist.configuration.prefix=ui.disable
Expand Down Expand Up @@ -70,7 +71,7 @@ ui.disable.whitelist.cache=false
##############################################
user.attribute.fullname=fullname
user.attribute.email=email
user.attribute.roles=memberOf
user.attribute.roles[]=memberOf
user.attribute.roles.administrators=administrators
user.attribute.roles.users=users
##############################################
Expand Down Expand Up @@ -168,3 +169,8 @@ ui.siard.available.search.all=true
# Show schema name in reference table
##############################################
ui.reference.table.show.schema.name=true
##############################################
# Reload dbptk viewer properties
##############################################
ui.reload.viewer.properties=false
ui.reload.viewer.properties.period=86400000
20 changes: 20 additions & 0 deletions src/main/resources/config/users-groups.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
##############################################
# This file is used to configure the users and groups if automatic reload of them is desired.
# If not keep this file empty.
##############################################
##############################################
# Authorization Groups
#--------------------------------------------
# A list of authorization groups for databases,
# DBPTKE will compare user roles with permissions saved in databases status using these groups.
# Label: Replaces attributeValue in interface.
# attributeName: Session attribute that will be added in user roles
# attributeOperator: Operator used to check database permissions
# attributeValue: Value used to check database permissions
# For now only the EQUAL operator is implemented
##############################################
#lists.collections.authorization.groups[]={list value}
#lists.collections.authorization.groups[].{list value}.label=Group1
#lists.collections.authorization.groups[].{list value}.attributeName=memberOf
#lists.collections.authorization.groups[].{list value}.attributeOperator=EQUAL
#lists.collections.authorization.groups[].{list value}.attributeValue=roda
Loading