API V2 refactoring and OpenAPI documentation

This commit is contained in:
Martin Stockhammer 2020-11-02 16:58:59 +01:00
parent ad45e62ef2
commit 8696d7cee3
15 changed files with 1026 additions and 176 deletions

View File

@ -18,6 +18,8 @@ package org.apache.archiva.redback.rest.api.model;
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
@ -26,17 +28,18 @@ import java.io.Serializable;
* @since 1.4
*/
@XmlRootElement( name = "errorMessage" )
@Schema(name="ErrorMessage",description = "Information about the error, that occured while processing the REST request.")
public class ErrorMessage
implements Serializable
{
private String errorKey;
private String errorKey = "";
private String[] args;
private String[] args = EMPTY;
/**
* @since 2.1 for message without any key
*/
private String message;
private String message = "";
private static final String[] EMPTY = new String[0];
@ -61,6 +64,7 @@ public class ErrorMessage
return new ErrorMessage( errorKey, args );
}
@Schema(description = "The key of the error message. If this is empty, the message message must be set.")
public String getErrorKey()
{
return errorKey;
@ -71,6 +75,7 @@ public class ErrorMessage
this.errorKey = errorKey;
}
@Schema(description = "Parameters that can be filled to the translated error message")
public String[] getArgs()
{
return args;
@ -81,6 +86,7 @@ public class ErrorMessage
this.args = args;
}
@Schema(description = "Full error message. Either additional to the key in the default language, or if the message is without key.")
public String getMessage()
{
return message;

View File

@ -18,6 +18,7 @@ package org.apache.archiva.redback.rest.api.model;
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.commons.lang3.StringUtils;
@ -31,6 +32,7 @@ import java.util.List;
* @since 1.4
*/
@XmlRootElement( name = "redbackRestError" )
@Schema(name="RedbackRestError", description = "Contains a list of error messages that resulted from the current REST call")
public class RedbackRestError
implements Serializable
{
@ -51,7 +53,7 @@ public class RedbackRestError
}
}
@Schema(name="errorMessages", description = "The list of errors that occurred while processing the REST request")
public List<ErrorMessage> getErrorMessages()
{
return errorMessages;

View File

@ -18,6 +18,8 @@ package org.apache.archiva.redback.rest.api.model.v2;
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlRootElement;
import java.time.Instant;
import java.time.OffsetDateTime;
@ -30,6 +32,7 @@ import java.time.ZoneId;
* @author Martin Stockhammer <martin_s@apache.org>
*/
@XmlRootElement(name="availabilityStatus")
@Schema(name="AvailabilityStatus", description = "Status of availability of a requested resource")
public class AvailabilityStatus
{
boolean exists = false;
@ -50,6 +53,7 @@ public class AvailabilityStatus
this.since = OffsetDateTime.ofInstant( Instant.EPOCH, ZoneId.systemDefault() );
}
@Schema(description = "Returns true, if the resource exists")
public boolean isExists( )
{
return exists;
@ -60,6 +64,7 @@ public class AvailabilityStatus
this.exists = exists;
}
@Schema(description = "Returns the last date since the resource was updated")
public OffsetDateTime getSince( )
{
return since;

View File

@ -0,0 +1,98 @@
package org.apache.archiva.redback.rest.api.model.v2;
/*
* 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 io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
/**
* @author Olivier Lamy
* @since 1.4
*/
@XmlRootElement( name = "operation" )
@Schema(name="Operation", description = "Operation assigned to a permission")
public class Operation
implements Serializable
{
private static final long serialVersionUID = 3666638961610656624L;
private String name;
private String description;
private boolean permanent;
public Operation()
{
// no op
}
public Operation( org.apache.archiva.redback.rbac.Operation operation )
{
this.name = operation.getName();
this.description = operation.getDescription();
this.permanent = operation.isPermanent();
}
@Schema(description = "The operation name")
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
@Schema(description = "The description of the operation")
public String getDescription()
{
return description;
}
public void setDescription( String description )
{
this.description = description;
}
@Schema(description = "True, if this operation is permanent")
public boolean isPermanent()
{
return permanent;
}
public void setPermanent( boolean permanent )
{
this.permanent = permanent;
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append( "Operation" );
sb.append( "{name='" ).append( name ).append( '\'' );
sb.append( ", description='" ).append( description ).append( '\'' );
sb.append( ", permanent=" ).append( permanent );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -0,0 +1,107 @@
package org.apache.archiva.redback.rest.api.model.v2;
/*
* 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 io.swagger.v3.oas.annotations.media.Schema;
import org.apache.archiva.redback.rest.api.model.v2.Resource;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
/**
* @author Olivier Lamy
* @since 1.4
*/
@XmlRootElement( name = "permission" )
@Schema(name="Permission", description = "Permission that allows operation on resources")
public class Permission
implements Serializable
{
private static final long serialVersionUID = 4243488525173718059L;
private String name;
private String description;
private Operation operation;
private Resource resource;
private boolean permanent;
public Permission()
{
// no op
}
public Permission( org.apache.archiva.redback.rbac.Permission permission )
{
this.name = permission.getName();
this.description = permission.getDescription();
this.operation = permission.getOperation() == null ? null : new Operation( permission.getOperation() );
this.resource = permission.getResource() == null ? null : new Resource( permission.getResource() );
this.permanent = permission.isPermanent();
}
@Schema(name="name", description = "The identifier of the permission")
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
@Schema(name="operation", description = "The operation that is assigned to this permission")
public Operation getOperation()
{
return operation;
}
public void setOperation( Operation operation )
{
this.operation = operation;
}
@Schema(name="resource", description = "The resource this permission applies to")
public Resource getResource()
{
return resource;
}
public void setResource( Resource resource )
{
this.resource = resource;
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append( "Permission" );
sb.append( "{name='" ).append( name ).append( '\'' );
sb.append( ", description='" ).append( description ).append( '\'' );
sb.append( ", operation=" ).append( operation );
sb.append( ", resource=" ).append( resource );
sb.append( ", permanent=" ).append( permanent );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -0,0 +1,98 @@
package org.apache.archiva.redback.rest.api.model.v2;
/*
* 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 io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
/**
* @author Olivier Lamy
* @since 1.4
*/
@XmlRootElement( name = "resource" )
@Schema(name="Resource", description = "Resource where permissions are applied to")
public class Resource
implements Serializable
{
private static final long serialVersionUID = -4597120682491493340L;
private String identifier;
private boolean pattern;
private boolean permanent;
public Resource()
{
// no op
}
public Resource( org.apache.archiva.redback.rbac.Resource resource )
{
this.identifier = resource.getIdentifier();
this.pattern = resource.isPattern();
this.permanent = resource.isPermanent();
}
@Schema(name="identifier", description = "Identifier of the resource")
public String getIdentifier()
{
return identifier;
}
public void setIdentifier( String identifier )
{
this.identifier = identifier;
}
@Schema(name="pattern", description = "True, if this resource is just a pattern")
public boolean isPattern()
{
return pattern;
}
public void setPattern( boolean pattern )
{
this.pattern = pattern;
}
@Schema(name="permanent", description = "True, if this resource is permanent")
public boolean isPermanent()
{
return permanent;
}
public void setPermanent( boolean permanent )
{
this.permanent = permanent;
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append( "Resource" );
sb.append( "{identifier='" ).append( identifier ).append( '\'' );
sb.append( ", pattern=" ).append( pattern );
sb.append( ", permanent=" ).append( permanent );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -1,5 +1,7 @@
package org.apache.archiva.redback.rest.api.model.v2;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
@ -28,6 +30,7 @@ import java.util.List;
*/
@XmlRootElement( name = "user" )
@Schema(name="User", description = "User information data")
public class User
implements Serializable
{
@ -142,8 +145,9 @@ public class User
}
@XmlElement(name="user_id")
public String getUserId()
@Schema( name = "user_id", description = "The user id" )
@XmlElement( name = "user_id" )
public String getUserId( )
{
return userId;
}
@ -153,7 +157,8 @@ public class User
this.userId = userId;
}
public String getFullName()
@Schema( description = "The full name of the user" )
public String getFullName( )
{
return fullName;
}
@ -163,7 +168,8 @@ public class User
this.fullName = fullName;
}
public String getEmail()
@Schema( description = "Email address" )
public String getEmail( )
{
return email;
}
@ -173,6 +179,7 @@ public class User
this.email = email;
}
@Schema( description = "True, if user is validated, or False, if user is still in register phase.")
public boolean isValidated()
{
return validated;
@ -183,6 +190,7 @@ public class User
this.validated = validated;
}
@Schema(description = "True, if user is locked.")
public boolean isLocked()
{
return locked;
@ -193,6 +201,7 @@ public class User
this.locked = isLocked;
}
public String getPassword()
{
return password;

View File

@ -0,0 +1,363 @@
package org.apache.archiva.redback.rest.api.model.v2;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.List;
/*
* 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.
*/
@XmlRootElement( name = "user" )
@Schema(name="User", description = "User information data")
public class UserInfo
implements Serializable
{
private static final long serialVersionUID = 822423853981984867L;
private String id;
private String userId;
private String fullName;
private String email;
private boolean validated;
private boolean locked;
private boolean passwordChangeRequired;
private boolean permanent;
// Display Only Fields.
private OffsetDateTime timestampAccountCreation;
private OffsetDateTime timestampLastLogin;
private OffsetDateTime timestampLastPasswordChange;
/**
* for roles update only <b>not return on user read</b>
*
* @since 2.0
*/
private List<String> assignedRoles;
/**
* with some userManagerImpl it's not possible to edit users;
* @since 2.1
*/
private boolean readOnly;
/**
* as we can user multiple userManagers implementation we must track from which one this one comes.
* @since 2.1
*/
private String userManagerId;
/**
* for request validation
*
* @since 2.2
*/
private String validationToken;
public UserInfo()
{
// no op
}
public UserInfo( String userId, String fullName, String email, boolean validated, boolean locked )
{
this.userId = userId;
this.fullName = fullName;
this.email = email;
this.validated = validated;
this.locked = locked;
}
public UserInfo( org.apache.archiva.redback.users.User user )
{
setUserId( user.getUsername() );
this.setEmail( user.getEmail() );
this.setFullName( user.getFullName() );
this.setLocked( user.isLocked() );
this.setValidated( user.isValidated() );
this.setPasswordChangeRequired( user.isPasswordChangeRequired() );
this.setPermanent( user.isPermanent() );
this.setUserManagerId( user.getUserManagerId() );
this.setId( user.getId() );
if (user.getAccountCreationDate()==null) {
setTimestampAccountCreationByInstant( Instant.EPOCH );
} else {
setTimestampAccountCreationByInstant( user.getAccountCreationDate().toInstant() );
}
if (user.getLastLoginDate()==null) {
setTimestampLastLoginByInstant( Instant.EPOCH );
} else
{
setTimestampLastLoginByInstant( user.getLastLoginDate( ).toInstant( ) );
}
if (user.getLastPasswordChange()==null) {
setTimestampLastLoginByInstant( Instant.EPOCH );
} else
{
setTimestampLastPasswordChangeByInstant( user.getLastPasswordChange( ).toInstant( ) );
}
}
@Schema( name = "user_id", description = "The user id" )
@XmlElement( name = "user_id" )
public String getUserId( )
{
return userId;
}
public void setUserId( String userId )
{
this.userId = userId;
}
@Schema( description = "The full name of the user" )
public String getFullName( )
{
return fullName;
}
public void setFullName( String fullName )
{
this.fullName = fullName;
}
@Schema( description = "Email address" )
public String getEmail( )
{
return email;
}
public void setEmail( String email )
{
this.email = email;
}
@Schema( description = "True, if user is validated, or False, if user is still in register phase.")
public boolean isValidated()
{
return validated;
}
public void setValidated( boolean validated )
{
this.validated = validated;
}
@Schema(description = "True, if user is locked.")
public boolean isLocked()
{
return locked;
}
public void setLocked( boolean isLocked )
{
this.locked = isLocked;
}
@Schema( description = "True, if user has to change his password" )
public boolean isPasswordChangeRequired( )
{
return passwordChangeRequired;
}
public void setPasswordChangeRequired( boolean passwordChangeRequired )
{
this.passwordChangeRequired = passwordChangeRequired;
}
@Schema(description = "True, if this is not a temporary user.")
public boolean isPermanent()
{
return permanent;
}
public void setPermanent( boolean permanent )
{
this.permanent = permanent;
}
@Schema(description = "The date and time, when the account was first created.")
public OffsetDateTime getTimestampAccountCreation()
{
return timestampAccountCreation;
}
public void setTimestampAccountCreation( OffsetDateTime timestampAccountCreation )
{
this.timestampAccountCreation = timestampAccountCreation;
}
public void setTimestampAccountCreationByInstant( Instant timestampAccountCreation )
{
this.timestampAccountCreation = OffsetDateTime.ofInstant( timestampAccountCreation, ZoneId.systemDefault() );
}
@Schema(description = "Date and time of the last successful login")
public OffsetDateTime getTimestampLastLogin()
{
return timestampLastLogin;
}
public void setTimestampLastLogin( OffsetDateTime timestampLastLogin )
{
this.timestampLastLogin = timestampLastLogin;
}
public void setTimestampLastLoginByInstant( Instant timestampLastLogin )
{
this.timestampLastLogin = OffsetDateTime.ofInstant( timestampLastLogin, ZoneId.systemDefault( ) );
}
@Schema(description = "Date and time of the last password change")
public OffsetDateTime getTimestampLastPasswordChange()
{
return timestampLastPasswordChange;
}
public void setTimestampLastPasswordChange( OffsetDateTime timestampLastPasswordChange )
{
this.timestampLastPasswordChange = timestampLastPasswordChange;
}
public void setTimestampLastPasswordChangeByInstant( Instant timestampLastPasswordChange )
{
this.timestampLastPasswordChange = OffsetDateTime.ofInstant( timestampLastPasswordChange, ZoneId.systemDefault() );
}
@Schema(description = "The roles assigned to the user")
public List<String> getAssignedRoles()
{
return assignedRoles;
}
public void setAssignedRoles( List<String> assignedRoles )
{
this.assignedRoles = assignedRoles;
}
@Schema(description = "True, if this is user has readonly access")
public boolean isReadOnly()
{
return readOnly;
}
public void setReadOnly( boolean readOnly )
{
this.readOnly = readOnly;
}
@Schema( description = "Id of the usermanager, where this user is registered")
public String getUserManagerId()
{
return userManagerId;
}
public void setUserManagerId( String userManagerId )
{
this.userManagerId = userManagerId;
}
@Schema( description = "Current validation token of this user")
public String getValidationToken() {
return validationToken;
}
public void setValidationToken(String validationToken) {
this.validationToken = validationToken;
}
@Schema( description = "User id that is unique over all user managers")
public String getId( )
{
return id;
}
public void setId( String id )
{
this.id = id;
}
@Override
public String toString()
{
return "User{" +
"username='" + userId + '\'' +
", fullName='" + fullName + '\'' +
", email='" + email + '\'' +
", validated=" + validated +
", locked=" + locked +
//", password='" + password + '\'' +
", passwordChangeRequired=" + passwordChangeRequired +
", permanent=" + permanent +
", timestampAccountCreation='" + timestampAccountCreation + '\'' +
", timestampLastLogin='" + timestampLastLogin + '\'' +
", timestampLastPasswordChange='" + timestampLastPasswordChange + '\'' +
", assignedRoles=" + assignedRoles +
", readOnly=" + readOnly +
", userManagerId='" + userManagerId + '\'' +
", validationToken='" + validationToken + '\'' +
'}';
}
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( !( o instanceof UserInfo ) )
{
return false;
}
UserInfo user = (UserInfo) o;
if ( !userId.equals( user.userId ) )
{
return false;
}
return true;
}
@Override
public int hashCode()
{
return userId.hashCode();
}
}

View File

@ -0,0 +1,64 @@
package org.apache.archiva.redback.rest.api.model.v2;
/*
* 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 io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@XmlRootElement(name="verificationStatus")
@Schema(name="VerificationStatus", description = "The verification status of the user registration")
public class VerificationStatus
{
boolean success = false;
String accessToken;
public VerificationStatus() {
}
public VerificationStatus( boolean success ) {
this.success = success;
}
@Schema(name="success",description = "True, if verification was successful")
public boolean isSuccess( )
{
return success;
}
public void setSuccess( boolean success )
{
this.success = success;
}
@Schema(name="accessToken", description = "The access token that is used for registration")
public String getAccessToken( )
{
return accessToken;
}
public void setAccessToken( String accessToken )
{
this.accessToken = accessToken;
}
}

View File

@ -20,15 +20,19 @@ package org.apache.archiva.redback.rest.api.services.v2;
*/
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.rest.api.model.RedbackRestError;
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.v2.TokenRefreshRequest;
import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
import org.apache.archiva.redback.rest.api.model.v2.TokenResponse;
import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import javax.ws.rs.Consumes;
@ -38,6 +42,8 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
/**
* Version 2 of authentication service
*
@ -59,6 +65,13 @@ public interface AuthenticationService
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true )
@Operation( summary = "Ping request.",
responses = {
@ApiResponse( responseCode = "200",
description = "Pong",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PingResult.class))
)
})
PingResult ping()
throws RedbackServiceException;
@ -72,7 +85,15 @@ public interface AuthenticationService
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = false, noPermission = true )
@Operation( summary = "Ping request to restricted service. You have to provide a valid authentication token." )
@Operation( summary = "Ping request to restricted service. You have to provide a valid authentication token.",
responses = {
@ApiResponse( responseCode = "200",
description = "Pong",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PingResult.class))
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to ping",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
})
@SecurityRequirement( name="BearerAuth" )
PingResult pingWithAutz()
throws RedbackServiceException;
@ -89,7 +110,14 @@ public interface AuthenticationService
@Operation( summary = "Authenticate by user/password login and return a bearer token, usable for further requests",
responses = {
@ApiResponse( description = "A access token, that has to be added to the Authorization header on authenticated requests. " +
"And refresh token, used to refresh the access token. Each token as a lifetime. After expiration it cannot be used anymore." )
"And refresh token, used to refresh the access token. Each token as a lifetime. After expiration it cannot be used anymore.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = TokenResponse.class))
),
@ApiResponse( responseCode = "401", description = "Authentication failed. The response body tells more about the failure.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
TokenResponse logIn( TokenRequest loginRequest )
@ -106,7 +134,8 @@ public interface AuthenticationService
"supported. You have to provide the refresh token in the payload. And you have to provide a valid Bearer access token in "+
"the Authorization header.",
responses = {
@ApiResponse( description = "The new access token," )
@ApiResponse( description = "The new access token",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = TokenResponse.class)))
}
)
@SecurityRequirement( name="BearerAuth" )
@ -122,8 +151,13 @@ public interface AuthenticationService
@Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true )
@Operation(summary = "Checks the request for a valid access token, and returns the user object that corresponds to the " +
"provided token.")
User getAuthenticatedUser()
"provided token.",
responses = {
@ApiResponse( description = "The new access token",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = UserInfo.class)))
}
)
UserInfo getAuthenticatedUser()
throws RedbackServiceException;
}

View File

@ -19,7 +19,10 @@ package org.apache.archiva.redback.rest.api.services.v2;
* under the License.
*/
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@ -27,17 +30,17 @@ 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.RedbackRestError;
import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.Operation;
import org.apache.archiva.redback.rest.api.model.v2.SelfUserData;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.Permission;
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.ResetPasswordRequest;
import org.apache.archiva.redback.rest.api.model.v2.RegistrationKey;
import org.apache.archiva.redback.rest.api.model.v2.SelfUserData;
import org.apache.archiva.redback.rest.api.model.v2.User;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.model.v2.UserRegistrationRequest;
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
import org.apache.archiva.redback.rest.api.model.v2.VerificationStatus;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import javax.ws.rs.Consumes;
@ -50,9 +53,9 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Collection;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.apache.archiva.redback.rest.api.Constants.DEFAULT_PAGE_LIMIT;
@Path( "/users" )
@ -63,10 +66,10 @@ public interface UserService
{
@Path( "{userId}" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION,
resource = "{userId}" )
@io.swagger.v3.oas.annotations.Operation( summary = "Returns information about a specific user",
@Operation( summary = "Returns information about a specific user",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION
@ -74,21 +77,25 @@ public interface UserService
},
responses = {
@ApiResponse( responseCode = "200",
description = "If user was found in the database"
description = "If user was found in the database",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = UserInfo.class))
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information" )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class ))
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
User getUser( @PathParam( "userId" ) String userId )
UserInfo getUser( @PathParam( "userId" ) String userId )
throws RedbackServiceException;
@Path( "" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_LIST_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Returns all users defined. The result is paged.",
@Operation( summary = "Returns all users defined. The result is paged.",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_USER_LIST_OPERATION
@ -96,21 +103,23 @@ public interface UserService
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the list could be returned"
description = "If the list could be returned",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PagedResult.class))
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information" )
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
PagedResult<User> getUsers( @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
PagedResult<UserInfo> getUsers( @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
@QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit)
throws RedbackServiceException;
@Path( "" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Consumes( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@Consumes( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_CREATE_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Creates a user",
@Operation( summary = "Creates a user",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_USER_CREATE_OPERATION
@ -121,9 +130,11 @@ public interface UserService
description = "If user creation was successful",
headers = {
@Header( name="Location", description = "The URL of the created mapping", schema = @Schema(type="string"))
}
},
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = UserInfo.class))
),
@ApiResponse( responseCode = "422", description = "Invalid input" ),
@ApiResponse( responseCode = "422", description = "Invalid input",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "303", description = "The user exists already",
headers = {
@Header( name="Location", description = "The URL of existing user", schema = @Schema(type="string"))
@ -131,14 +142,14 @@ public interface UserService
)
}
)
User createUser( User user )
UserInfo createUser( User user )
throws RedbackServiceException;
@Path( "{userId}" )
@DELETE
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_DELETE_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Deletes a given user",
@Operation( summary = "Deletes a given user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_DELETE_OPERATION )
},
@ -146,8 +157,10 @@ public interface UserService
@ApiResponse( responseCode = "200",
description = "If user deletion was successful"
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for deletion." )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for deletion.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
void deleteUser( @PathParam( "userId" ) String userId )
@ -155,22 +168,26 @@ public interface UserService
@Path( "{userId}" )
@PUT
@Produces( {MediaType.APPLICATION_JSON} )
@Produces( {APPLICATION_JSON} )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Updates an existing user",
@Operation( summary = "Updates an existing user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If update was successful"
description = "If update was successful",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = UserInfo.class))
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "422", description = "Update data was not valid. E.g. password violations." ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for update." )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "422", description = "Update data was not valid. E.g. password violations.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for update." ,
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )))
}
)
User updateUser( @PathParam( "userId" ) String userId, User user )
UserInfo updateUser( @PathParam( "userId" ) String userId, User user )
throws RedbackServiceException;
@ -180,18 +197,20 @@ public interface UserService
*/
@Path( "admin" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Consumes( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@Consumes( { APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Creates the admin user, if it does not exist",
@Operation( summary = "Creates the admin user, if it does not exist",
responses = {
@ApiResponse( responseCode = "201",
description = "If user creation was successful",
headers = {
@Header( name="Location", description = "The URL of the created mapping", schema = @Schema(type="string"))
}
},
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = UserInfo.class))
),
@ApiResponse( responseCode = "422", description = "Invalid input" ),
@ApiResponse( responseCode = "422", description = "Invalid input",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "303", description = "The user exists already",
headers = {
@Header( name="Location", description = "The URL of the existing admin user", schema = @Schema(type="string"))
@ -199,17 +218,18 @@ public interface UserService
)
}
)
User createAdminUser( User user )
UserInfo createAdminUser( User user )
throws RedbackServiceException;
@Path( "admin/status" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Returns the availability status of the admin user. ",
@Operation( summary = "Returns the availability status of the admin user. ",
responses = {
@ApiResponse( responseCode = "200",
description = "If status can be retrieved"
description = "If status can be retrieved",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = AvailabilityStatus.class))
)
}
)
@ -222,9 +242,9 @@ public interface UserService
*/
@Path( "{userId}/lock/set" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Creates a user",
@Operation( summary = "Creates a user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
},
@ -232,8 +252,10 @@ public interface UserService
@ApiResponse( responseCode = "200",
description = "If locking was successful"
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for locking." )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for locking.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
void lockUser( @PathParam( "userId" ) String userId )
@ -243,9 +265,9 @@ public interface UserService
*/
@Path( "{userId}/lock/clear" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Unlocks a user",
@Operation( summary = "Unlocks a user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
},
@ -253,8 +275,10 @@ public interface UserService
@ApiResponse( responseCode = "200",
description = "If unlocking was successful"
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for unlock." )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for unlock.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
void unlockUser( @PathParam( "userId" ) String userId )
@ -265,9 +289,9 @@ public interface UserService
*/
@Path( "{userId}/password/require/set" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Sets the requirePassword flag for a given user",
@Operation( summary = "Sets the requirePassword flag for a given user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
},
@ -275,8 +299,10 @@ public interface UserService
@ApiResponse( responseCode = "200",
description = "If password change require flag was set"
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for editing." )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for editing.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
@ -287,9 +313,9 @@ public interface UserService
*/
@Path( "{userId}/password/require/clear" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Clears the requirePassword flag for a given user",
@Operation( summary = "Clears the requirePassword flag for a given user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
},
@ -297,8 +323,10 @@ public interface UserService
@ApiResponse( responseCode = "200",
description = "If password change require flag was unset"
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for editing." )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for editing.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
@ -309,78 +337,96 @@ public interface UserService
/**
* Update only the current logged in user and this fields: fullname, email, password.
* The service verifies the current logged user with the one passed in the method
* @return
* @return the user info object
*/
@Path( "me" )
@PUT
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( noPermission = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Updates information of the current logged in user",
@Operation( summary = "Updates information of the current logged in user",
responses = {
@ApiResponse( responseCode = "200",
description = "If user data has been updated"
description = "The updated user information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = UserInfo.class))
),
@ApiResponse( responseCode = "401", description = "User is not logged in" ),
@ApiResponse( responseCode = "400", description = "Provided data is not valid" )
@ApiResponse( responseCode = "401", description = "User is not logged in",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "400", description = "Provided data is not valid",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
User updateMe( SelfUserData user )
UserInfo updateMe( SelfUserData user )
throws RedbackServiceException;
@Path( "me" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( noPermission = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Gets information of the current logged in user",
responses = {
@Operation( summary = "Gets information of the current logged in user",
responses = {
@ApiResponse( responseCode = "200",
description = "If user data is returned"
description = "The user information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = UserInfo.class))
),
@ApiResponse( responseCode = "401", description = "User is not logged in" ),
@ApiResponse( responseCode = "401", description = "User is not logged in" ,
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
}
)
User getLoggedInUser( ) throws RedbackServiceException;
UserInfo getLoggedInUser( ) throws RedbackServiceException;
@Path( "___ping___" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true )
@Operation( summary = "Checks the service availability",
responses = {
@ApiResponse( responseCode = "200",
description = "Pong",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = PingResult.class))
)}
)
PingResult ping()
throws RedbackServiceException;
@Path( "{userId}/cache/clear" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION,
resource = "{userId}")
@io.swagger.v3.oas.annotations.Operation( summary = "Clears the cache for the user",
@Operation( summary = "Clears the cache for the user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the cache was cleared properly"
description = "Status of the clear operation",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ActionStatus.class))
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the required permission." )
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the required permission.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
ActionStatus removeFromCache( @PathParam( "userId" ) String userId )
throws RedbackServiceException;
/**
* @return
* @return the registration key
*/
@Path( "{userId}/register" )
@POST
@Produces( {MediaType.APPLICATION_JSON} )
@Produces( {APPLICATION_JSON} )
@RedbackAuthorization( noRestriction = true, noPermission = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Registers a new user",
@Operation( summary = "Registers a new user",
responses = {
@ApiResponse( responseCode = "200",
description = "If the registration was successful, a registration key is returned"
description = "If the registration was successful, a registration key is returned",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RegistrationKey.class))
),
@ApiResponse( responseCode = "422", description = "If the the provided user data is not valid" ),
@ApiResponse( responseCode = "422", description = "If the the provided user data is not valid",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
}
)
RegistrationKey registerUser( @PathParam( "userId" ) String userId, UserRegistrationRequest userRegistrationRequest )
@ -392,15 +438,18 @@ public interface UserService
*/
@Path( "{userId}/password/reset" )
@POST
@Produces( { MediaType.APPLICATION_JSON } )
@Consumes( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@Consumes( { APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true, noPermission = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Asks for a password reset of the given user. This generates a reset email sent to the stored address of the given user.",
@Operation( summary = "Asks for a password reset of the given user. This generates a reset email sent to the stored address of the given user.",
responses = {
@ApiResponse( responseCode = "200",
description = "If the password reset email was sent"
description = "The result status of the password reset.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ActionStatus.class))
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
}
)
ActionStatus resetPassword( @PathParam( "userId" )String userId )
@ -410,19 +459,23 @@ public interface UserService
*/
@Path( "{userId}/permissions" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_VIEW_OPERATION,
resource = "{userId}")
@io.swagger.v3.oas.annotations.Operation( summary = "Returns a list of permissions assigned to the given user.",
@Operation( summary = "Returns a list of permissions assigned to the given user.",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_VIEW_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the list could be returned"
description = "If the list could be returned",
content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(schema =
@Schema(implementation = Permission.class)))
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "Logged in user does not have the permission to get this information." ),
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "Logged in user does not have the permission to get this information." ,
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class ))),
}
)
Collection<Permission> getUserPermissions( @PathParam( "userId" ) String userName )
@ -433,22 +486,26 @@ public interface UserService
*/
@Path( "{userId}/operations" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_VIEW_OPERATION,
resource = "{userId}")
@io.swagger.v3.oas.annotations.Operation( summary = "Returns a list of privileged operations assigned to the given user.",
@Operation( summary = "Returns a list of privileged operations assigned to the given user.",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_USER_VIEW_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the list could be returned"
description = "If the list could be returned",
content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(schema =
@Schema(implementation = org.apache.archiva.redback.rest.api.model.v2.Operation.class )))
),
@ApiResponse( responseCode = "404", description = "User does not exist" ),
@ApiResponse( responseCode = "403", description = "Logged in user does not have the permission to get this information." ),
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "Logged in user does not have the permission to get this information.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
}
)
Collection<Operation> getUserOperations( @PathParam( "userId" ) String userName )
Collection<org.apache.archiva.redback.rest.api.model.v2.Operation> getUserOperations( @PathParam( "userId" ) String userName )
throws RedbackServiceException;
/**
@ -457,12 +514,14 @@ public interface UserService
*/
@Path( "me/permissions" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true, noPermission = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Returns a list of permissions assigned to the logged in user.",
@Operation( summary = "Returns a list of permissions assigned to the logged in user.",
responses = {
@ApiResponse( responseCode = "200",
description = "If the list could be returned"
description = "If the list could be returned",
content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(schema =
@Schema(implementation = Permission.class )))
)
}
)
@ -475,29 +534,33 @@ public interface UserService
*/
@Path( "me/operations" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true, noPermission = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Returns a list of privileged operations assigned to the logged in user.",
@Operation( summary = "Returns a list of privileged operations assigned to the logged in user.",
responses = {
@ApiResponse( responseCode = "200",
description = "If the list could be returned"
description = "The list of operations assigne to the current user",
content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(schema =
@Schema(implementation = org.apache.archiva.redback.rest.api.model.v2.Operation.class )))
)
}
)
Collection<Operation> getCurrentUserOperations( )
Collection<org.apache.archiva.redback.rest.api.model.v2.Operation> getCurrentUserOperations( )
throws RedbackServiceException;
@Path( "{userId}/register/{key}/validate" )
@POST
@Produces( {MediaType.APPLICATION_JSON} )
@Produces( {APPLICATION_JSON} )
@RedbackAuthorization( noRestriction = true, noPermission = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Validate the user registration for the given userid by checking the provided key.",
@Operation( summary = "Validate the user registration for the given userid by checking the provided key.",
responses = {
@ApiResponse( responseCode = "200",
description = "If the verification was successful"
description = "The status of the user registration",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = VerificationStatus.class))
),
@ApiResponse( responseCode = "404", description = "No user registration was found for the given id and key" )
@ApiResponse( responseCode = "404", description = "No user registration was found for the given id and key",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )))
}
)
VerificationStatus validateUserRegistration( @PathParam( "userId" ) String userId, @PathParam( "key" ) String key )

View File

@ -32,12 +32,11 @@ import org.apache.archiva.redback.policy.MustChangePasswordException;
import org.apache.archiva.redback.rest.api.MessageKeys;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.GrantType;
import org.apache.archiva.redback.rest.api.model.v2.TokenResponse;
import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.model.UserLogin;
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.v2.TokenRefreshRequest;
import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
import org.apache.archiva.redback.rest.api.model.v2.TokenResponse;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.v2.AuthenticationService;
import org.apache.archiva.redback.rest.services.interceptors.RedbackPrincipal;
@ -225,7 +224,7 @@ public class DefaultAuthenticationService
}
@Override
public User getAuthenticatedUser()
public UserInfo getAuthenticatedUser()
throws RedbackServiceException
{
RedbackPrincipal pri = getPrincipal( );
@ -237,11 +236,11 @@ public class DefaultAuthenticationService
}
}
private UserLogin buildRestUser( org.apache.archiva.redback.users.User user )
private UserInfo buildRestUser( org.apache.archiva.redback.users.User user )
{
UserLogin restUser = new UserLogin();
UserInfo restUser = new UserInfo();
restUser.setEmail( user.getEmail() );
restUser.setUsername( user.getUsername() );
restUser.setUserId( user.getUsername() );
restUser.setPasswordChangeRequired( user.isPasswordChangeRequired() );
restUser.setLocked( user.isLocked() );
restUser.setValidated( user.isValidated() );

View File

@ -46,15 +46,16 @@ import org.apache.archiva.redback.rest.api.MessageKeys;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.v2.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.Permission;
import org.apache.archiva.redback.rest.api.model.v2.Operation;
import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.SelfUserData;
import org.apache.archiva.redback.rest.api.model.v2.RegistrationKey;
import org.apache.archiva.redback.rest.api.model.Resource;
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
import org.apache.archiva.redback.rest.api.model.v2.Resource;
import org.apache.archiva.redback.rest.api.model.v2.VerificationStatus;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.v2.User;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.model.v2.UserRegistrationRequest;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.v2.UserService;
@ -182,10 +183,10 @@ public class DefaultUserService
}
@Override
public User createUser( User user )
public UserInfo createUser( User user )
throws RedbackServiceException
{
User result;
UserInfo result;
if ( Arrays.binarySearch( INVALID_CREATE_USER_NAMES, user.getUserId( ) ) >=0 )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_USER_ID_INVALID, user.getUserId() ), 422 );
@ -311,7 +312,7 @@ public class DefaultUserService
@Override
public User getUser( String userId )
public UserInfo getUser( String userId )
throws RedbackServiceException
{
try
@ -333,7 +334,7 @@ public class DefaultUserService
}
@Override
public PagedResult<User> getUsers(Integer offset,
public PagedResult<UserInfo> getUsers(Integer offset,
Integer limit)
throws RedbackServiceException
{
@ -345,7 +346,7 @@ public class DefaultUserService
}
int endIndex = PagingHelper.getLastIndex( offset, limit, users.size( ) );
List<? extends org.apache.archiva.redback.users.User> resultList = users.subList( offset, endIndex );
List<User> simpleUsers = new ArrayList<>( resultList.size() );
List<UserInfo> simpleUsers = new ArrayList<>( resultList.size() );
for ( org.apache.archiva.redback.users.User user : resultList )
{
@ -360,7 +361,7 @@ public class DefaultUserService
}
@Override
public User updateMe( SelfUserData user )
public UserInfo updateMe( SelfUserData user )
throws RedbackServiceException
{
RedbackPrincipal principal = getPrincipal( );
@ -422,7 +423,7 @@ public class DefaultUserService
}
@Override
public User getLoggedInUser( )
public UserInfo getLoggedInUser( )
throws RedbackServiceException
{
RedbackPrincipal principal = getPrincipal( );
@ -442,7 +443,7 @@ public class DefaultUserService
}
@Override
public User updateUser( String userId, User user )
public UserInfo updateUser( String userId, User user )
throws RedbackServiceException
{
try
@ -513,20 +514,20 @@ public class DefaultUserService
return new PingResult( true );
}
private User getRestUser( org.apache.archiva.redback.users.User user )
private UserInfo getRestUser( org.apache.archiva.redback.users.User user )
{
if ( user == null )
{
return null;
}
return new User( user );
return new UserInfo( user );
}
@Override
public User createAdminUser( User adminUser )
public UserInfo createAdminUser( User adminUser )
throws RedbackServiceException
{
User result;
UserInfo result;
if ( getAdminStatus().isExists() )
{
log.warn( "Admin user exists already" );

View File

@ -178,7 +178,7 @@ public class NativeAuthenticationServiceTest extends AbstractNativeRestServices
.when( ).get( "/authenticated" ).then( ).statusCode( 200 )
.extract( ).response( );
System.out.println( result.getBody( ).prettyPrint( ) );
assertEquals( "admin", result.getBody( ).jsonPath( ).getString( "username" ) );
assertEquals( "admin", result.getBody( ).jsonPath( ).getString( "user_id" ) );
}

View File

@ -20,14 +20,15 @@ package org.apache.archiva.redback.rest.services.v2;
*/
import org.apache.archiva.redback.rest.api.model.GrantType;
import org.apache.archiva.redback.rest.api.model.Operation;
import org.apache.archiva.redback.rest.api.model.v2.Operation;
import org.apache.archiva.redback.rest.api.model.v2.SelfUserData;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.Permission;
import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
import org.apache.archiva.redback.rest.api.model.v2.TokenResponse;
import org.apache.archiva.redback.rest.api.model.v2.User;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.model.v2.UserRegistrationRequest;
import org.apache.archiva.redback.rest.api.services.v2.UserService;
import org.apache.archiva.redback.rest.services.FakeCreateAdminService;
@ -122,7 +123,7 @@ public class UserServiceTest
{
String adminHeader = getAdminAuthzHeader( );
UserService userService = getUserService( adminHeader );
PagedResult<org.apache.archiva.redback.rest.api.model.v2.User> users = userService.getUsers( 0, Integer.MAX_VALUE );
PagedResult<org.apache.archiva.redback.rest.api.model.v2.UserInfo> users = userService.getUsers( 0, Integer.MAX_VALUE );
assertNotNull( users );
assertFalse( users.getData().isEmpty( ) );
}
@ -225,11 +226,11 @@ public class UserServiceTest
service = getUserService( getAdminAuthzHeader( ) );
u = service.getUser( "toto" );
UserInfo uInfo = service.getUser( "toto" );
assertNotNull( u );
assertFalse( u.isValidated( ) );
assertTrue( u.isPasswordChangeRequired( ) );
assertNotNull( uInfo );
assertFalse( uInfo.isValidated( ) );
assertTrue( uInfo.isPasswordChangeRequired( ) );
// assertTrue( service.validateUserFromKey( key ).isSuccess( ) );
@ -287,11 +288,11 @@ public class UserServiceTest
service = getUserService( getAdminAuthzHeader( ) );
u = service.getUser( "toto" );
UserInfo uInfo = service.getUser( "toto" );
assertNotNull( u );
assertTrue( u.isValidated( ) );
assertTrue( u.isPasswordChangeRequired( ) );
assertNotNull( uInfo );
assertTrue( uInfo.isValidated( ) );
assertTrue( uInfo.isPasswordChangeRequired( ) );
// assertTrue( service.validateUserFromKey( key ).isSuccess( ) );
@ -349,11 +350,11 @@ public class UserServiceTest
service = getUserService( getAdminAuthzHeader( ) );
u = service.getUser( "toto" );
UserInfo uInfo = service.getUser( "toto" );
assertNotNull( u );
assertFalse( u.isValidated( ) );
assertTrue( u.isPasswordChangeRequired( ) );
assertNotNull( uInfo );
assertFalse( uInfo.isValidated( ) );
assertTrue( uInfo.isPasswordChangeRequired( ) );
// assertTrue( service.validateUserFromKey( key ).isSuccess( ) );
@ -410,11 +411,11 @@ public class UserServiceTest
service = getUserService( getAdminAuthzHeader( ) );
u = service.getUser( "toto" );
UserInfo uInfo = service.getUser( "toto" );
assertNotNull( u );
assertFalse( u.isValidated( ) );
assertTrue( u.isPasswordChangeRequired( ) );
assertNotNull( uInfo );
assertFalse( uInfo.isValidated( ) );
assertTrue( uInfo.isPasswordChangeRequired( ) );
// assertTrue( service.validateUserFromKey( key ).isSuccess( ) );
@ -511,9 +512,9 @@ public class UserServiceTest
selfUserData.setCurrentPassword( "toto123" );
getUserService( getUserAuthzHeader( "toto" ) ).updateMe( selfUserData );
u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" );
assertEquals( "the toto123", u.getFullName( ) );
assertEquals( "toto@titi.fr", u.getEmail( ) );
UserInfo uInfo = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" );
assertEquals( "the toto123", uInfo.getFullName( ) );
assertEquals( "toto@titi.fr", uInfo.getEmail( ) );
selfUserData.setFullName( "the toto1234" );
selfUserData.setEmail( "toto@tititi.fr" );
@ -521,9 +522,9 @@ public class UserServiceTest
selfUserData.setCurrentPassword( "toto1234" );
getUserService( getUserAuthzHeader( "toto" )) .updateMe( selfUserData );
u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" );
assertEquals( "the toto1234", u.getFullName( ) );
assertEquals( "toto@tititi.fr", u.getEmail( ) );
uInfo = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" );
assertEquals( "the toto1234", uInfo.getFullName( ) );
assertEquals( "toto@tititi.fr", uInfo.getEmail( ) );
getUserService( getAdminAuthzHeader( ) ).deleteUser( "toto" );
}
@ -545,10 +546,10 @@ public class UserServiceTest
UserService userService = getUserService( getAdminAuthzHeader( ) );
userService.createUser( user );
// END SNIPPET: create-user
user = userService.getUser( "toto" );
assertNotNull( user );
assertEquals( "toto the king", user.getFullName( ) );
assertEquals( "toto@toto.fr", user.getEmail( ) );
UserInfo userInfo = userService.getUser( "toto" );
assertNotNull( userInfo );
assertEquals( "toto the king", userInfo.getFullName( ) );
assertEquals( "toto@toto.fr", userInfo.getEmail( ) );
TokenResponse result = getLoginServiceV2( null ).logIn( new TokenRequest( "toto", "foo123", GrantType.AUTHORIZATION_CODE ) );
getLoginServiceV2( "Bearer " + result.getAccessToken( ) ).pingWithAutz( );