Replacing simple REST return types by model objects

This commit is contained in:
Martin Stockhammer 2020-06-30 21:19:55 +02:00
parent b4c86e98c8
commit fdb48a6024
33 changed files with 999 additions and 199 deletions

42
pom.xml
View File

@ -582,6 +582,48 @@
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-core</artifactId>
<scope>compile</scope>
<version>${io.swagger.version}</version>
<exclusions>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2</artifactId>
<version>${io.swagger.version}</version>
<exclusions>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${io.swagger.version}</version>
<exclusions>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>

View File

@ -71,8 +71,29 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
<configuration>
<excludes>
<exclude>target/generated</exclude>
<exclude>src/main/resources/templates/*</exclude>
<exclude>src/main/resources/openapi-codegen-ignore</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<!--
The jaxb dependency is needed by the enunciate plugin starting with JDK9.
Adding to the plugin dependency is not sufficient, so I have to add it as project dependency.

View File

@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<enunciate
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://enunciate.webcohesion.com/schemas/enunciate-2.12.0.xsd">
<title>Apache Archiva Redback REST API</title>
<modules>
<jaxrs>
<application path="redbackServices" />
</jaxrs>
<cxf disabled="false"/>
<jersey disabled="true"/>
<c disabled="true"/>
<csharp disabled="true"/>
<obj-c disabled="true"/>
<jaxws-ri disabled="true"/>
<jaxws-support disabled="true"/>
<jaxon1 disabled="true"/>
<jackson1 disabled="true"/>
<java-json-client disabled="true"/>
<docs disabled="false"
docsSubdir="" freemarkerTemplate="${project.basedir}/src/enunciate/archiva.fmt" css="${project.basedir}/src/enunciate/archiva.css">
<!-- <war docsDir="apidocs" /> -->
</docs>
</modules>
</enunciate>

View File

@ -0,0 +1,76 @@
package org.apache.archiva.redback.rest.api.model;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@XmlRootElement(name = "actionStatus")
public class ActionStatus
{
private boolean success = false;
private int modifiedNumber = 0;
public static final ActionStatus SUCCESS = new ActionStatus( true );
public static final ActionStatus FAIL = new ActionStatus( false );
public static ActionStatus FROM(boolean status) {
return status ? SUCCESS : FAIL;
}
public ActionStatus() {
}
public ActionStatus( boolean success) {
this.success = success;
}
public ActionStatus(boolean success, int modifiedNumber) {
this.success = success;
this.modifiedNumber = modifiedNumber;
}
public boolean isSuccess( )
{
return success;
}
public void setSuccess( boolean success )
{
this.success = success;
}
public int getModifiedNumber( )
{
return modifiedNumber;
}
public void setModifiedNumber( int modifiedNumber )
{
this.modifiedNumber = modifiedNumber;
}
@Override
public String toString( )
{
return Boolean.toString( success );
}
}

View File

@ -0,0 +1,50 @@
package org.apache.archiva.redback.rest.api.model;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.archiva.redback.keys.AuthenticationKey;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@XmlRootElement(name = "authenticationKeyResult")
public class AuthenticationKeyResult
{
String key = "";
public AuthenticationKeyResult() {
}
public AuthenticationKeyResult(String key) {
this.key = key;
}
public String getKey( )
{
return key;
}
public void setKey( String key )
{
this.key = key;
}
}

View File

@ -0,0 +1,48 @@
package org.apache.archiva.redback.rest.api.model;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@XmlRootElement(name="availabilityStatus")
public class AvailabilityStatus
{
boolean exists = false;
public AvailabilityStatus() {
}
public AvailabilityStatus(boolean exists) {
this.exists = exists;
}
public boolean isExists( )
{
return exists;
}
public void setExists( boolean exists )
{
this.exists = exists;
}
}

View File

@ -0,0 +1,45 @@
package org.apache.archiva.redback.rest.api.model;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class PasswordStatus
{
boolean changeRequired = false;
public PasswordStatus() {
}
public PasswordStatus(boolean changeRequired) {
this.changeRequired = changeRequired;
}
public boolean isChangeRequired( )
{
return changeRequired;
}
public void setChangeRequired( boolean changeRequired )
{
this.changeRequired = changeRequired;
}
}

View File

@ -0,0 +1,48 @@
package org.apache.archiva.redback.rest.api.model;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@XmlRootElement(name="pingResult")
public class PingResult
{
boolean success;
public PingResult() {
}
public PingResult( boolean success ) {
this.success = success;
}
public boolean isSuccess( )
{
return success;
}
public void setSuccess( boolean success )
{
this.success = success;
}
}

View File

@ -0,0 +1,48 @@
package org.apache.archiva.redback.rest.api.model;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@XmlRootElement(name="verificationStatus")
public class VerificationStatus
{
boolean success = false;
public VerificationStatus() {
}
public VerificationStatus(boolean success ) {
this.success = success;
}
public boolean isSuccess( )
{
return success;
}
public void setSuccess( boolean success )
{
this.success = success;
}
}

View File

@ -18,8 +18,10 @@ package org.apache.archiva.redback.rest.api.services;
* under the License.
*/
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.LdapGroupMapping;
import org.apache.archiva.redback.rest.api.model.LdapGroupMappingUpdateRequest;
import org.apache.archiva.redback.rest.api.model.StringList;
@ -40,6 +42,7 @@ import java.util.List;
* @since 2.1
*/
@Path("/ldapGroupMappingService/")
@Tag( name = "LDAP", description = "LDAP Service" )
public interface LdapGroupMappingService
{
@Path("ldapGroups")
@ -61,7 +64,7 @@ public interface LdapGroupMappingService
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@RedbackAuthorization(permissions = RedbackRoleConstants.CONFIGURATION_EDIT_OPERATION)
Boolean addLdapGroupMapping( LdapGroupMapping ldapGroupMapping )
ActionStatus addLdapGroupMapping( LdapGroupMapping ldapGroupMapping )
throws RedbackServiceException;
@DELETE
@ -69,14 +72,14 @@ public interface LdapGroupMappingService
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@RedbackAuthorization(permissions = RedbackRoleConstants.CONFIGURATION_EDIT_OPERATION)
Boolean removeLdapGroupMapping( @PathParam("group") String group )
ActionStatus removeLdapGroupMapping( @PathParam("group") String group )
throws RedbackServiceException;
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@RedbackAuthorization(permissions = RedbackRoleConstants.CONFIGURATION_EDIT_OPERATION)
Boolean updateLdapGroupMapping( LdapGroupMappingUpdateRequest ldapGroupMappingUpdateRequest )
ActionStatus updateLdapGroupMapping( LdapGroupMappingUpdateRequest ldapGroupMappingUpdateRequest )
throws RedbackServiceException;
}

View File

@ -20,7 +20,11 @@ package org.apache.archiva.redback.rest.api.services;
*/
import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.keys.AuthenticationKey;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.AuthenticationKeyResult;
import org.apache.archiva.redback.rest.api.model.LoginRequest;
import org.apache.archiva.redback.rest.api.model.PingResult;
import org.apache.archiva.redback.rest.api.model.User;
import javax.ws.rs.GET;
@ -38,9 +42,9 @@ public interface LoginService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true )
String addAuthenticationKey( @QueryParam( "providerKey" ) String providedKey,
@QueryParam( "principal" ) String principal, @QueryParam( "purpose" ) String purpose,
@QueryParam( "expirationMinutes" ) int expirationMinutes )
AuthenticationKeyResult addAuthenticationKey( @QueryParam( "providerKey" ) String providedKey,
@QueryParam( "principal" ) String principal, @QueryParam( "purpose" ) String purpose,
@QueryParam( "expirationMinutes" ) int expirationMinutes )
throws RedbackServiceException;
@ -48,7 +52,7 @@ public interface LoginService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true )
Boolean ping()
PingResult ping()
throws RedbackServiceException;
@ -56,7 +60,7 @@ public interface LoginService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = false, noPermission = true )
Boolean pingWithAutz()
PingResult pingWithAutz()
throws RedbackServiceException;
/**
@ -89,6 +93,6 @@ public interface LoginService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true, noPermission = true )
Boolean logout()
ActionStatus logout()
throws RedbackServiceException;
}

View File

@ -20,10 +20,13 @@ package org.apache.archiva.redback.rest.api.services;
import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.Application;
import org.apache.archiva.redback.rest.api.model.ApplicationRoles;
import org.apache.archiva.redback.rest.api.model.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.Role;
import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@ -46,8 +49,8 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean createTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
ActionStatus createTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
throws RedbackServiceException;
/**
@ -62,7 +65,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean removeTemplatedRole( @QueryParam( "templateId" ) String templateId,
ActionStatus removeTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
throws RedbackServiceException;
@ -81,7 +84,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean updateRole( @QueryParam( "templateId" ) String templateId, @QueryParam( "oldResource" ) String oldResource,
ActionStatus updateRole( @QueryParam( "templateId" ) String templateId, @QueryParam( "oldResource" ) String oldResource,
@QueryParam( "newResource" ) String newResource )
throws RedbackServiceException;
@ -96,7 +99,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean assignRole( @QueryParam( "roleId" ) String roleId, @QueryParam( "principal" ) String principal )
ActionStatus assignRole( @QueryParam( "roleId" ) String roleId, @QueryParam( "principal" ) String principal )
throws RedbackServiceException;
/**
@ -110,7 +113,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean assignRoleByName( @QueryParam( "roleName" ) String roleName, @QueryParam( "principal" ) String principal )
ActionStatus assignRoleByName( @QueryParam( "roleName" ) String roleName, @QueryParam( "principal" ) String principal )
throws RedbackServiceException;
/**
@ -126,7 +129,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean assignTemplatedRole( @QueryParam( "templateId" ) String templateId,
ActionStatus assignTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource,
@QueryParam( "principal" ) String principal )
throws RedbackServiceException;
@ -142,7 +145,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean unassignRole( @QueryParam( "roleId" ) String roleId, @QueryParam( "principal" ) String principal )
ActionStatus unassignRole( @QueryParam( "roleId" ) String roleId, @QueryParam( "principal" ) String principal )
throws RedbackServiceException;
/**
@ -156,7 +159,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean unassignRoleByName( @QueryParam( "roleName" ) String roleName, @QueryParam( "principal" ) String principal )
ActionStatus unassignRoleByName( @QueryParam( "roleName" ) String roleName, @QueryParam( "principal" ) String principal )
throws RedbackServiceException;
/**
@ -170,7 +173,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean roleExists( @QueryParam( "roleId" ) String roleId )
AvailabilityStatus roleExists( @QueryParam( "roleId" ) String roleId )
throws RedbackServiceException;
/**
@ -185,7 +188,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean templatedRoleExists( @QueryParam( "templateId" ) String templateId,
AvailabilityStatus templatedRoleExists( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
throws RedbackServiceException;
@ -201,8 +204,8 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean verifyTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
VerificationStatus verifyTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
throws RedbackServiceException;
/**
@ -265,7 +268,7 @@ public interface RoleManagementService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean updateRoleDescription( @QueryParam( "roleName" ) String roleName,
ActionStatus updateRoleDescription( @QueryParam( "roleName" ) String roleName,
@QueryParam( "roleDescription" ) String description )
throws RedbackServiceException;
@ -278,7 +281,7 @@ public interface RoleManagementService
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean updateRoleUsers( Role role )
ActionStatus updateRoleUsers( Role role )
throws RedbackServiceException;
/**
@ -300,7 +303,7 @@ public interface RoleManagementService
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Boolean updateUserRoles( User user )
ActionStatus updateUserRoles( User user )
throws RedbackServiceException;
}

View File

@ -21,13 +21,19 @@ package org.apache.archiva.redback.rest.api.services;
import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.Operation;
import org.apache.archiva.redback.rest.api.model.PasswordStatus;
import org.apache.archiva.redback.rest.api.model.Permission;
import org.apache.archiva.redback.rest.api.model.PingResult;
import org.apache.archiva.redback.rest.api.model.RegistrationKey;
import org.apache.archiva.redback.rest.api.model.ResetPasswordRequest;
import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.model.UserRegistrationRequest;
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
import javax.swing.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@ -61,7 +67,7 @@ public interface UserService
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_CREATE_OPERATION )
Boolean createUser( User user )
ActionStatus createUser( User user )
throws RedbackServiceException;
@ -73,14 +79,14 @@ public interface UserService
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( noRestriction = true )
Boolean createAdminUser( User user )
ActionStatus createAdminUser( User user )
throws RedbackServiceException;
@Path( "isAdminUserExists" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true )
Boolean isAdminUserExists()
AvailabilityStatus isAdminUserExists()
throws RedbackServiceException;
@ -88,14 +94,14 @@ public interface UserService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_DELETE_OPERATION )
Boolean deleteUser( @PathParam( "userName" ) String username )
ActionStatus deleteUser( @PathParam( "userName" ) String username )
throws RedbackServiceException;
@Path( "updateUser" )
@POST
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
Boolean updateUser( User user )
ActionStatus updateUser( User user )
throws RedbackServiceException;
/**
@ -105,7 +111,7 @@ public interface UserService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
Boolean lockUser( @PathParam( "username" ) String username )
ActionStatus lockUser( @PathParam( "username" ) String username )
throws RedbackServiceException;
/**
@ -115,7 +121,7 @@ public interface UserService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
Boolean unlockUser( @PathParam( "username" ) String username )
ActionStatus unlockUser( @PathParam( "username" ) String username )
throws RedbackServiceException;
@ -126,20 +132,9 @@ public interface UserService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
Boolean passwordChangeRequired( @PathParam( "username" ) String username )
PasswordStatus passwordChangeRequired( @PathParam( "username" ) String username )
throws RedbackServiceException;
/**
* @since 2.0
*/
@Path( "passwordChangeNotRequired/{username}" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
Boolean passwordChangeNotRequired( @PathParam( "username" ) String username )
throws RedbackServiceException;
/**
* update only the current user and this fields: fullname, email, password.
* the service verify the curent logged user with the one passed in the method
@ -149,21 +144,21 @@ public interface UserService
@POST
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = false, noPermission = true )
Boolean updateMe( User user )
ActionStatus updateMe( User user )
throws RedbackServiceException;
@Path( "ping" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true )
Boolean ping()
PingResult ping()
throws RedbackServiceException;
@Path( "removeFromCache/{userName}" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
int removeFromCache( @PathParam( "userName" ) String username )
ActionStatus removeFromCache( @PathParam( "userName" ) String username )
throws RedbackServiceException;
@Path( "getGuestUser" )
@ -202,7 +197,7 @@ public interface UserService
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( noRestriction = true, noPermission = true )
Boolean validateUserFromKey( @PathParam( "key" ) String key )
VerificationStatus validateUserFromKey( @PathParam( "key" ) String key )
throws RedbackServiceException;
/**
@ -215,7 +210,7 @@ public interface UserService
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( noRestriction = true, noPermission = true )
Boolean resetPassword( ResetPasswordRequest resetPasswordRequest )
ActionStatus resetPassword( ResetPasswordRequest resetPasswordRequest )
throws RedbackServiceException;
/**

View File

@ -0,0 +1,16 @@
resourcePackages:
- org.apache.archiva.redback.rest.api
prettyPrint: true
cacheTTL: 0
openAPI:
info:
version: '3.0'
title: Apache Archiva Redback REST API
description: 'This is the Apache Archiva Redback REST API documentation'
termsOfService: https://archiva.apache.org
contact:
email: dev@archiva.apache.org
url: https://archiva.apache.org/index.html
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html

View File

@ -0,0 +1,4 @@
{{#is this 'body-param'}}<div class="param">{{baseName}} {{#baseType}}<a href="#{{baseType}}">{{baseType}}</a>{{/baseType}} {{^required}}(optional){{/required}}{{#required}}(required){{/required}}</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; {{unescapedDescription}} {{#defaultValue}}default: {{{defaultValue}}}{{/defaultValue}}</div>{{/is}}
{{#example}}<div class="param-desc"><span class="param-type">example: <code>{{example}}</code></span></div>{{/example}}

View File

@ -0,0 +1,3 @@
{{#is this 'form-param'}}<div class="param">{{baseName}} {{^required}}(optional){{/required}}{{#required}}(required){{/required}}</div>
<div class="param-desc"><span class="param-type">Form Parameter</span> &mdash; {{unescapedDescription}} {{#defaultValue}}default: {{{defaultValue}}} {{/defaultValue}}{{#dataFormat}}format: {{{dataFormat}}}{{/dataFormat}}</div>{{/is}}

View File

@ -0,0 +1,3 @@
{{#is this 'header-param'}}<div class="param">{{baseName}} {{^required}}(optional){{/required}}{{#required}}(required){{/required}}</div>
<div class="param-desc"><span class="param-type">Header Parameter</span> &mdash; {{unescapedDescription}} {{#defaultValue}}default: {{{defaultValue}}} {{/defaultValue}}{{#dataFormat}}format: {{{dataFormat}}}{{/dataFormat}}</div>{{/is}}

View File

@ -0,0 +1,213 @@
<!doctype html>
<html>
<head>
<title>{{{appName}}}</title>
<style type="text/css">
{{>style.css}}
</style>
</head>
<body>
<h1>{{{appName}}}</h1>
<div class="app-desc">{{{appDescription}}}</div>
{{#infoUrl}}<div class="app-desc">More information: <a href="{{{infoUrl}}}">{{{infoUrl}}}</a></div>{{/infoUrl}}
{{#infoEmail}}<div class="app-desc">Contact Info: <a href="{{{infoEmail}}}">{{{infoEmail}}}</a></div>{{/infoEmail}}
{{#version}}<div class="app-desc">Version: {{{version}}}</div>{{/version}}
{{#basePathWithoutHost}}<div class="app-desc">BasePath:{{basePathWithoutHost}}</div>{{/basePathWithoutHost}}
<div class="license-info">{{{licenseInfo}}}</div>
<div class="license-url">{{{licenseUrl}}}</div>
<h2>Access</h2>
{{#hasAuthMethods}}
<ol>
{{#authMethods}}
<li>{{#is this 'basic'}}HTTP Basic Authentication{{/is}}{{#is this 'oauth'}}OAuth AuthorizationUrl:{{authorizationUrl}}TokenUrl:{{tokenUrl}}{{/is}}{{#is this 'api-key'}}APIKey KeyParamName:{{keyParamName}} KeyInQuery:{{isKeyInQuery}} KeyInHeader:{{isKeyInHeader}}{{/is}}</li>
{{/authMethods}}
</ol>
{{/hasAuthMethods}}
<h2><a name="__Methods">Methods</a></h2>
[ Jump to <a href="#__Models">Models</a> ]
{{! for the tables of content, I cheat and don't use CSS styles.... }}
<h3>Table of Contents </h3>
<div class="method-summary">{{access}}</div>
{{#apiInfo}}
{{#apis}}
{{#operations}}
<h4><a href="#{{baseName}}">{{baseName}}</a></h4>
<ul>
{{#operation}}
<li><a href="#{{nickname}}"><code><span class="http-method">{{httpMethod}}</span> {{path}}</code></a></li>
{{/operation}}
</ul>
{{/operations}}
{{/apis}}
{{/apiInfo}}
{{#apiInfo}}
{{#apis}}
{{#operations}}
<h1><a name="{{baseName}}">{{baseName}}</a></h1>
{{#operation}}
<div class="method"><a name="{{nickname}}"></a>
<div class="method-path">
<a class="up" href="#__Methods">Up</a>
<pre class="{{httpMethod}}"><code class="huge"><span class="http-method">{{httpMethod}}</span> {{path}}</code></pre></div>
<div class="method-summary">{{summary}} (<span class="nickname">{{nickname}}</span>)</div>
{{! notes is operation.description. So why rename it and make it super confusing???? }}
<div class="method-notes">{{notes}}</div>
{{#hasPathParams}}
<h3 class="field-label">Path parameters</h3>
<div class="field-items">
{{#pathParams}}{{>pathParam}}{{/pathParams}}
</div> <!-- field-items -->
{{/hasPathParams}}
{{#has this 'consumes'}}
<h3 class="field-label">Consumes</h3>
This API call consumes the following media types via the <span class="header">Content-Type</span> request header:
<ul>
{{#consumes}}
<li><code>{{{mediaType}}}</code></li>
{{/consumes}}
</ul>
{{/has}}
{{#hasBodyParam}}
<h3 class="field-label">Request body</h3>
<div class="field-items">
{{#bodyParams}}{{>bodyParam}}{{/bodyParams}}
</div> <!-- field-items -->
{{/hasBodyParam}}
{{#hasHeaderParams}}
<h3 class="field-label">Request headers</h3>
<div class="field-items">
{{#headerParam}}{{>headerParam}}{{/headerParam}}
</div> <!-- field-items -->
{{/hasHeaderParams}}
{{#hasQueryParams}}
<h3 class="field-label">Query parameters</h3>
<div class="field-items">
{{#queryParams}}{{>queryParam}}{{/queryParams}}
</div> <!-- field-items -->
{{/hasQueryParams}}
{{#hasFormParams}}
<h3 class="field-label">Form parameters</h3>
<div class="field-items">
{{#formParams}}{{>formParam}}{{/formParams}}
</div> <!-- field-items -->
{{/hasFormParams}}
{{#returnType}}
<h3 class="field-label">Return type</h3>
<div class="return-type">
{{#hasReference}}{{^returnSimpleType}}{{returnContainer}}[{{/returnSimpleType}}<a href="#{{returnBaseType}}">{{returnBaseType}}</a>{{^returnSimpleType}}]{{/returnSimpleType}}{{/hasReference}}
{{^hasReference}}{{returnType}}{{/hasReference}}
</div>
{{/returnType}}
<!--Todo: process Response Object and its headers, schema, examples -->
{{#hasExamples}}
{{#examples}}
<h3 class="field-label">Example data</h3>
<div class="example-data-content-type">Content-Type: {{{contentType}}}</div>
<pre class="example"><code>{{{example}}}</code></pre>
{{/examples}}
{{/hasExamples}}
{{#has this 'produces'}}
<h3 class="field-label">Produces</h3>
This API call produces the following media types according to the <span class="header">Accept</span> request header;
the media type will be conveyed by the <span class="header">Content-Type</span> response header.
<ul>
{{#produces}}
<li><code>{{{mediaType}}}</code></li>
{{/produces}}
</ul>
{{/has}}
<h3 class="field-label">Responses</h3>
{{#responses}}
<h4 class="field-label">{{code}}</h4>
{{message}}
{{#simpleType}}<a href="#{{dataType}}">{{dataType}}</a>{{/simpleType}}
{{#examples}}
<h3 class="field-label">Example data</h3>
<div class="example-data-content-type">Content-Type: {{{contentType}}}</div>
<pre class="example"><code>{{example}}</code></pre>
{{/examples}}
{{/responses}}
</div> <!-- method -->
<hr/>
{{/operation}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
<h2><a name="__Models">Models</a></h2>
[ Jump to <a href="#__Methods">Methods</a> ]
<h3>Table of Contents</h3>
<ol>
{{#models}}
{{#model}}
<li><a href="#{{name}}"><code>{{name}}</code>{{#title}} - {{title}}{{/title}}</a></li>
{{/model}}
{{/models}}
</ol>
{{#models}}
{{#model}}
<div class="model">
<h3><a name="{{name}}"><code>{{name}}</code>{{#title}} - {{title}}{{/title}}</a> <a class="up" href="#__Models">Up</a></h3>
{{#unescapedDescription}}<div class='model-description'>{{unescapedDescription}}</div>{{/unescapedDescription}}
<div class="field-items">
{{#vars}}<div class="param">{{name}} {{^required}}(optional){{/required}}</div><div class="param-desc"><span class="param-type">{{#isNot this 'primitive-type'}}<a href="#{{complexType}}">{{datatype}}</a>{{/isNot}}</span> {{unescapedDescription}} {{#dataFormat}}format: {{{dataFormat}}}{{/dataFormat}}</div>
{{#is this 'enum'}}
<div class="param-enum-header">Enum:</div>
{{#_enum}}<div class="param-enum">{{this}}</div>{{/_enum}}
{{/is}}
{{#example}}
<div class="param-desc"><span class="param-type">example: {{example}}</span></div>
{{/example}}
{{#vendorExtensions.oneOf-model}}
<div class="param-desc"><span class="param-type">oneOf:</span>
{{#vendorExtensions.x-model-names}}
<a href="#{{this}}"><code>{{this}}</code></a>&nbsp;&nbsp;&nbsp;
{{/vendorExtensions.x-model-names}}
</div>
{{/vendorExtensions.oneOf-model}}
{{#vendorExtensions.anyOf-model}}
<div class="param-desc"><span class="param-type">anyOf:</span>
{{#vendorExtensions.x-model-names}}
<a href="#{{this}}"><code>{{this}}</code></a>&nbsp;&nbsp;&nbsp;
{{/vendorExtensions.x-model-names}}
</div>
{{/vendorExtensions.anyOf-model}}
{{#items}}
{{#vendorExtensions.oneOf-model}}
<div class="param-desc"><span class="param-type">items oneOf:</span>
{{#vendorExtensions.x-model-names}}
<a href="#{{this}}"><code>{{this}}</code></a>&nbsp;&nbsp;&nbsp;
{{/vendorExtensions.x-model-names}}
</div>
{{/vendorExtensions.oneOf-model}}
{{#vendorExtensions.anyOf-model}}
<div class="param-desc"><span class="param-type">items anyOf:</span>
{{#vendorExtensions.x-model-names}}
<a href="#{{this}}"><code>{{this}}</code></a>&nbsp;&nbsp;&nbsp;
{{/vendorExtensions.x-model-names}}
</div>
{{/vendorExtensions.anyOf-model}}
{{/items}}
{{/vars}}
</div> <!-- field-items -->
</div>
{{/model}}
{{/models}}
</body>
</html>

View File

@ -0,0 +1,3 @@
{{#is this 'path-param'}}<div class="param">{{baseName}} {{^required}}(optional){{/required}}{{#required}}(required){{/required}}</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; {{unescapedDescription}} {{#defaultValue}}default: {{{defaultValue}}} {{/defaultValue}}{{#dataFormat}}format: {{{dataFormat}}}{{/dataFormat}}</div>{{/is}}

View File

@ -0,0 +1,3 @@
{{#is this 'query-param'}}<div class="param">{{baseName}} {{^required}}(optional){{/required}}{{#required}}(required){{/required}}</div>
<div class="param-desc"><span class="param-type">Query Parameter</span> &mdash; {{unescapedDescription}} {{#defaultValue}}default: {{{defaultValue}}} {{/defaultValue}}{{#dataFormat}}format: {{{dataFormat}}}{{/dataFormat}}</div>{{/is}}

View File

@ -0,0 +1,172 @@
body {
font-family: Trebuchet MS, sans-serif;
font-size: 15px;
color: #444;
margin-right: 24px;
}
h1 {
font-size: 25px;
}
h2 {
font-size: 20px;
}
h3 {
font-size: 16px;
font-weight: bold;
}
hr {
height: 1px;
border: 0;
color: #ddd;
background-color: #ddd;
}
.app-desc {
clear: both;
margin-left: 20px;
}
.param-name {
width: 100%;
}
.license-info {
margin-left: 20px;
}
.license-url {
margin-left: 20px;
}
.model {
margin: 0 0 0px 20px;
}
.method {
margin-left: 20px;
}
.method-notes {
margin: 10px 0 20px 0;
font-size: 90%;
color: #555;
}
pre {
padding: 10px;
margin-bottom: 2px;
}
.http-method {
text-transform: uppercase;
}
pre.get {
background-color: #0f6ab4;
}
pre.post {
background-color: #10a54a;
}
pre.put {
background-color: #c5862b;
}
pre.delete {
background-color: #a41e22;
}
.huge {
color: #fff;
}
pre.example {
background-color: #f3f3f3;
padding: 10px;
border: 1px solid #ddd;
}
code {
white-space: pre;
}
.nickname {
font-weight: bold;
}
.method-path {
font-size: 1.5em;
background-color: #0f6ab4;
}
.up {
float:right;
}
.parameter {
width: 500px;
}
.param {
width: 500px;
padding: 10px 0 0 20px;
font-weight: bold;
}
.param-desc {
width: 700px;
padding: 0 0 0 20px;
color: #777;
}
.param-type {
font-style: italic;
}
.param-enum-header {
width: 700px;
padding: 0 0 0 60px;
color: #777;
font-weight: bold;
}
.param-enum {
width: 700px;
padding: 0 0 0 80px;
color: #777;
font-style: italic;
}
.field-label {
padding: 0;
margin: 0;
clear: both;
}
.field-items {
padding: 0 0 15px 0;
margin-bottom: 15px;
}
.return-type {
clear: both;
padding-bottom: 10px;
}
.param-header {
font-weight: bold;
}
.method-tags {
text-align: right;
}
.method-tag {
background: none repeat scroll 0% 0% #24A600;
border-radius: 3px;
padding: 2px 10px;
margin: 2px;
color: #FFF;
display: inline-block;
text-decoration: none;
}

View File

@ -186,6 +186,11 @@
<artifactId>jackson-jaxrs-xml-provider</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
@ -327,6 +332,15 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
<configuration>
<excludes>
<exclude>src/main/resources/META-INF/cxf/org.apache.cxf.Logger</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>

View File

@ -24,6 +24,7 @@ import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
import org.apache.archiva.redback.common.ldap.connection.LdapException;
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapperConfiguration;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.LdapGroupMapping;
import org.apache.archiva.redback.rest.api.model.LdapGroupMappingUpdateRequest;
import org.apache.archiva.redback.rest.api.model.StringList;
@ -111,7 +112,7 @@ public class DefaultLdapGroupMappingService
}
}
public Boolean addLdapGroupMapping( LdapGroupMapping ldapGroupMapping )
public ActionStatus addLdapGroupMapping( LdapGroupMapping ldapGroupMapping )
throws RedbackServiceException
{
try
@ -124,10 +125,10 @@ public class DefaultLdapGroupMappingService
log.error( e.getMessage(), e );
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean removeLdapGroupMapping( String group )
public ActionStatus removeLdapGroupMapping( String group )
throws RedbackServiceException
{
try
@ -139,10 +140,10 @@ public class DefaultLdapGroupMappingService
log.error( e.getMessage(), e );
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean updateLdapGroupMapping( LdapGroupMappingUpdateRequest ldapGroupMappingUpdateRequest )
public ActionStatus updateLdapGroupMapping( LdapGroupMappingUpdateRequest ldapGroupMappingUpdateRequest )
throws RedbackServiceException
{
try
@ -158,7 +159,7 @@ public class DefaultLdapGroupMappingService
log.error( e.getMessage(), e );
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
//------------------

View File

@ -32,8 +32,11 @@ import org.apache.archiva.redback.keys.memory.MemoryAuthenticationKey;
import org.apache.archiva.redback.keys.memory.MemoryKeyManager;
import org.apache.archiva.redback.policy.AccountLockedException;
import org.apache.archiva.redback.policy.MustChangePasswordException;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.AuthenticationKeyResult;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.LoginRequest;
import org.apache.archiva.redback.rest.api.model.PingResult;
import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.services.LoginService;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
@ -87,7 +90,7 @@ public class DefaultLoginService
}
public String addAuthenticationKey( String providedKey, String principal, String purpose, int expirationMinutes )
public AuthenticationKeyResult addAuthenticationKey( String providedKey, String principal, String purpose, int expirationMinutes )
throws RedbackServiceException
{
KeyManager keyManager = securitySystem.getKeyManager();
@ -118,19 +121,19 @@ public class DefaultLoginService
keyManager.addKey( key );
return key.getKey();
return new AuthenticationKeyResult( key.getKey( ) );
}
public Boolean ping()
public PingResult ping()
throws RedbackServiceException
{
return Boolean.TRUE;
return new PingResult( true);
}
public Boolean pingWithAutz()
public PingResult pingWithAutz()
throws RedbackServiceException
{
return Boolean.TRUE;
return new PingResult( true );
}
public User logIn( LoginRequest loginRequest )
@ -220,7 +223,7 @@ public class DefaultLoginService
return isLogged && securitySession.getUser() != null ? buildRestUser( securitySession.getUser() ) : null;
}
public Boolean logout()
public ActionStatus logout()
throws RedbackServiceException
{
HttpSession httpSession = httpServletRequest.getSession();
@ -228,7 +231,7 @@ public class DefaultLoginService
{
httpSession.invalidate();
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
private Calendar getNowGMT()

View File

@ -26,11 +26,14 @@ import org.apache.archiva.redback.rbac.RBACManager;
import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.Resource;
import org.apache.archiva.redback.rbac.UserAssignment;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.Application;
import org.apache.archiva.redback.rest.api.model.ApplicationRoles;
import org.apache.archiva.redback.rest.api.model.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.Role;
import org.apache.archiva.redback.rest.api.model.RoleTemplate;
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.RoleManagementService;
import org.apache.archiva.redback.role.RoleManager;
@ -90,7 +93,7 @@ public class DefaultRoleManagementService
log.debug( "use userManager impl: {}", userManager.getClass().getName() );
}
public Boolean createTemplatedRole( String templateId, String resource )
public ActionStatus createTemplatedRole( String templateId, String resource )
throws RedbackServiceException
{
try
@ -101,10 +104,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean removeTemplatedRole( String templateId, String resource )
public ActionStatus removeTemplatedRole( String templateId, String resource )
throws RedbackServiceException
{
@ -116,10 +119,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean updateRole( String templateId, String oldResource, String newResource )
public ActionStatus updateRole( String templateId, String oldResource, String newResource )
throws RedbackServiceException
{
try
@ -130,10 +133,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean assignRole( String roleId, String principal )
public ActionStatus assignRole( String roleId, String principal )
throws RedbackServiceException
{
try
@ -144,10 +147,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean assignRoleByName( String roleName, String principal )
public ActionStatus assignRoleByName( String roleName, String principal )
throws RedbackServiceException
{
try
@ -158,10 +161,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean assignTemplatedRole( String templateId, String resource, String principal )
public ActionStatus assignTemplatedRole( String templateId, String resource, String principal )
throws RedbackServiceException
{
try
@ -172,10 +175,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean unassignRole( String roleId, String principal )
public ActionStatus unassignRole( String roleId, String principal )
throws RedbackServiceException
{
try
@ -186,10 +189,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean unassignRoleByName( String roleName, String principal )
public ActionStatus unassignRoleByName( String roleName, String principal )
throws RedbackServiceException
{
try
@ -200,15 +203,15 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean roleExists( String roleId )
public AvailabilityStatus roleExists( String roleId )
throws RedbackServiceException
{
try
{
return roleManager.roleExists( roleId );
return new AvailabilityStatus( roleManager.roleExists( roleId ) );
}
catch ( RoleManagerException e )
{
@ -216,12 +219,12 @@ public class DefaultRoleManagementService
}
}
public Boolean templatedRoleExists( String templateId, String resource )
public AvailabilityStatus templatedRoleExists( String templateId, String resource )
throws RedbackServiceException
{
try
{
return roleManager.templatedRoleExists( templateId, resource );
return new AvailabilityStatus( roleManager.templatedRoleExists( templateId, resource ) );
}
catch ( RoleManagerException e )
{
@ -230,7 +233,7 @@ public class DefaultRoleManagementService
}
public Boolean verifyTemplatedRole( String templateId, String resource )
public VerificationStatus verifyTemplatedRole( String templateId, String resource )
throws RedbackServiceException
{
try
@ -241,7 +244,7 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( e.getMessage() );
}
return Boolean.TRUE;
return new VerificationStatus( true );
}
public List<Role> getEffectivelyAssignedRoles( String username )
@ -460,7 +463,7 @@ public class DefaultRoleManagementService
}
}
public Boolean updateRoleDescription( String roleName, String description )
public ActionStatus updateRoleDescription( String roleName, String description )
throws RedbackServiceException
{
try
@ -473,10 +476,10 @@ public class DefaultRoleManagementService
{
throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean updateRoleUsers( Role role )
public ActionStatus updateRoleUsers( Role role )
throws RedbackServiceException
{
@ -562,7 +565,7 @@ public class DefaultRoleManagementService
}
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public List<ApplicationRoles> getApplicationRoles( String username )
@ -671,7 +674,7 @@ public class DefaultRoleManagementService
}
}
public Boolean updateUserRoles( org.apache.archiva.redback.rest.api.model.User user )
public ActionStatus updateUserRoles( org.apache.archiva.redback.rest.api.model.User user )
throws RedbackServiceException
{
@ -736,7 +739,7 @@ public class DefaultRoleManagementService
throw redbackServiceException;
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}

View File

@ -39,14 +39,19 @@ import org.apache.archiva.redback.policy.UserSecurityPolicy;
import org.apache.archiva.redback.rbac.RBACManager;
import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.UserAssignment;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.Operation;
import org.apache.archiva.redback.rest.api.model.PasswordStatus;
import org.apache.archiva.redback.rest.api.model.Permission;
import org.apache.archiva.redback.rest.api.model.PingResult;
import org.apache.archiva.redback.rest.api.model.RegistrationKey;
import org.apache.archiva.redback.rest.api.model.ResetPasswordRequest;
import org.apache.archiva.redback.rest.api.model.Resource;
import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.model.UserRegistrationRequest;
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.UserService;
import org.apache.archiva.redback.rest.services.utils.PasswordValidator;
@ -141,7 +146,8 @@ public class DefaultUserService
}
public Boolean createUser( User user )
@Override
public ActionStatus createUser( User user )
throws RedbackServiceException
{
@ -216,10 +222,11 @@ public class DefaultUserService
{
throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean deleteUser( String username )
@Override
public ActionStatus deleteUser( String username )
throws RedbackServiceException
{
@ -241,7 +248,7 @@ public class DefaultUserService
try
{
userManager.deleteUser( username );
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
catch ( UserNotFoundException e )
{
@ -259,6 +266,7 @@ public class DefaultUserService
}
@Override
public User getUser( String username )
throws RedbackServiceException
{
@ -277,6 +285,7 @@ public class DefaultUserService
}
}
@Override
public List<User> getUsers()
throws RedbackServiceException
{
@ -298,7 +307,8 @@ public class DefaultUserService
}
}
public Boolean updateMe( User user )
@Override
public ActionStatus updateMe( User user )
throws RedbackServiceException
{
// check username == one in the session
@ -365,10 +375,11 @@ public class DefaultUserService
updateUser( realUser );
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean updateUser( User user )
@Override
public ActionStatus updateUser( User user )
throws RedbackServiceException
{
try
@ -383,7 +394,7 @@ public class DefaultUserService
rawUser.setPermanent( user.isPermanent() );
userManager.updateUser( rawUser );
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
catch ( UserNotFoundException e )
{
@ -395,7 +406,8 @@ public class DefaultUserService
}
}
public int removeFromCache( String userName )
@Override
public ActionStatus removeFromCache( String userName )
throws RedbackServiceException
{
if ( userAssignmentsCache != null )
@ -421,9 +433,10 @@ public class DefaultUserService
}
}
return 0;
return ActionStatus.SUCCESS;
}
@Override
public User getGuestUser()
throws RedbackServiceException
{
@ -438,6 +451,7 @@ public class DefaultUserService
}
}
@Override
public User createGuestUser()
throws RedbackServiceException
{
@ -475,10 +489,11 @@ public class DefaultUserService
}
}
public Boolean ping()
@Override
public PingResult ping()
throws RedbackServiceException
{
return Boolean.TRUE;
return new PingResult( true );
}
private User getSimpleUser( org.apache.archiva.redback.users.User user )
@ -490,12 +505,13 @@ public class DefaultUserService
return new User( user );
}
public Boolean createAdminUser( User adminUser )
@Override
public ActionStatus createAdminUser( User adminUser )
throws RedbackServiceException
{
if ( isAdminUserExists() )
if ( isAdminUserExists().isExists() )
{
return Boolean.FALSE;
return ActionStatus.FAIL;
}
log.debug("Creating admin admin user '{}'", adminUser.getUsername());
if (!RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME.equals(adminUser.getUsername())) {
@ -526,16 +542,17 @@ public class DefaultUserService
{
throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
public Boolean isAdminUserExists()
@Override
public AvailabilityStatus isAdminUserExists()
throws RedbackServiceException
{
try
{
userManager.findUser( config.getString( UserConfigurationKeys.DEFAULT_ADMIN ) );
return Boolean.TRUE;
return new AvailabilityStatus( true );
}
catch ( UserNotFoundException e )
{
@ -547,14 +564,15 @@ public class DefaultUserService
if ( cause != null && cause instanceof UserNotFoundException )
{
return Boolean.FALSE;
return new AvailabilityStatus( false );
}
throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) );
}
return Boolean.FALSE;
return new AvailabilityStatus( false );
}
public Boolean resetPassword( ResetPasswordRequest resetPasswordRequest )
@Override
public ActionStatus resetPassword( ResetPasswordRequest resetPasswordRequest )
throws RedbackServiceException
{
String username = resetPasswordRequest.getUsername();
@ -598,9 +616,10 @@ public class DefaultUserService
throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) );
}
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
@Override
public RegistrationKey registerUser( UserRegistrationRequest userRegistrationRequest )
throws RedbackServiceException
{
@ -715,7 +734,8 @@ public class DefaultUserService
}
public Boolean validateUserFromKey( String key )
@Override
public VerificationStatus validateUserFromKey( String key )
throws RedbackServiceException
{
String principal = null;
@ -744,7 +764,7 @@ public class DefaultUserService
log.info( "account validated for user {}", user.getUsername() );
return Boolean.TRUE;
return new VerificationStatus( true );
}
catch ( MustChangePasswordException | AccountLockedException | AuthenticationException e )
{
@ -771,6 +791,7 @@ public class DefaultUserService
}
}
@Override
public Collection<Permission> getCurrentUserPermissions()
throws RedbackServiceException
{
@ -788,6 +809,7 @@ public class DefaultUserService
return getUserPermissions( userName );
}
@Override
public Collection<Operation> getCurrentUserOperations()
throws RedbackServiceException
{
@ -805,6 +827,7 @@ public class DefaultUserService
return getUserOperations( userName );
}
@Override
public Collection<Operation> getUserOperations( String userName )
throws RedbackServiceException
{
@ -822,6 +845,7 @@ public class DefaultUserService
return operations;
}
@Override
public Collection<Permission> getUserPermissions( String userName )
throws RedbackServiceException
{
@ -950,7 +974,8 @@ public class DefaultUserService
return null;
}
public Boolean unlockUser( String username )
@Override
public ActionStatus unlockUser( String username )
throws RedbackServiceException
{
User user = getUser( username );
@ -958,12 +983,13 @@ public class DefaultUserService
{
user.setLocked( false );
updateUser( user );
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
return Boolean.FALSE;
return ActionStatus.FAIL;
}
public Boolean lockUser( String username )
@Override
public ActionStatus lockUser( String username )
throws RedbackServiceException
{
User user = getUser( username );
@ -971,12 +997,13 @@ public class DefaultUserService
{
user.setLocked( true );
updateUser( user );
return Boolean.TRUE;
return ActionStatus.SUCCESS;
}
return Boolean.FALSE;
return ActionStatus.FAIL;
}
public Boolean passwordChangeRequired( String username )
@Override
public PasswordStatus passwordChangeRequired( String username )
throws RedbackServiceException
{
User user = getUser( username );
@ -984,21 +1011,9 @@ public class DefaultUserService
{
user.setPasswordChangeRequired( true );
updateUser( user );
return Boolean.TRUE;
return new PasswordStatus( true );
}
return Boolean.FALSE;
return new PasswordStatus( false );
}
public Boolean passwordChangeNotRequired( String username )
throws RedbackServiceException
{
User user = getUser( username );
if ( user == null )
{
user.setPasswordChangeRequired( false );
updateUser( user );
return Boolean.TRUE;
}
return Boolean.FALSE;
}
}

View File

@ -20,11 +20,14 @@ package org.apache.archiva.redback.rest.services.interceptors;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.eclipse.jetty.util.annotation.Name;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
import javax.inject.Named;
/**
* to setup some ObjectMapper configuration
@ -38,10 +41,12 @@ public class JacksonJsonConfigurator
private Logger log = LoggerFactory.getLogger( getClass() );
@Inject
public JacksonJsonConfigurator( ObjectMapper objectMapper )
public JacksonJsonConfigurator( @Named("redbackJacksonJsonMapper") ObjectMapper objectMapper,
@Name( "redbackJacksonXMLMapper" ) XmlMapper xmlMapper)
{
log.info( "configure jackson ObjectMapper" );
objectMapper.disable( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES );
xmlMapper.disable( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES );
}
}

View File

@ -0,0 +1 @@
org.apache.cxf.common.logging.Slf4jLogger

View File

@ -40,12 +40,17 @@
base-package="org.apache.archiva.redback.rest.services"/>
<bean id="jsonProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider">
<property name="mapper" ref="redbackJacksonMapper"/>
<property name="mapper" ref="redbackJacksonJsonMapper"/>
</bean>
<bean id="redbackJacksonMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
<bean id="xmlProvider" class="com.fasterxml.jackson.jaxrs.xml.JacksonJaxbXMLProvider">
<property name="mapper" ref="redbackJacksonXMLMapper"/>
</bean>
<bean id="redbackJacksonJsonMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
<bean id="redbackJacksonXMLMapper" class="com.fasterxml.jackson.dataformat.xml.XmlMapper" />
<jaxrs:server id="redbackServices" address="/redbackServices">
<jaxrs:serviceBeans>
@ -59,6 +64,7 @@
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="xmlProvider"/>
<ref bean="authenticationInterceptor#rest"/>
<ref bean="permissionInterceptor#rest"/>
<ref bean="redbackServiceExceptionMapper"/>

View File

@ -161,7 +161,7 @@ public abstract class AbstractRestServicesTest
adminUser.setPassword( FakeCreateAdminServiceImpl.ADMIN_TEST_PWD );
adminUser.setFullName( "the admin user" );
adminUser.setEmail( "toto@toto.fr" );
Boolean res = userService.createAdminUser( adminUser );
Boolean res = userService.createAdminUser( adminUser ).isSuccess();
FakeCreateAdminService fakeCreateAdminService = getFakeCreateAdminService();
//assertTrue( res.booleanValue() );

View File

@ -49,8 +49,8 @@ public class RoleManagementServiceTest
public void roleExist()
throws Exception
{
assertTrue( getRoleManagementService( authorizationHeader ).roleExists( "guest" ) );
assertFalse( getRoleManagementService( authorizationHeader ).roleExists( "foo" ) );
assertTrue( getRoleManagementService( authorizationHeader ).roleExists( "guest" ).isExists() );
assertFalse( getRoleManagementService( authorizationHeader ).roleExists( "foo" ).isExists() );
}
@Test( expected = ForbiddenException.class )
@ -59,7 +59,7 @@ public class RoleManagementServiceTest
{
try
{
assertTrue( getRoleManagementService( null ).roleExists( "guest" ) );
assertTrue( getRoleManagementService( null ).roleExists( "guest" ).isExists() );
}
catch ( ForbiddenException e )
{

View File

@ -59,7 +59,7 @@ public class UserServiceTest
public void ping()
throws Exception
{
Boolean res = getUserService().ping();
Boolean res = getUserService().ping().isSuccess();
assertTrue( res.booleanValue() );
}
@ -167,7 +167,7 @@ public class UserServiceTest
assertThat( messageContent ).contains( "Use the following URL to validate your account." ).contains(
"http://wine.fr/bordeaux" ).containsIgnoringCase( "toto" );
assertTrue( service.validateUserFromKey( key ) );
assertTrue( service.validateUserFromKey( key ).isSuccess() );
service = getUserService( authorizationHeader );
@ -177,7 +177,7 @@ public class UserServiceTest
assertTrue( u.isValidated() );
assertTrue( u.isPasswordChangeRequired() );
assertTrue( service.validateUserFromKey( key ) );
assertTrue( service.validateUserFromKey( key ).isSuccess() );
}
catch ( Exception e )
@ -226,7 +226,7 @@ public class UserServiceTest
assertThat( messageContent ).contains( "Use the following URL to validate your account." ).contains(
"http://localhost:" + getServerPort() ).containsIgnoringCase( "toto" );
assertTrue( service.validateUserFromKey( key ) );
assertTrue( service.validateUserFromKey( key ).isSuccess() );
service = getUserService( authorizationHeader );
@ -236,7 +236,7 @@ public class UserServiceTest
assertTrue( u.isValidated() );
assertTrue( u.isPasswordChangeRequired() );
assertTrue( service.validateUserFromKey( key ) );
assertTrue( service.validateUserFromKey( key ).isSuccess() );
}
catch ( Exception e )
@ -284,7 +284,7 @@ public class UserServiceTest
assertTrue(
emailMessages.get( 0 ).getText().contains( "Use the following URL to validate your account." ) );
assertTrue( service.validateUserFromKey( key ) );
assertTrue( service.validateUserFromKey( key ).isSuccess() );
service = getUserService( authorizationHeader );
@ -294,9 +294,9 @@ public class UserServiceTest
assertTrue( u.isValidated() );
assertTrue( u.isPasswordChangeRequired() );
assertTrue( service.validateUserFromKey( key ) );
assertTrue( service.validateUserFromKey( key ).isSuccess() );
assertTrue( service.resetPassword( new ResetPasswordRequest( "toto", "http://foo.fr/bar" ) ) );
assertTrue( service.resetPassword( new ResetPasswordRequest( "toto", "http://foo.fr/bar" ) ).isSuccess() );
emailMessages = assertService.getEmailMessageSended();
assertEquals( 2, emailMessages.size() );