Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
pathob committed Oct 27, 2023
1 parent 5136d8e commit a6fe02d
Show file tree
Hide file tree
Showing 12 changed files with 1,077 additions and 216 deletions.
506 changes: 497 additions & 9 deletions index.adoc

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</parent>

<artifactId>confapi-crowd-plugin</artifactId>
<version>0.1.0</version>
<version>0.2.0-SNAPSHOT</version>
<packaging>atlassian-plugin</packaging>

<name>ConfAPI for Crowd</name>
Expand Down Expand Up @@ -68,6 +68,10 @@
<atlassian.spring.scanner.version>2.1.5</atlassian.spring.scanner.version>
<confapi-commons.version>0.0.34</confapi-commons.version>
<plugin.testrunner.version>2.0.1</plugin.testrunner.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<dependencyManagement>
Expand Down
198 changes: 126 additions & 72 deletions src/main/java/de/aservo/confapi/crowd/model/util/DirectoryBeanUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@

import com.atlassian.crowd.embedded.api.Directory;
import com.atlassian.crowd.embedded.api.DirectoryType;
import com.atlassian.crowd.embedded.api.OperationType;
import com.atlassian.crowd.model.directory.ImmutableDirectory;
import de.aservo.confapi.commons.model.AbstractDirectoryBean;
import de.aservo.confapi.commons.model.DirectoryCrowdBean;
import de.aservo.confapi.commons.model.DirectoryGenericBean;
import de.aservo.confapi.commons.model.DirectoryInternalBean;
import de.aservo.confapi.commons.model.DirectoryLdapBean;

import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.List;
import java.util.HashSet;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.Set;

import static com.atlassian.crowd.directory.AbstractInternalDirectory.*;
import static de.aservo.confapi.crowd.util.AttributeUtil.*;
import static java.lang.Boolean.TRUE;

public class DirectoryBeanUtil {

public static final String LIST_SEPARATOR = ",";
public static final String ATTRIBUTE_USE_NESTED_GROUPS = "useNestedGroups";

/**
* Build directory bean.
*
* @param directory the directory
* @return the directory bean
*/
@Nullable
@Nonnull
public static AbstractDirectoryBean toDirectoryBean(
@Nullable final Directory directory) {

if (directory == null) {
return null;
}
@Nonnull final Directory directory) {

if (directory.getType().equals(DirectoryType.INTERNAL)) {
return toDirectoryInternalBean(directory);
Expand All @@ -41,24 +41,41 @@ public static AbstractDirectoryBean toDirectoryBean(
return toDirectoryGenericBean(directory);
}

private static DirectoryInternalBean toDirectoryInternalBean(
public static DirectoryInternalBean toDirectoryInternalBean(
final Directory directory) {

final DirectoryInternalBean directoryBean = new DirectoryInternalBean();
directoryBean.setId(directory.getId());
directoryBean.setName(directory.getName());
directoryBean.setDescription(directory.getDescription());
directoryBean.setActive(directory.isActive());
directoryBean.setCreatedDate(directory.getCreatedDate());
directoryBean.setUpdatedDate(directory.getUpdatedDate());

final Map<String, String> attributes = new HashMap<>(directory.getAttributes());
final Set<OperationType> allowedOperations = new HashSet<>(directory.getAllowedOperations());

final Map<String, String> directoryAttributes = directory.getAttributes();
directoryBean.setCredentialPolicy(new DirectoryInternalBean.DirectoryInternalCredentialPolicy());
directoryBean.getCredentialPolicy().setPasswordRegex(directoryAttributes.get(ATTRIBUTE_PASSWORD_REGEX));
directoryBean.getCredentialPolicy().setPasswordComplexityMessage(directoryAttributes.get(ATTRIBUTE_PASSWORD_COMPLEXITY_MESSAGE));
directoryBean.getCredentialPolicy().setPasswordMaxAttempts(toLong(directoryAttributes.get(ATTRIBUTE_PASSWORD_MAX_ATTEMPTS)));
directoryBean.getCredentialPolicy().setPasswordHistoryCount(toLong(directoryAttributes.get(ATTRIBUTE_PASSWORD_HISTORY_COUNT)));
directoryBean.getCredentialPolicy().setPasswordMaxChangeTime(toLong(directoryAttributes.get(ATTRIBUTE_PASSWORD_MAX_CHANGE_TIME)));
directoryBean.getCredentialPolicy().setPasswordExpiryNotificationDays(toList(directoryAttributes.get(ATTRIBUTE_PASSWORD_EXPIRATION_NOTIFICATION_PERIODS)));
directoryBean.getCredentialPolicy().setPasswordEncryptionMethod(directoryAttributes.get(ATTRIBUTE_USER_ENCRYPTION_METHOD));
directoryBean.getCredentialPolicy().setPasswordRegex(attributes.get(ATTRIBUTE_PASSWORD_REGEX));
directoryBean.getCredentialPolicy().setPasswordComplexityMessage(attributes.get(ATTRIBUTE_PASSWORD_COMPLEXITY_MESSAGE));
directoryBean.getCredentialPolicy().setPasswordMaxAttempts(toLong(attributes.get(ATTRIBUTE_PASSWORD_MAX_ATTEMPTS)));
directoryBean.getCredentialPolicy().setPasswordHistoryCount(toLong(attributes.get(ATTRIBUTE_PASSWORD_HISTORY_COUNT)));
directoryBean.getCredentialPolicy().setPasswordMaxChangeTime(toLong(attributes.get(ATTRIBUTE_PASSWORD_MAX_CHANGE_TIME)));
directoryBean.getCredentialPolicy().setPasswordExpiryNotificationDays(toIntegerList(attributes.get(ATTRIBUTE_PASSWORD_EXPIRATION_NOTIFICATION_PERIODS)));
directoryBean.getCredentialPolicy().setPasswordEncryptionMethod(attributes.get(ATTRIBUTE_USER_ENCRYPTION_METHOD));

directoryBean.setAdvanced(new DirectoryInternalBean.DirectoryInternalAdvanced());
directoryBean.getAdvanced().setEnableNestedGroups(toBoolean(attributes.getOrDefault(ATTRIBUTE_USE_NESTED_GROUPS, "false")));

directoryBean.setPermissions(new DirectoryInternalBean.DirectoryInternalPermissions());
directoryBean.getPermissions().setAddGroup(allowedOperations.contains(OperationType.CREATE_GROUP));
directoryBean.getPermissions().setAddUser(allowedOperations.contains(OperationType.CREATE_USER));
directoryBean.getPermissions().setModifyGroup(allowedOperations.contains(OperationType.UPDATE_GROUP));
directoryBean.getPermissions().setModifyUser(allowedOperations.contains(OperationType.UPDATE_USER));
directoryBean.getPermissions().setModifyGroupAttributes(allowedOperations.contains(OperationType.UPDATE_GROUP_ATTRIBUTE));
directoryBean.getPermissions().setModifyUserAttributes(allowedOperations.contains(OperationType.UPDATE_USER_ATTRIBUTE));
directoryBean.getPermissions().setRemoveGroup(allowedOperations.contains(OperationType.DELETE_GROUP));
directoryBean.getPermissions().setRemoveUser(allowedOperations.contains(OperationType.DELETE_USER));

return directoryBean;
}
Expand All @@ -81,88 +98,125 @@ private static DirectoryGenericBean toDirectoryGenericBean(
* @param directoryBean the directory bean
* @return the directory
*/
@Nullable
@Nonnull
public static Directory toDirectory(
@Nonnull final AbstractDirectoryBean directoryBean) {

final ImmutableDirectory.Builder directoryBuilder = ImmutableDirectory.builder(
directoryBean.getName(), toDirectoryType(directoryBean), toDirectoryImplClass(directoryBean));

return toDirectory(directoryBean, directoryBuilder.build());
}

/**
* Build directory.
*
* @param directoryBean the directory bean
* @return the directory
*/
@Nonnull
public static Directory toDirectory(
@Nullable final AbstractDirectoryBean directoryBean) {
@Nonnull final AbstractDirectoryBean directoryBean,
@Nonnull final Directory directory) {

if (directoryBean == null) {
return null;
final ImmutableDirectory.Builder directoryBuilder = ImmutableDirectory.builder(directory);

if (directoryBean.getDescription() != null) {
directoryBuilder.setDescription(directoryBean.getDescription());
}

if (directoryBean.getActive() != null) {
directoryBuilder.setActive(directoryBean.getActive());
}

DirectoryType directoryType = DirectoryType.UNKNOWN;
final Map<String, String> directoryAttributes = new HashMap<>();
final Map<String, String> attributes = new HashMap<>(directory.getAttributes());
final Set<OperationType> allowedOperations = new HashSet<>(directory.getAllowedOperations());

if (directoryBean instanceof DirectoryInternalBean) {
directoryType = DirectoryType.INTERNAL;
if (DirectoryInternalBean.class.equals(directoryBean.getClass())) {
final DirectoryInternalBean directoryInternalBean = (DirectoryInternalBean) directoryBean;
final DirectoryInternalBean.DirectoryInternalCredentialPolicy credentialPolicy = directoryInternalBean.getCredentialPolicy();

final DirectoryInternalBean.DirectoryInternalCredentialPolicy credentialPolicy = directoryInternalBean.getCredentialPolicy();
if (credentialPolicy != null) {
directoryAttributes.put(ATTRIBUTE_PASSWORD_REGEX, credentialPolicy.getPasswordRegex());
directoryAttributes.put(ATTRIBUTE_PASSWORD_COMPLEXITY_MESSAGE, credentialPolicy.getPasswordComplexityMessage());
directoryAttributes.put(ATTRIBUTE_PASSWORD_MAX_ATTEMPTS, fromLong(credentialPolicy.getPasswordMaxAttempts()));
directoryAttributes.put(ATTRIBUTE_PASSWORD_HISTORY_COUNT, fromLong(credentialPolicy.getPasswordHistoryCount()));
directoryAttributes.put(ATTRIBUTE_PASSWORD_MAX_CHANGE_TIME, fromLong(credentialPolicy.getPasswordMaxChangeTime()));
directoryAttributes.put(ATTRIBUTE_PASSWORD_EXPIRATION_NOTIFICATION_PERIODS, fromList(credentialPolicy.getPasswordExpiryNotificationDays()));
directoryAttributes.put(ATTRIBUTE_USER_ENCRYPTION_METHOD, credentialPolicy.getPasswordEncryptionMethod());
setAttributeIfNotNull(attributes, ATTRIBUTE_PASSWORD_REGEX, credentialPolicy.getPasswordRegex());
setAttributeIfNotNull(attributes, ATTRIBUTE_PASSWORD_COMPLEXITY_MESSAGE, credentialPolicy.getPasswordComplexityMessage());
setAttributeIfNotNull(attributes, ATTRIBUTE_PASSWORD_MAX_ATTEMPTS, fromLong(credentialPolicy.getPasswordMaxAttempts()));
setAttributeIfNotNull(attributes, ATTRIBUTE_PASSWORD_HISTORY_COUNT, fromLong(credentialPolicy.getPasswordHistoryCount()));
setAttributeIfNotNull(attributes, ATTRIBUTE_PASSWORD_MAX_CHANGE_TIME, fromLong(credentialPolicy.getPasswordMaxChangeTime()));
setAttributeIfNotNull(attributes, ATTRIBUTE_PASSWORD_EXPIRATION_NOTIFICATION_PERIODS, fromIntegerList(credentialPolicy.getPasswordExpiryNotificationDays()));
setAttributeIfNotNull(attributes, ATTRIBUTE_USER_ENCRYPTION_METHOD, credentialPolicy.getPasswordEncryptionMethod());
}

final DirectoryInternalBean.DirectoryInternalAdvanced advanced = directoryInternalBean.getAdvanced();
if (advanced != null) {
setAttributeIfNotNull(attributes, ATTRIBUTE_USE_NESTED_GROUPS, fromBoolean(advanced.getEnableNestedGroups()));
}

final DirectoryInternalBean.DirectoryInternalPermissions permissions = directoryInternalBean.getPermissions();
if (permissions != null) {
setAllowedOperationIfNotNull(allowedOperations, OperationType.CREATE_GROUP, permissions.getAddGroup());
setAllowedOperationIfNotNull(allowedOperations, OperationType.CREATE_USER, permissions.getAddUser());
setAllowedOperationIfNotNull(allowedOperations, OperationType.UPDATE_GROUP, permissions.getModifyGroup());
setAllowedOperationIfNotNull(allowedOperations, OperationType.UPDATE_USER, permissions.getModifyUser());
setAllowedOperationIfNotNull(allowedOperations, OperationType.UPDATE_GROUP_ATTRIBUTE, permissions.getModifyGroupAttributes());
setAllowedOperationIfNotNull(allowedOperations, OperationType.UPDATE_USER_ATTRIBUTE, permissions.getModifyUserAttributes());
setAllowedOperationIfNotNull(allowedOperations, OperationType.DELETE_GROUP, permissions.getRemoveGroup());
setAllowedOperationIfNotNull(allowedOperations, OperationType.DELETE_USER, permissions.getRemoveUser());
}
}

return ImmutableDirectory.builder(directoryBean.getName(), directoryType, "")
.setId(directoryBean.getId())
.setDescription(directoryBean.getDescription())
.setActive(directoryBean.getActive())
.setAttributes(directoryAttributes)
return directoryBuilder
.setAttributes(attributes)
.setAllowedOperations(allowedOperations)
.build();
}

private static String fromList(
@Nullable final List<Integer> value) {
@Nonnull
private static DirectoryType toDirectoryType(
@Nonnull final AbstractDirectoryBean directoryBean) {

if (value == null) {
return null;
if (DirectoryInternalBean.class.equals(directoryBean.getClass())) {
return DirectoryType.INTERNAL;
} else if (DirectoryCrowdBean.class.equals(directoryBean.getClass())) {
return DirectoryType.CROWD;
} else if (DirectoryLdapBean.class.equals(directoryBean.getClass())) {
return DirectoryType.AZURE_AD;
}

return value.stream()
.sorted()
.map(String::valueOf)
.collect(Collectors.joining(LIST_SEPARATOR));
return DirectoryType.UNKNOWN;
}

@Nullable
private static String fromLong(
@Nullable final Long value) {
private static String toDirectoryImplClass(
@Nonnull final AbstractDirectoryBean directoryBean) {

if (value == null) {
return null;
if (DirectoryInternalBean.class.equals(directoryBean.getClass())) {
return "com.atlassian.crowd.directory.InternalDirectory";
}

return String.valueOf(value);
return null;
}

@Nullable
private static List<Integer> toList(
@Nullable final String value) {
private static void setAttributeIfNotNull(
final Map<String, String> attributes,
final String attribute,
final String value) {

if (value == null) {
return null;
if (value != null) {
attributes.put(attribute, value);
}

return Stream.of(value.split(LIST_SEPARATOR))
.sorted()
.map(Integer::valueOf)
.collect(Collectors.toList());
}

@Nullable
private static Long toLong(
@Nullable final String value) {
private static void setAllowedOperationIfNotNull(
final Set<OperationType> allowedOperations,
final OperationType operationType,
final Boolean permission) {

if (value == null) {
return null;
}
if (permission != null) {
allowedOperations.remove(operationType);

return Long.valueOf(value);
if (TRUE.equals(permission)) {
allowedOperations.add(operationType);
}
}
}

private DirectoryBeanUtil() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,24 @@

import com.sun.jersey.spi.container.ResourceFilters;
import de.aservo.confapi.commons.constants.ConfAPI;
import de.aservo.confapi.commons.exception.NotFoundException;
import de.aservo.confapi.commons.model.AbstractDirectoryBean;
import de.aservo.confapi.commons.rest.AbstractDirectoriesResourceImpl;
import de.aservo.confapi.commons.service.api.DirectoriesService;
import de.aservo.confapi.crowd.filter.SysadminOnlyResourceFilter;
import de.aservo.confapi.crowd.rest.api.DirectoriesResource;
import de.aservo.confapi.crowd.service.api.DirectoriesService;
import org.springframework.stereotype.Component;

import javax.inject.Inject;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path(ConfAPI.DIRECTORIES)
@ResourceFilters(SysadminOnlyResourceFilter.class)
@Component
public class DirectoriesResourceImpl implements DirectoriesResource {

private final DirectoriesService directoriesService;
public class DirectoriesResourceImpl extends AbstractDirectoriesResourceImpl {

@Inject
public DirectoriesResourceImpl(
final DirectoriesService directoriesService) {

this.directoriesService = directoriesService;
}

@Override
public Response getDirectories() {
return Response.ok(directoriesService.getDirectories()).build();
}

@Override
public Response getDirectory(
final long id) {

final AbstractDirectoryBean directoryBean = directoriesService.getDirectory(id);

if (directoryBean == null) {
throw new NotFoundException(String.format("Directory with ID '%d' cannot be found", id));
}

return Response.ok(directoryBean).build();
super(directoriesService);
}

}
Loading

0 comments on commit a6fe02d

Please sign in to comment.