merge with 2.0.0-m3

This commit is contained in:
Sebastian Sdorra
2018-07-16 10:36:29 +02:00
18 changed files with 346 additions and 316 deletions

82
Jenkinsfile vendored
View File

@@ -1,29 +1,33 @@
#!groovy #!groovy
@Library('github.com/cloudogu/ces-build-lib@ac17d45')
// Keep the version in sync with the one used in pom.xml in order to get correct syntax completion.
@Library('github.com/cloudogu/ces-build-lib@9aadeeb')
import com.cloudogu.ces.cesbuildlib.* import com.cloudogu.ces.cesbuildlib.*
node() { // No specific label node() { // No specific label
// Change this as when we go back to default - necessary for proper SonarQube analysis
mainBranch = "2.0.0-m3"
properties([ properties([
// Keep only the last 10 build to preserve space // Keep only the last 10 build to preserve space
buildDiscarder(logRotator(numToKeepStr: '10')), buildDiscarder(logRotator(numToKeepStr: '10')),
// Don't run concurrent builds for a branch, because they use the same workspace directory
disableConcurrentBuilds()
]) ])
String defaultEmailRecipients = env.EMAIL_SCM_RECIPIENTS
catchError { catchError {
Maven mvn = new MavenWrapper(this) Maven mvn = setupMavenBuild()
// Maven build specified it must be 1.8.0-101 or newer
def javaHome = tool 'JDK-1.8.0-101+'
withEnv(["JAVA_HOME=${javaHome}", "PATH=${env.JAVA_HOME}/bin:${env.PATH}"]) {
stage('Checkout') { stage('Checkout') {
checkout scm checkout scm
} }
stage('Build') { stage('Build') {
mvn 'clean install -DskipTests -DperformRelease' mvn 'clean install -DskipTests'
archive '**/target/*.jar,**/target/*.zip'
} }
stage('Unit Test') { stage('Unit Test') {
@@ -31,9 +35,15 @@ node() { // No specific label
} }
stage('SonarQube') { stage('SonarQube') {
def sonarQube = new SonarQube(this, 'ces-sonar')
sonarQube.analyzeWith(mvn) def sonarQube = new SonarQube(this, 'sonarcloud.io')
analyzeWith(mvn)
if (!sonarQube.waitForQualityGateWebhookToBeCalled()) {
currentBuild.result = 'UNSTABLE'
}
}
} }
} }
@@ -43,5 +53,55 @@ node() { // No specific label
// Find maven warnings and visualize in job // Find maven warnings and visualize in job
warnings consoleParsers: [[parserName: 'Maven']], canRunOnFailed: true warnings consoleParsers: [[parserName: 'Maven']], canRunOnFailed: true
mailIfStatusChanged(defaultEmailRecipients) mailIfStatusChanged(commitAuthorEmail)
}
String mainBranch
Maven setupMavenBuild() {
Maven mvn = new MavenWrapper(this)
if (mainBranch.equals(env.BRANCH_NAME)) {
// Release starts javadoc, which takes very long, so do only for certain branches
mvn.additionalArgs += ' -DperformRelease'
// JDK8 is more strict, we should fix this before the next release. Right now, this is just not the focus, yet.
mvn.additionalArgs += ' -Dmaven.javadoc.failOnError=false'
}
return mvn
}
void analyzeWith(Maven mvn) {
withSonarQubeEnv('sonarcloud.io') {
String mvnArgs = "${env.SONAR_MAVEN_GOAL} " +
"-Dsonar.host.url=${env.SONAR_HOST_URL} " +
"-Dsonar.login=${env.SONAR_AUTH_TOKEN} "
if (isPullRequest()) {
echo "Analysing SQ in PR mode"
mvnArgs += "-Dsonar.pullrequest.base=${env.CHANGE_TARGET} " +
"-Dsonar.pullrequest.branch=${env.CHANGE_BRANCH} " +
"-Dsonar.pullrequest.key=${env.CHANGE_ID} " +
"-Dsonar.pullrequest.provider=bitbucketcloud " +
"-Dsonar.pullrequest.bitbucketcloud.owner=sdorra " +
"-Dsonar.pullrequest.bitbucketcloud.repository=scm-manager "
} else {
mvnArgs += " -Dsonar.branch.name=${env.BRANCH_NAME} "
if (!mainBranch.equals(env.BRANCH_NAME)) {
// Avoid exception "The main branch must not have a target" on main branch
mvnArgs += " -Dsonar.branch.target=${mainBranch} "
}
}
mvn "${mvnArgs}"
}
}
String getCommitAuthorComplete() {
new Sh(this).returnStdOut 'hg log --branch . --limit 1 --template "{author}"'
}
String getCommitAuthorEmail() {
def matcher = getCommitAuthorComplete() =~ "<(.*?)>"
matcher ? matcher[0][1] : ""
} }

23
pom.xml
View File

@@ -146,9 +146,30 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<!-- Dependency used in Jenkinsfile. Including this in maven provides code completion in Jenkinsfile. -->
<groupId>com.github.cloudogu</groupId>
<artifactId>ces-build-lib</artifactId>
<!-- Keep this version in sync with the one used in Jenkinsfile -->
<version>9aadeeb</version>
<!-- Don't ship this dependency with the app -->
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
<build> <build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins> <plugins>
<plugin> <plugin>
@@ -254,7 +275,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration> <configuration>
<useStandardDocletOptions>true</useStandardDocletOptions> <useStandardDocletOptions>true</useStandardDocletOptions>
<charset>${project.build.sourceEncoding}</charset> <charset>${project.build.sourceEncoding}</charset>
@@ -439,7 +459,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.8.1</version>
<configuration> <configuration>
<doclet>org.jboss.apiviz.APIviz</doclet> <doclet>org.jboss.apiviz.APIviz</doclet>
<docletArtifact> <docletArtifact>

View File

@@ -159,7 +159,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration> <configuration>
<useStandardDocletOptions>true</useStandardDocletOptions> <useStandardDocletOptions>true</useStandardDocletOptions>
<charset>${project.build.sourceEncoding}</charset> <charset>${project.build.sourceEncoding}</charset>

View File

@@ -53,5 +53,11 @@ public interface ModelObject
* *
* @return unique id * @return unique id
*/ */
public String getId(); String getId();
void setLastModified(Long timestamp);
Long getCreationDate();
void setCreationDate(Long timestamp);
} }

View File

@@ -42,15 +42,9 @@ package sonia.scm.group;
public class GroupAlreadyExistsException extends GroupException public class GroupAlreadyExistsException extends GroupException
{ {
/** Field description */
private static final long serialVersionUID = 4042878550219750430L; private static final long serialVersionUID = 4042878550219750430L;
/** public GroupAlreadyExistsException(Group group) {
* Constructs a new instance. super(group.getName() + " group already exists");
*
* @param name The name (aka id) of the group
*/
public GroupAlreadyExistsException(String name) {
super(name + " group already exists");
} }
} }

View File

@@ -52,7 +52,7 @@ public class GroupNotFoundException extends GroupException
* Constructs a new GroupNotFoundException. * Constructs a new GroupNotFoundException.
* *
*/ */
public GroupNotFoundException() { public GroupNotFoundException(Group group) {
super("group does not exists"); super("group " + group.getName() + " does not exist");
} }
} }

View File

@@ -52,17 +52,11 @@ public class RepositoryNotFoundException extends RepositoryException
* error detail message. * error detail message.
* *
*/ */
public RepositoryNotFoundException() {} public RepositoryNotFoundException(Repository repository) {
super("repository " + repository.getName() + "/" + repository.getNamespace() + " does not exist");
}
/** public RepositoryNotFoundException(String repositoryId) {
* Constructs a new {@link RepositoryNotFoundException} with the specified super("repository with id " + repositoryId + " does not exist");
* error detail message.
*
*
* @param message error detail message
*/
public RepositoryNotFoundException(String message)
{
super(message);
} }
} }

View File

@@ -177,8 +177,7 @@ public final class RepositoryServiceFactory
if (repository == null) if (repository == null)
{ {
throw new RepositoryNotFoundException( throw new RepositoryNotFoundException(repositoryId);
"could not find a repository with id ".concat(repositoryId));
} }
return create(repository); return create(repository);

View File

@@ -41,19 +41,11 @@ package sonia.scm.user;
public class UserAlreadyExistsException extends UserException public class UserAlreadyExistsException extends UserException
{ {
/** Field description */
private static final long serialVersionUID = 9182294539718090814L; private static final long serialVersionUID = 9182294539718090814L;
//~--- constructors --------------------------------------------------------- //~--- constructors ---------------------------------------------------------
/** public UserAlreadyExistsException(User user) {
* Constructs a new instance. super(user.getName() + " user already exists");
*
* @param name The name (aka id) of the user
* @since 1.5
*/
public UserAlreadyExistsException(String name)
{
super(name + " user already exists");
} }
} }

View File

@@ -51,7 +51,7 @@ public class UserNotFoundException extends UserException
* Constructs a new UserNotFoundException. * Constructs a new UserNotFoundException.
* *
*/ */
public UserNotFoundException() { public UserNotFoundException(User user) {
super("user does not exists"); super("user " + user.getName() + " does not exist");
} }
} }

View File

@@ -566,7 +566,7 @@
<sonar.issue.ignore.multicriteria>e1</sonar.issue.ignore.multicriteria> <sonar.issue.ignore.multicriteria>e1</sonar.issue.ignore.multicriteria>
<sonar.issue.ignore.multicriteria.e1.ruleKey>javascript:S3827</sonar.issue.ignore.multicriteria.e1.ruleKey> <sonar.issue.ignore.multicriteria.e1.ruleKey>javascript:S3827</sonar.issue.ignore.multicriteria.e1.ruleKey>
<sonar.issue.ignore.multicriteria.e1.resourceKey>**.js</sonar.issue.ignore.multicriteria.e1.resourceKey> <sonar.issue.ignore.multicriteria.e1.resourceKey>**.js</sonar.issue.ignore.multicriteria.e1.resourceKey>
<sonar.exclusions>src/main/webapp/resources/extjs/**,src/main/webapp/resources/moment/**,src/main/webapp/resources/syntaxhighlighter/**</sonar.exclusions> <sonar.exclusions>src/main/webapp**</sonar.exclusions>
</properties> </properties>
<profiles> <profiles>

View File

@@ -0,0 +1,68 @@
package sonia.scm;
import com.github.sdorra.ssp.PermissionCheck;
import sonia.scm.util.AssertUtil;
import java.util.function.Function;
import java.util.function.Supplier;
public class ManagerDaoAdapter<T extends ModelObject, E extends Exception> {
private final GenericDAO<T> dao;
private final Function<T, E> notFoundException;
private final Function<T, E> alreadyExistsException;
public ManagerDaoAdapter(GenericDAO<T> dao, Function<T, E> notFoundException, Function<T, E> alreadyExistsException) {
this.dao = dao;
this.notFoundException = notFoundException;
this.alreadyExistsException = alreadyExistsException;
}
public void modify(T object, Function<T, PermissionCheck> permissionCheck, AroundHandler<T, E> beforeUpdate, AroundHandler<T, E> afterUpdate) throws E {
T notModified = dao.get(object.getId());
if (notModified != null) {
permissionCheck.apply(notModified).check();
AssertUtil.assertIsValid(object);
beforeUpdate.handle(notModified);
object.setLastModified(System.currentTimeMillis());
object.setCreationDate(notModified.getCreationDate());
dao.modify(object);
afterUpdate.handle(notModified);
} else {
throw notFoundException.apply(object);
}
}
public T create(T newObject, Supplier<PermissionCheck> permissionCheck, AroundHandler<T, E> beforeCreate, AroundHandler<T, E> afterCreate) throws E {
permissionCheck.get().check();
AssertUtil.assertIsValid(newObject);
if (dao.contains(newObject)) {
throw alreadyExistsException.apply(newObject);
}
newObject.setCreationDate(System.currentTimeMillis());
beforeCreate.handle(newObject);
dao.add(newObject);
afterCreate.handle(newObject);
return newObject;
}
public void delete(T toDelete, Supplier<PermissionCheck> permissionCheck, AroundHandler<T, E> beforeDelete, AroundHandler<T, E> afterDelete) throws E {
permissionCheck.get().check();
if (dao.contains(toDelete)) {
beforeDelete.handle(toDelete);
dao.delete(toDelete);
afterDelete.handle(toDelete);
} else {
throw notFoundException.apply(toDelete);
}
}
@FunctionalInterface
public interface AroundHandler<T extends ModelObject, E extends Exception> {
void handle(T notModified) throws E;
}
}

View File

@@ -43,6 +43,7 @@ import com.google.inject.Singleton;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.HandlerEventType; import sonia.scm.HandlerEventType;
import sonia.scm.ManagerDaoAdapter;
import sonia.scm.SCMContextProvider; import sonia.scm.SCMContextProvider;
import sonia.scm.TransformFilter; import sonia.scm.TransformFilter;
import sonia.scm.search.SearchRequest; import sonia.scm.search.SearchRequest;
@@ -84,6 +85,10 @@ public class DefaultGroupManager extends AbstractGroupManager
public DefaultGroupManager(GroupDAO groupDAO) public DefaultGroupManager(GroupDAO groupDAO)
{ {
this.groupDAO = groupDAO; this.groupDAO = groupDAO;
this.managerDaoAdapter = new ManagerDaoAdapter<>(
groupDAO,
GroupNotFoundException::new,
GroupAlreadyExistsException::new);
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
@@ -101,79 +106,34 @@ public class DefaultGroupManager extends AbstractGroupManager
// do nothing // do nothing
} }
/**
* Method description
*
*
* @param group
*
* @throws GroupException
* @throws IOException
*/
@Override @Override
public Group create(Group group) throws GroupException public Group create(Group group) throws GroupException {
{
String type = group.getType(); String type = group.getType();
if (Util.isEmpty(type)) {
if (Util.isEmpty(type))
{
group.setType(groupDAO.getType()); group.setType(groupDAO.getType());
} }
String name = group.getName(); logger.info("create group {} of type {}", group.getName(), group.getType());
if (logger.isInfoEnabled())
{
logger.info("create group {} of type {}", name,
group.getType());
}
GroupPermissions.create().check();
if (groupDAO.contains(name))
{
throw new GroupAlreadyExistsException(name);
}
removeDuplicateMembers(group); removeDuplicateMembers(group);
group.setCreationDate(System.currentTimeMillis());
fireEvent(HandlerEventType.BEFORE_CREATE, group); return managerDaoAdapter.create(
groupDAO.add(group); group,
fireEvent(HandlerEventType.CREATE, group); GroupPermissions::create,
return group; newGroup -> fireEvent(HandlerEventType.BEFORE_CREATE, newGroup),
newGroup -> fireEvent(HandlerEventType.CREATE, newGroup)
);
} }
/**
* Method description
*
*
* @param group
*
* @throws GroupException
* @throws IOException
*/
@Override @Override
public void delete(Group group) throws GroupException public void delete(Group group) throws GroupException {
{ logger.info("delete group {} of type {}", group.getName(), group.getType());
if (logger.isInfoEnabled()) managerDaoAdapter.delete(
{ group,
logger.info("delete group {} of type {}", group.getName(), () -> GroupPermissions.delete(group.getName()),
group.getType()); toDelete -> fireEvent(HandlerEventType.BEFORE_DELETE, toDelete),
} toDelete -> fireEvent(HandlerEventType.DELETE, toDelete)
);
String name = group.getName();
GroupPermissions.delete().check(name);
if (groupDAO.contains(name))
{
fireEvent(HandlerEventType.BEFORE_DELETE, group);
groupDAO.delete(group);
fireEvent(HandlerEventType.DELETE, group);
}
else
{
throw new GroupNotFoundException();
}
} }
/** /**
@@ -195,31 +155,18 @@ public class DefaultGroupManager extends AbstractGroupManager
* @throws IOException * @throws IOException
*/ */
@Override @Override
public void modify(Group group) throws GroupException public void modify(Group group) throws GroupException {
{ logger.info("modify group {} of type {}", group.getName(), group.getType());
if (logger.isInfoEnabled())
{
logger.info("modify group {} of type {}", group.getName(),
group.getType());
}
String name = group.getName(); managerDaoAdapter.modify(
GroupPermissions.modify().check(name); group,
GroupPermissions::modify,
Group notModified = groupDAO.get(name); notModified -> {
if (notModified != null)
{
removeDuplicateMembers(group); removeDuplicateMembers(group);
fireEvent(HandlerEventType.BEFORE_MODIFY, group, notModified); fireEvent(HandlerEventType.BEFORE_MODIFY, group, notModified);
group.setLastModified(System.currentTimeMillis()); },
group.setCreationDate(notModified.getCreationDate()); notModified -> fireEvent(HandlerEventType.MODIFY, group, notModified)
groupDAO.modify(group); );
fireEvent(HandlerEventType.MODIFY, group, notModified);
}
else
{
throw new GroupNotFoundException();
}
} }
/** /**
@@ -245,7 +192,7 @@ public class DefaultGroupManager extends AbstractGroupManager
if (fresh == null) if (fresh == null)
{ {
throw new GroupNotFoundException(); throw new GroupNotFoundException(group);
} }
fresh.copyProperties(group); fresh.copyProperties(group);
@@ -458,4 +405,5 @@ public class DefaultGroupManager extends AbstractGroupManager
/** Field description */ /** Field description */
private GroupDAO groupDAO; private GroupDAO groupDAO;
private final ManagerDaoAdapter<Group, GroupException> managerDaoAdapter;
} }

View File

@@ -45,6 +45,7 @@ import org.slf4j.LoggerFactory;
import sonia.scm.ArgumentIsInvalidException; import sonia.scm.ArgumentIsInvalidException;
import sonia.scm.ConfigurationException; import sonia.scm.ConfigurationException;
import sonia.scm.HandlerEventType; import sonia.scm.HandlerEventType;
import sonia.scm.ManagerDaoAdapter;
import sonia.scm.SCMContextProvider; import sonia.scm.SCMContextProvider;
import sonia.scm.Type; import sonia.scm.Type;
import sonia.scm.config.ScmConfiguration; import sonia.scm.config.ScmConfiguration;
@@ -90,6 +91,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
private final Set<Type> types; private final Set<Type> types;
private RepositoryMatcher repositoryMatcher; private RepositoryMatcher repositoryMatcher;
private NamespaceStrategy namespaceStrategy; private NamespaceStrategy namespaceStrategy;
private final ManagerDaoAdapter<Repository, RepositoryException> managerDaoAdapter;
@Inject @Inject
@@ -116,6 +118,10 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
for (RepositoryHandler handler : handlerSet) { for (RepositoryHandler handler : handlerSet) {
addHandler(contextProvider, handler); addHandler(contextProvider, handler);
} }
managerDaoAdapter = new ManagerDaoAdapter<>(
repositoryDAO,
RepositoryNotFoundException::new,
RepositoryAlreadyExistsException::create);
} }
@@ -128,64 +134,47 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
} }
} }
public Repository create(Repository repository, boolean initRepository)
throws RepositoryException {
logger.info("create repository {} of type {}", repository.getName(), repository.getType());
RepositoryPermissions.create().check();
repository.setNamespace(namespaceStrategy.getNamespace());
logger.info("setting namespace of new repository {} to {}", repository.getName(), repository.getNamespace());
AssertUtil.assertIsValid(repository);
if (repositoryDAO.contains(repository.getNamespaceAndName())) {
throw RepositoryAlreadyExistsException.create(repository);
}
repository.setId(keyGenerator.createKey());
repository.setCreationDate(System.currentTimeMillis());
if (initRepository) {
getHandler(repository).create(repository);
}
fireEvent(HandlerEventType.BEFORE_CREATE, repository);
repositoryDAO.add(repository);
fireEvent(HandlerEventType.CREATE, repository);
return repository;
}
@Override @Override
public Repository create(Repository repository) public Repository create(Repository repository) throws RepositoryException {
throws RepositoryException {
return create(repository, true); return create(repository, true);
} }
public Repository create(Repository repository, boolean initRepository) throws RepositoryException {
repository.setId(keyGenerator.createKey());
repository.setNamespace(namespaceStrategy.getNamespace());
logger.info("create repository {} of type {} in namespace {}", repository.getName(), repository.getType(), repository.getNamespace());
return managerDaoAdapter.create(
repository,
RepositoryPermissions::create,
newRepository -> {
if (initRepository) {
getHandler(newRepository).create(newRepository);
}
fireEvent(HandlerEventType.BEFORE_CREATE, newRepository);
},
newRepository -> fireEvent(HandlerEventType.CREATE, newRepository)
);
}
@Override @Override
public void delete(Repository repository) public void delete(Repository repository) throws RepositoryException {
throws RepositoryException { logger.info("delete repository {} of type {}", repository.getName(), repository.getType());
if (logger.isInfoEnabled()) { managerDaoAdapter.delete(
logger.info("delete repository {} of type {}", repository.getName(), repository,
repository.getType()); () -> RepositoryPermissions.delete(repository),
this::preDelete,
toDelete -> fireEvent(HandlerEventType.DELETE, toDelete)
);
} }
RepositoryPermissions.delete(repository).check(); private void preDelete(Repository toDelete) throws RepositoryException {
if (configuration.isEnableRepositoryArchive() && !toDelete.isArchived()) {
if (configuration.isEnableRepositoryArchive() && !repository.isArchived()) { throw new RepositoryIsNotArchivedException("Repository could not deleted, because it is not archived.");
throw new RepositoryIsNotArchivedException(
"Repository could not deleted, because it is not archived.");
}
if (repositoryDAO.contains(repository)) {
fireEvent(HandlerEventType.BEFORE_DELETE, repository);
getHandler(repository).delete(repository);
repositoryDAO.delete(repository);
fireEvent(HandlerEventType.DELETE, repository);
} else {
throw new RepositoryNotFoundException(
"repository ".concat(repository.getName()).concat(" not found"));
} }
fireEvent(HandlerEventType.BEFORE_DELETE, toDelete);
getHandler(toDelete).delete(toDelete);
} }
@Override @Override
@@ -199,29 +188,18 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
} }
@Override @Override
public void modify(Repository repository) public void modify(Repository repository) throws RepositoryException {
throws RepositoryException { logger.info("modify repository {} of type {}", repository.getName(), repository.getType());
if (logger.isInfoEnabled()) {
logger.info("modify repository {} of type {}", repository.getName(),
repository.getType());
}
AssertUtil.assertIsValid(repository); managerDaoAdapter.modify(
repository,
Repository oldRepository = repositoryDAO.get(repository.getNamespaceAndName()); RepositoryPermissions::modify,
notModified -> {
if (oldRepository != null) { fireEvent(HandlerEventType.BEFORE_MODIFY, repository, notModified);
RepositoryPermissions.modify(oldRepository).check();
fireEvent(HandlerEventType.BEFORE_MODIFY, repository, oldRepository);
repository.setLastModified(System.currentTimeMillis());
repository.setCreationDate(oldRepository.getCreationDate());
getHandler(repository).modify(repository); getHandler(repository).modify(repository);
repositoryDAO.modify(repository); },
fireEvent(HandlerEventType.MODIFY, repository, oldRepository); notModified -> fireEvent(HandlerEventType.MODIFY, repository, notModified)
} else { );
throw new RepositoryNotFoundException(
"repository ".concat(repository.getName()).concat(" not found"));
}
} }
@Override @Override
@@ -235,8 +213,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
if (fresh != null) { if (fresh != null) {
fresh.copyProperties(repository); fresh.copyProperties(repository);
} else { } else {
throw new RepositoryNotFoundException( throw new RepositoryNotFoundException(repository);
"repository ".concat(repository.getName()).concat(" not found"));
} }
} }
@@ -452,5 +429,4 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
return handler; return handler;
} }
} }

View File

@@ -41,11 +41,11 @@ import com.google.inject.Singleton;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.HandlerEventType; import sonia.scm.HandlerEventType;
import sonia.scm.ManagerDaoAdapter;
import sonia.scm.SCMContextProvider; import sonia.scm.SCMContextProvider;
import sonia.scm.TransformFilter; import sonia.scm.TransformFilter;
import sonia.scm.search.SearchRequest; import sonia.scm.search.SearchRequest;
import sonia.scm.search.SearchUtil; import sonia.scm.search.SearchUtil;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.CollectionAppender; import sonia.scm.util.CollectionAppender;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
import sonia.scm.util.Util; import sonia.scm.util.Util;
@@ -96,6 +96,10 @@ public class DefaultUserManager extends AbstractUserManager
public DefaultUserManager(UserDAO userDAO) public DefaultUserManager(UserDAO userDAO)
{ {
this.userDAO = userDAO; this.userDAO = userDAO;
this.managerDaoAdapter = new ManagerDaoAdapter<>(
userDAO,
UserNotFoundException::new,
UserAlreadyExistsException::new);
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
@@ -137,65 +141,31 @@ public class DefaultUserManager extends AbstractUserManager
* @throws UserException * @throws UserException
*/ */
@Override @Override
public User create(User user) throws UserException public User create(User user) throws UserException {
{
String type = user.getType(); String type = user.getType();
if (Util.isEmpty(type)) {
if (Util.isEmpty(type))
{
user.setType(userDAO.getType()); user.setType(userDAO.getType());
} }
if (logger.isInfoEnabled())
{
logger.info("create user {} of type {}", user.getName(), user.getType()); logger.info("create user {} of type {}", user.getName(), user.getType());
return managerDaoAdapter.create(
user,
UserPermissions::create,
newUser -> fireEvent(HandlerEventType.BEFORE_CREATE, newUser),
newUser -> fireEvent(HandlerEventType.CREATE, newUser)
);
} }
UserPermissions.create().check();
if (userDAO.contains(user.getName()))
{
throw new UserAlreadyExistsException(user.getName());
}
AssertUtil.assertIsValid(user);
user.setCreationDate(System.currentTimeMillis());
fireEvent(HandlerEventType.BEFORE_CREATE, user);
userDAO.add(user);
fireEvent(HandlerEventType.CREATE, user);
return user;
}
/**
* Method description
*
*
* @param user
*
* @throws IOException
* @throws UserException
*/
@Override @Override
public void delete(User user) throws UserException public void delete(User user) throws UserException {
{
if (logger.isInfoEnabled())
{
logger.info("delete user {} of type {}", user.getName(), user.getType()); logger.info("delete user {} of type {}", user.getName(), user.getType());
} managerDaoAdapter.delete(
user,
String name = user.getName(); () -> UserPermissions.delete(user.getName()),
UserPermissions.delete(name).check(); toDelete -> fireEvent(HandlerEventType.BEFORE_DELETE, toDelete),
toDelete -> fireEvent(HandlerEventType.DELETE, toDelete)
if (userDAO.contains(name)) );
{
fireEvent(HandlerEventType.BEFORE_DELETE, user);
userDAO.delete(user);
fireEvent(HandlerEventType.DELETE, user);
}
else
{
throw new UserNotFoundException();
}
} }
/** /**
@@ -226,28 +196,14 @@ public class DefaultUserManager extends AbstractUserManager
*/ */
@Override @Override
public void modify(User user) throws UserException public void modify(User user) throws UserException
{
String name = user.getName();
if (logger.isInfoEnabled())
{ {
logger.info("modify user {} of type {}", user.getName(), user.getType()); logger.info("modify user {} of type {}", user.getName(), user.getType());
}
UserPermissions.modify(user).check(); managerDaoAdapter.modify(
User notModified = userDAO.get(name); user,
if (notModified != null) UserPermissions::modify,
{ notModified -> fireEvent(HandlerEventType.BEFORE_MODIFY, user, notModified),
AssertUtil.assertIsValid(user); notModified -> fireEvent(HandlerEventType.MODIFY, user, notModified));
fireEvent(HandlerEventType.BEFORE_MODIFY, user, notModified);
user.setLastModified(System.currentTimeMillis());
user.setCreationDate(notModified.getCreationDate());
userDAO.modify(user);
fireEvent(HandlerEventType.MODIFY, user, notModified);
}
else
{
throw new UserNotFoundException();
}
} }
/** /**
@@ -272,7 +228,7 @@ public class DefaultUserManager extends AbstractUserManager
if (fresh == null) if (fresh == null)
{ {
throw new UserNotFoundException(); throw new UserNotFoundException(user);
} }
fresh.copyProperties(user); fresh.copyProperties(user);
@@ -497,6 +453,6 @@ public class DefaultUserManager extends AbstractUserManager
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */
private final UserDAO userDAO; private final UserDAO userDAO;
private final ManagerDaoAdapter<User, UserException> managerDaoAdapter;
} }

View File

@@ -105,6 +105,21 @@ public class AbstractManagerResourceTest {
return id; return id;
} }
@Override
public void setLastModified(Long timestamp) {
}
@Override
public Long getCreationDate() {
return null;
}
@Override
public void setCreationDate(Long timestamp) {
}
@Override @Override
public Long getLastModified() { public Long getLastModified() {
return null; return null;

View File

@@ -37,7 +37,6 @@ import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware; import com.github.sdorra.shiro.SubjectAware;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.util.ThreadContext;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
@@ -45,7 +44,9 @@ import org.mockito.invocation.InvocationOnMock;
import sonia.scm.HandlerEventType; import sonia.scm.HandlerEventType;
import sonia.scm.Manager; import sonia.scm.Manager;
import sonia.scm.ManagerTestBase; import sonia.scm.ManagerTestBase;
import sonia.scm.ModelObject;
import sonia.scm.Type; import sonia.scm.Type;
import sonia.scm.TypedObject;
import sonia.scm.config.ScmConfiguration; import sonia.scm.config.ScmConfiguration;
import sonia.scm.event.ScmEventBus; import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.api.HookContext; import sonia.scm.repository.api.HookContext;
@@ -99,6 +100,8 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository, Re
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
private ScmConfiguration configuration;
private String mockedNamespace = "default_namespace"; private String mockedNamespace = "default_namespace";
@Test @Test
@@ -139,7 +142,8 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository, Re
@Test(expected = RepositoryIsNotArchivedException.class) @Test(expected = RepositoryIsNotArchivedException.class)
public void testDeleteNonArchived() throws RepositoryException { public void testDeleteNonArchived() throws RepositoryException {
delete(createRepositoryManager(true), createTestRepository()); configuration.setEnableRepositoryArchive(true);
delete(manager, createTestRepository());
} }
@Test(expected = RepositoryNotFoundException.class) @Test(expected = RepositoryNotFoundException.class)
@@ -492,7 +496,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository, Re
XmlRepositoryDAO repositoryDAO = new XmlRepositoryDAO(factory); XmlRepositoryDAO repositoryDAO = new XmlRepositoryDAO(factory);
ScmConfiguration configuration = new ScmConfiguration(); this.configuration = new ScmConfiguration();
configuration.setEnableRepositoryArchive(archiveEnabled); configuration.setEnableRepositoryArchive(archiveEnabled);