Interface changes for V2 REST

This commit is contained in:
Martin Stockhammer 2020-07-26 18:02:39 +02:00
parent c066d2382f
commit 3b78d274cf
21 changed files with 817 additions and 116 deletions

View File

@ -0,0 +1,27 @@
package org.apache.archiva.redback.rest.api;
/*
* 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 Constants
{
public static final String DEFAULT_PAGE_LIMIT = "1000";
}

View File

@ -1,4 +1,4 @@
package org.apache.archiva.redback.rest.api.model; package org.apache.archiva.redback.rest.api.model.v2;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -19,6 +19,7 @@ package org.apache.archiva.redback.rest.api.model;
*/ */
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.archiva.redback.rest.api.model.PaginationInfo;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import java.util.List; import java.util.List;
@ -32,28 +33,28 @@ import java.util.List;
public class PagedResult<T> public class PagedResult<T>
{ {
PaginationInfo pagination; PaginationInfo pagination;
T data; List<T> data;
public PagedResult() { public PagedResult() {
} }
public PagedResult( long totalCount, long offset, long limit, T data ) { public PagedResult( int totalCount, int offset, int limit, List<T> data ) {
this.data = data; this.data = data;
this.pagination = new PaginationInfo( totalCount, offset, limit ); this.pagination = new PaginationInfo( totalCount, offset, limit );
} }
public static final <T> PagedResult<T> of(long totalSize, long offset, long limit, T element) { public static final <T> PagedResult<T> of(int totalSize, int offset, int limit, List<T> element) {
return new PagedResult( totalSize, offset, limit, element); return new PagedResult( totalSize, offset, limit, element);
} }
@Schema(description = "This is the payload of the paged data. The type of data depends on the REST method. ") @Schema(description = "This is the payload of the paged data. The type of data depends on the REST method. ")
public T getData( ) public List<T> getData( )
{ {
return data; return data;
} }
public void setData( T data ) public void setData( List<T> data )
{ {
this.data = data; this.data = data;
} }

View File

@ -1,4 +1,4 @@
package org.apache.archiva.redback.rest.api.model; package org.apache.archiva.redback.rest.api.model.v2;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,4 +1,4 @@
package org.apache.archiva.redback.rest.api.model; package org.apache.archiva.redback.rest.api.model.v2;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,4 +1,4 @@
package org.apache.archiva.redback.rest.api.model; package org.apache.archiva.redback.rest.api.model.v2;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -19,6 +19,7 @@ package org.apache.archiva.redback.rest.api.model;
*/ */
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.archiva.redback.rest.api.model.GrantType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
@ -29,7 +30,7 @@ import java.io.Serializable;
*/ */
@XmlRootElement(name="refreshToken") @XmlRootElement(name="refreshToken")
@Schema(name="Request Token Data", description = "Schema used for requesting a Bearer token.") @Schema(name="Request Token Data", description = "Schema used for requesting a Bearer token.")
public class RequestTokenRequest implements Serializable public class TokenRequest implements Serializable
{ {
private static final long serialVersionUID = -4803869713444270526L; private static final long serialVersionUID = -4803869713444270526L;
GrantType grantType = null; GrantType grantType = null;
@ -42,24 +43,24 @@ public class RequestTokenRequest implements Serializable
String password; String password;
String redirectUri; String redirectUri;
public RequestTokenRequest() { public TokenRequest() {
} }
public RequestTokenRequest( String userId, String password ) public TokenRequest( String userId, String password )
{ {
this.userId = userId; this.userId = userId;
this.password = password; this.password = password;
} }
public RequestTokenRequest( String userId, String password, String scope ) public TokenRequest( String userId, String password, String scope )
{ {
this.userId = userId; this.userId = userId;
this.password = password; this.password = password;
this.scope = scope; this.scope = scope;
} }
public RequestTokenRequest( String userId, String password, GrantType grantType ) public TokenRequest( String userId, String password, GrantType grantType )
{ {
this.userId = userId; this.userId = userId;
this.password = password; this.password = password;

View File

@ -0,0 +1,377 @@
package org.apache.archiva.redback.rest.api.model.v2;
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" )
public class User
implements Serializable
{
private static final long serialVersionUID = 7457798933140993643L;
private String userId;
private String fullName;
private String email;
private boolean validated;
private boolean locked;
private String password;
private boolean passwordChangeRequired;
private boolean permanent;
private String confirmPassword;
// Display Only Fields.
private OffsetDateTime timestampAccountCreation;
private OffsetDateTime timestampLastLogin;
private OffsetDateTime timestampLastPasswordChange;
/**
* for password change only
*
* @since 1.4
*/
private String previousPassword;
/**
* 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 User()
{
// no op
}
public User( 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 User( org.apache.archiva.redback.users.User user )
{
setUserId( user.getUsername() );
this.setEmail( user.getEmail() );
this.setFullName( user.getFullName() );
this.setLocked( user.isLocked() );
this.setPassword( user.getPassword() );
this.setValidated( user.isValidated() );
this.setPasswordChangeRequired( user.isPasswordChangeRequired() );
this.setPermanent( user.isPermanent() );
this.setUserManagerId( user.getUserManagerId() );
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( ) );
}
}
@XmlElement(name="user_id")
public String getUserId()
{
return userId;
}
public void setUserId( String userId )
{
this.userId = userId;
}
public String getFullName()
{
return fullName;
}
public void setFullName( String fullName )
{
this.fullName = fullName;
}
public String getEmail()
{
return email;
}
public void setEmail( String email )
{
this.email = email;
}
public boolean isValidated()
{
return validated;
}
public void setValidated( boolean validated )
{
this.validated = validated;
}
public boolean isLocked()
{
return locked;
}
public void setLocked( boolean isLocked )
{
this.locked = isLocked;
}
public String getPassword()
{
return password;
}
public void setPassword( String password )
{
this.password = password;
}
public boolean isPasswordChangeRequired()
{
return passwordChangeRequired;
}
public void setPasswordChangeRequired( boolean passwordChangeRequired )
{
this.passwordChangeRequired = passwordChangeRequired;
}
public boolean isPermanent()
{
return permanent;
}
public void setPermanent( boolean permanent )
{
this.permanent = permanent;
}
public String getConfirmPassword()
{
return confirmPassword;
}
public void setConfirmPassword( String confirmPassword )
{
this.confirmPassword = confirmPassword;
}
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() );
}
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( ) );
}
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() );
}
public String getPreviousPassword()
{
return previousPassword;
}
public void setPreviousPassword( String previousPassword )
{
this.previousPassword = previousPassword;
}
public List<String> getAssignedRoles()
{
return assignedRoles;
}
public void setAssignedRoles( List<String> assignedRoles )
{
this.assignedRoles = assignedRoles;
}
public boolean isReadOnly()
{
return readOnly;
}
public void setReadOnly( boolean readOnly )
{
this.readOnly = readOnly;
}
public String getUserManagerId()
{
return userManagerId;
}
public void setUserManagerId( String userManagerId )
{
this.userManagerId = userManagerId;
}
public String getValidationToken() {
return validationToken;
}
public void setValidationToken(String validationToken) {
this.validationToken = validationToken;
}
@Override
public String toString()
{
return "User{" +
"username='" + userId + '\'' +
", fullName='" + fullName + '\'' +
", email='" + email + '\'' +
", validated=" + validated +
", locked=" + locked +
//", password='" + password + '\'' +
", passwordChangeRequired=" + passwordChangeRequired +
", permanent=" + permanent +
", confirmPassword='" + confirmPassword + '\'' +
", timestampAccountCreation='" + timestampAccountCreation + '\'' +
", timestampLastLogin='" + timestampLastLogin + '\'' +
", timestampLastPasswordChange='" + timestampLastPasswordChange + '\'' +
", previousPassword='" + previousPassword + '\'' +
", assignedRoles=" + assignedRoles +
", readOnly=" + readOnly +
", userManagerId='" + userManagerId + '\'' +
", validationToken='" + validationToken + '\'' +
'}';
}
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( !( o instanceof User ) )
{
return false;
}
User user = (User) o;
if ( !userId.equals( user.userId ) )
{
return false;
}
return true;
}
@Override
public int hashCode()
{
return userId.hashCode();
}
}

View File

@ -0,0 +1,78 @@
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 javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
/**
* @author Olivier Lamy
* @since 2.0
*/
@XmlRootElement( name = "userRegistrationRequest" )
public class UserRegistrationRequest
implements Serializable
{
private static final long serialVersionUID = 5516902373853039946L;
private User user;
private String applicationUrl;
public UserRegistrationRequest()
{
// no op
}
public UserRegistrationRequest( User user, String applicationUrl )
{
this.user = user;
this.applicationUrl = applicationUrl;
}
public User getUser()
{
return user;
}
public void setUser( User user )
{
this.user = user;
}
public String getApplicationUrl()
{
return applicationUrl;
}
public void setApplicationUrl( String applicationUrl )
{
this.applicationUrl = applicationUrl;
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append( "UserRegistrationRequest" );
sb.append( "{user=" ).append( user );
sb.append( ", applicationUrl='" ).append( applicationUrl ).append( '\'' );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -24,11 +24,8 @@ import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme; import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.redback.authorization.RedbackAuthorization; 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.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.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.model.User;
import javax.ws.rs.GET; import javax.ws.rs.GET;

View File

@ -20,16 +20,12 @@ package org.apache.archiva.redback.rest.api.services.v2;
*/ */
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.redback.authorization.RedbackAuthorization; import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.rest.api.model.PingResult; import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.TokenRequest; import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
import org.apache.archiva.redback.rest.api.model.RequestTokenRequest;
import org.apache.archiva.redback.rest.api.model.TokenResponse; import org.apache.archiva.redback.rest.api.model.TokenResponse;
import org.apache.archiva.redback.rest.api.model.User; import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
@ -93,7 +89,7 @@ public interface AuthenticationService
"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." )
} }
) )
TokenResponse logIn( RequestTokenRequest loginRequest ) TokenResponse logIn( TokenRequest loginRequest )
throws RedbackServiceException; throws RedbackServiceException;
/** /**
@ -111,7 +107,7 @@ public interface AuthenticationService
} }
) )
@SecurityRequirement( name="BearerAuth" ) @SecurityRequirement( name="BearerAuth" )
TokenResponse token( TokenRequest tokenRequest ) TokenResponse token( org.apache.archiva.redback.rest.api.model.TokenRequest tokenRequest )
throws RedbackServiceException; throws RedbackServiceException;

View File

@ -26,9 +26,10 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.redback.authorization.RedbackAuthorization; import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants; import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.rest.api.Constants;
import org.apache.archiva.redback.rest.api.model.ActionStatus; import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.Group; import org.apache.archiva.redback.rest.api.model.Group;
import org.apache.archiva.redback.rest.api.model.PagedResult; import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.v2.GroupMapping; import org.apache.archiva.redback.rest.api.model.v2.GroupMapping;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
@ -58,8 +59,6 @@ import java.util.List;
public interface GroupService public interface GroupService
{ {
String DEFAULT_PAGE_LIMIT = "1000";
@Path( "" ) @Path( "" )
@GET @GET
@Produces( {MediaType.APPLICATION_JSON} ) @Produces( {MediaType.APPLICATION_JSON} )
@ -69,8 +68,8 @@ public interface GroupService
@ApiResponse( description = "List of group objects. The number of returned results depend on the pagination parameters offset and limit." ) @ApiResponse( description = "List of group objects. The number of returned results depend on the pagination parameters offset and limit." )
} }
) )
PagedResult<List<Group>> getGroups( @QueryParam( "offset" ) @DefaultValue( "0" ) Long offset, PagedResult<Group> getGroups( @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
@QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Long limit) @QueryParam( "limit" ) @DefaultValue( value = Constants.DEFAULT_PAGE_LIMIT ) Integer limit)
throws RedbackServiceException; throws RedbackServiceException;

View File

@ -19,6 +19,8 @@ package org.apache.archiva.redback.rest.api.services.v2;
* under the License. * under the License.
*/ */
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.redback.authorization.RedbackAuthorization; import org.apache.archiva.redback.authorization.RedbackAuthorization;
@ -26,27 +28,31 @@ 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.ActionStatus;
import org.apache.archiva.redback.rest.api.model.AvailabilityStatus; 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.Operation;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.PasswordStatus; 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.Permission;
import org.apache.archiva.redback.rest.api.model.PingResult; import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.RegistrationKey; 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.ResetPasswordRequest;
import org.apache.archiva.redback.rest.api.model.User; import org.apache.archiva.redback.rest.api.model.v2.User;
import org.apache.archiva.redback.rest.api.model.UserRegistrationRequest; 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.VerificationStatus;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import static org.apache.archiva.redback.rest.api.Constants.DEFAULT_PAGE_LIMIT;
@Path( "/users" ) @Path( "/users" )
@Tag(name = "v2") @Tag(name = "v2")
@ -66,7 +72,8 @@ public interface UserService
@GET @GET
@Produces( { MediaType.APPLICATION_JSON } ) @Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_LIST_OPERATION ) @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_LIST_OPERATION )
List<User> getUsers() PagedResult<User> getUsers( @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
@QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit)
throws RedbackServiceException; throws RedbackServiceException;
@Path( "" ) @Path( "" )
@ -74,6 +81,22 @@ public interface UserService
@Produces( { MediaType.APPLICATION_JSON } ) @Produces( { MediaType.APPLICATION_JSON } )
@Consumes( { MediaType.APPLICATION_JSON } ) @Consumes( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_CREATE_OPERATION ) @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_CREATE_OPERATION )
@io.swagger.v3.oas.annotations.Operation( summary = "Creates a user",
responses = {
@ApiResponse( responseCode = "201",
description = "If user creation was successful",
headers = {
@Header( name="Location", description = "The URL of the created mapping")
}
),
@ApiResponse( responseCode = "405", description = "Invalid input" ),
@ApiResponse( responseCode = "303", description = "The user exists already",
headers = {
@Header( name="Location", description = "The URL of existing user")
}
)
}
)
ActionStatus createUser( User user ) ActionStatus createUser( User user )
throws RedbackServiceException; throws RedbackServiceException;
@ -86,12 +109,28 @@ public interface UserService
@Produces( { MediaType.APPLICATION_JSON } ) @Produces( { MediaType.APPLICATION_JSON } )
@Consumes( { MediaType.APPLICATION_JSON } ) @Consumes( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true ) @RedbackAuthorization( noRestriction = true )
@io.swagger.v3.oas.annotations.Operation( summary = "Creates a user",
responses = {
@ApiResponse( responseCode = "201",
description = "If user creation was successful",
headers = {
@Header( name="Location", description = "The URL of the created mapping")
}
),
@ApiResponse( responseCode = "405", description = "Invalid input" ),
@ApiResponse( responseCode = "303", description = "The user exists already",
headers = {
@Header( name="Location", description = "The URL of the existing admin user")
}
)
}
)
ActionStatus createAdminUser( User user ) ActionStatus createAdminUser( User user )
throws RedbackServiceException; throws RedbackServiceException;
@Path( "admin/exists" ) @Path( "admin/exists" )
@GET @GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } ) @Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( noRestriction = true ) @RedbackAuthorization( noRestriction = true )
AvailabilityStatus isAdminUserExists() AvailabilityStatus isAdminUserExists()
throws RedbackServiceException; throws RedbackServiceException;
@ -106,7 +145,7 @@ public interface UserService
@Path( "{userId}" ) @Path( "{userId}" )
@PUT @PUT
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } ) @Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION ) @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
ActionStatus updateUser( @PathParam( "userId" ) String userId, User user ) ActionStatus updateUser( @PathParam( "userId" ) String userId, User user )
throws RedbackServiceException; throws RedbackServiceException;
@ -136,7 +175,7 @@ public interface UserService
@GET @GET
@Produces( { MediaType.APPLICATION_JSON } ) @Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION ) @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION )
PasswordStatus passwordChangeRequired( @PathParam( "userId" ) String username ) PasswordStatus passwordChangeRequired( @PathParam( "userId" ) String userId )
throws RedbackServiceException; throws RedbackServiceException;
/** /**

View File

@ -33,10 +33,8 @@ import org.apache.archiva.redback.keys.memory.MemoryKeyManager;
import org.apache.archiva.redback.policy.AccountLockedException; import org.apache.archiva.redback.policy.AccountLockedException;
import org.apache.archiva.redback.policy.MustChangePasswordException; import org.apache.archiva.redback.policy.MustChangePasswordException;
import org.apache.archiva.redback.rest.api.model.ActionStatus; 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.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.LoginRequest; 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.model.User;
import org.apache.archiva.redback.rest.api.services.LoginService; import org.apache.archiva.redback.rest.api.services.LoginService;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.RedbackServiceException;

View File

@ -31,16 +31,14 @@ import org.apache.archiva.redback.policy.AccountLockedException;
import org.apache.archiva.redback.policy.MustChangePasswordException; import org.apache.archiva.redback.policy.MustChangePasswordException;
import org.apache.archiva.redback.rest.api.model.ErrorMessage; 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.GrantType;
import org.apache.archiva.redback.rest.api.model.PingResult; import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.RequestTokenRequest; import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
import org.apache.archiva.redback.rest.api.model.TokenRequest;
import org.apache.archiva.redback.rest.api.model.TokenResponse; import org.apache.archiva.redback.rest.api.model.TokenResponse;
import org.apache.archiva.redback.rest.api.model.User; 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.UserLogin;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; 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.api.services.v2.AuthenticationService;
import org.apache.archiva.redback.rest.services.interceptors.RedbackPrincipal; import org.apache.archiva.redback.rest.services.interceptors.RedbackPrincipal;
import org.apache.archiva.redback.rest.services.interceptors.RedbackSecurityContext;
import org.apache.archiva.redback.system.SecuritySession; import org.apache.archiva.redback.system.SecuritySession;
import org.apache.archiva.redback.system.SecuritySystem; import org.apache.archiva.redback.system.SecuritySystem;
import org.apache.archiva.redback.users.UserManagerException; import org.apache.archiva.redback.users.UserManagerException;
@ -125,7 +123,7 @@ public class DefaultAuthenticationService
} }
@Override @Override
public TokenResponse logIn( RequestTokenRequest loginRequest ) public TokenResponse logIn( TokenRequest loginRequest )
throws RedbackServiceException throws RedbackServiceException
{ {
if (!GrantType.AUTHORIZATION_CODE.equals(loginRequest.getGrantType())) { if (!GrantType.AUTHORIZATION_CODE.equals(loginRequest.getGrantType())) {
@ -208,7 +206,7 @@ public class DefaultAuthenticationService
} }
@Override @Override
public TokenResponse token( TokenRequest request ) throws RedbackServiceException public TokenResponse token( org.apache.archiva.redback.rest.api.model.TokenRequest request ) throws RedbackServiceException
{ {
if (!GrantType.REFRESH_TOKEN.equals(request.getGrantType())) { if (!GrantType.REFRESH_TOKEN.equals(request.getGrantType())) {
log.debug( "Bad grant type {}, expected: refresh_token", request.getGrantType( ).name( ).toLowerCase( ) ); log.debug( "Bad grant type {}, expected: refresh_token", request.getGrantType( ).name( ).toLowerCase( ) );

View File

@ -28,9 +28,8 @@ import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapperConfiguration; 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.ActionStatus;
import org.apache.archiva.redback.rest.api.model.Group; import org.apache.archiva.redback.rest.api.model.Group;
import org.apache.archiva.redback.rest.api.model.GroupMappingUpdateRequest;
import org.apache.archiva.redback.rest.api.model.v2.GroupMapping; import org.apache.archiva.redback.rest.api.model.v2.GroupMapping;
import org.apache.archiva.redback.rest.api.model.PagedResult; import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.v2.GroupService; import org.apache.archiva.redback.rest.api.services.v2.GroupService;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -94,7 +93,7 @@ public class DefaultGroupService
} }
@Override @Override
public PagedResult<List<Group>> getGroups( Long offset, Long limit ) throws RedbackServiceException public PagedResult<Group> getGroups( Integer offset, Integer limit ) throws RedbackServiceException
{ {
LdapConnection ldapConnection = null; LdapConnection ldapConnection = null;

View File

@ -45,14 +45,15 @@ 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.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.ErrorMessage; 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.Operation;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.PasswordStatus; 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.Permission;
import org.apache.archiva.redback.rest.api.model.PingResult; import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.RegistrationKey; 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.ResetPasswordRequest;
import org.apache.archiva.redback.rest.api.model.Resource; 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.v2.User;
import org.apache.archiva.redback.rest.api.model.UserRegistrationRequest; 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.VerificationStatus;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.v2.UserService; import org.apache.archiva.redback.rest.api.services.v2.UserService;
@ -81,6 +82,7 @@ import javax.ws.rs.core.Response;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -159,17 +161,17 @@ public class DefaultUserService
try try
{ {
org.apache.archiva.redback.users.User u = userManager.findUser( user.getUsername() ); org.apache.archiva.redback.users.User u = userManager.findUser( user.getUserId() );
if ( u != null ) if ( u != null )
{ {
throw new RedbackServiceException( throw new RedbackServiceException(
new ErrorMessage( "user " + user.getUsername() + " already exists" ) ); new ErrorMessage( "user " + user.getUserId() + " already exists" ) );
} }
} }
catch ( UserNotFoundException e ) catch ( UserNotFoundException e )
{ {
//ignore we just want to prevent non human readable error message from backend :-) //ignore we just want to prevent non human readable error message from backend :-)
log.debug( "user {} not exists", user.getUsername() ); log.debug( "user {} not exists", user.getUserId() );
} }
catch ( UserManagerException e ) catch ( UserManagerException e )
{ {
@ -177,7 +179,7 @@ public class DefaultUserService
} }
// data validation // data validation
if ( StringUtils.isEmpty( user.getUsername() ) ) if ( StringUtils.isEmpty( user.getUserId() ) )
{ {
throw new RedbackServiceException( new ErrorMessage( "username cannot be empty" ) ); throw new RedbackServiceException( new ErrorMessage( "username cannot be empty" ) );
} }
@ -196,7 +198,7 @@ public class DefaultUserService
{ {
org.apache.archiva.redback.users.User u = org.apache.archiva.redback.users.User u =
userManager.createUser( user.getUsername(), user.getFullName(), user.getEmail() ); userManager.createUser( user.getUserId(), user.getFullName(), user.getEmail() );
u.setPassword( user.getPassword() ); u.setPassword( user.getPassword() );
u.setLocked( user.isLocked() ); u.setLocked( user.isLocked() );
u.setPasswordChangeRequired( user.isPasswordChangeRequired() ); u.setPasswordChangeRequired( user.isPasswordChangeRequired() );
@ -292,20 +294,25 @@ public class DefaultUserService
} }
@Override @Override
public List<User> getUsers() public PagedResult<User> getUsers(Integer offset,
Integer limit)
throws RedbackServiceException throws RedbackServiceException
{ {
try try
{ {
List<? extends org.apache.archiva.redback.users.User> users = userManager.getUsers(); List<? extends org.apache.archiva.redback.users.User> users = userManager.getUsers();
List<User> simpleUsers = new ArrayList<>( users.size( ) ); if (offset>=users.size()) {
return new PagedResult<>( users.size( ), offset, limit, Collections.emptyList( ) );
}
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() );
for ( org.apache.archiva.redback.users.User user : users ) for ( org.apache.archiva.redback.users.User user : resultList )
{ {
simpleUsers.add( getRestUser( user ) ); simpleUsers.add( getRestUser( user ) );
} }
return new PagedResult<>( users.size( ), offset, limit, simpleUsers );
return simpleUsers;
} }
catch ( UserManagerException e ) catch ( UserManagerException e )
{ {
@ -330,7 +337,7 @@ public class DefaultUserService
throw new RedbackServiceException( new ErrorMessage( "user parameter is mandatory" ), throw new RedbackServiceException( new ErrorMessage( "user parameter is mandatory" ),
Response.Status.BAD_REQUEST.getStatusCode() ); Response.Status.BAD_REQUEST.getStatusCode() );
} }
if ( !StringUtils.equals( redbackRequestInformation.getUser().getUsername(), user.getUsername() ) ) if ( !StringUtils.equals( redbackRequestInformation.getUser().getUsername(), user.getUserId() ) )
{ {
throw new RedbackServiceException( new ErrorMessage( "you can update only your profile" ), throw new RedbackServiceException( new ErrorMessage( "you can update only your profile" ),
Response.Status.FORBIDDEN.getStatusCode() ); Response.Status.FORBIDDEN.getStatusCode() );
@ -342,11 +349,11 @@ public class DefaultUserService
Response.Status.BAD_REQUEST.getStatusCode() ); Response.Status.BAD_REQUEST.getStatusCode() );
} }
User realUser = getUser( user.getUsername() ); User realUser = getUser( user.getUserId() );
try try
{ {
String previousEncodedPassword = String previousEncodedPassword =
securitySystem.getUserManager().findUser( user.getUsername(), false ).getEncodedPassword(); securitySystem.getUserManager().findUser( user.getUserId(), false ).getEncodedPassword();
// check oldPassword with the current one // check oldPassword with the current one
@ -374,12 +381,12 @@ public class DefaultUserService
// ui can limit to not update password // ui can limit to not update password
if ( StringUtils.isNotBlank( user.getPassword() ) ) if ( StringUtils.isNotBlank( user.getPassword() ) )
{ {
passwordValidator.validatePassword( user.getPassword(), user.getUsername() ); passwordValidator.validatePassword( user.getPassword(), user.getUserId() );
realUser.setPassword( user.getPassword() ); realUser.setPassword( user.getPassword() );
} }
updateUser( realUser.getUsername(), realUser ); updateUser( realUser.getUserId(), realUser );
return ActionStatus.SUCCESS; return ActionStatus.SUCCESS;
} }
@ -390,7 +397,7 @@ public class DefaultUserService
{ {
try try
{ {
org.apache.archiva.redback.users.User rawUser = userManager.findUser( user.getUsername(), false ); org.apache.archiva.redback.users.User rawUser = userManager.findUser( user.getUserId(), false );
rawUser.setFullName( user.getFullName() ); rawUser.setFullName( user.getFullName() );
rawUser.setEmail( user.getEmail() ); rawUser.setEmail( user.getEmail() );
rawUser.setValidated( user.isValidated() ); rawUser.setValidated( user.isValidated() );
@ -520,9 +527,9 @@ public class DefaultUserService
log.warn( "Admin user exists already" ); log.warn( "Admin user exists already" );
return ActionStatus.FAIL; return ActionStatus.FAIL;
} }
log.debug("Creating admin admin user '{}'", adminUser.getUsername()); log.debug("Creating admin admin user '{}'", adminUser.getUserId());
if (!RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME.equals(adminUser.getUsername())) { if (!RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME.equals(adminUser.getUserId())) {
log.error("Wrong admin user name {}", adminUser.getUsername()); log.error("Wrong admin user name {}", adminUser.getUserId());
throw new RedbackServiceException(new ErrorMessage("admin.wrongUsername")); throw new RedbackServiceException(new ErrorMessage("admin.wrongUsername"));
} }
@ -657,13 +664,13 @@ public class DefaultUserService
// NOTE: Do not perform Password Rules Validation Here. // NOTE: Do not perform Password Rules Validation Here.
if ( userManager.userExists( user.getUsername() ) ) if ( userManager.userExists( user.getUserId() ) )
{ {
throw new RedbackServiceException( throw new RedbackServiceException(
new ErrorMessage( "user.already.exists", new String[]{ user.getUsername() } ) ); new ErrorMessage( "user.already.exists", new String[]{ user.getUserId() } ) );
} }
u = userManager.createUser( user.getUsername(), user.getFullName(), user.getEmail() ); u = userManager.createUser( user.getUserId(), user.getFullName(), user.getEmail() );
u.setPassword( user.getPassword() ); u.setPassword( user.getPassword() );
u.setValidated( false ); u.setValidated( false );
u.setLocked( false ); u.setLocked( false );
@ -904,13 +911,13 @@ public class DefaultUserService
{ {
RedbackServiceException redbackServiceException = RedbackServiceException redbackServiceException =
new RedbackServiceException( "issues during validating user" ); new RedbackServiceException( "issues during validating user" );
if ( StringUtils.isEmpty( user.getUsername() ) ) if ( StringUtils.isEmpty( user.getUserId() ) )
{ {
redbackServiceException.addErrorMessage( new ErrorMessage( "username.required", null ) ); redbackServiceException.addErrorMessage( new ErrorMessage( "username.required", null ) );
} }
else else
{ {
if ( !user.getUsername().matches( VALID_USERNAME_CHARS ) ) if ( !user.getUserId().matches( VALID_USERNAME_CHARS ) )
{ {
redbackServiceException.addErrorMessage( new ErrorMessage( "username.invalid.characters", null ) ); redbackServiceException.addErrorMessage( new ErrorMessage( "username.invalid.characters", null ) );
} }
@ -955,7 +962,7 @@ public class DefaultUserService
try try
{ {
org.apache.archiva.redback.users.User tmpuser = org.apache.archiva.redback.users.User tmpuser =
userManager.createUser( user.getUsername(), user.getFullName(), user.getEmail() ); userManager.createUser( user.getUserId(), user.getFullName(), user.getEmail() );
user.setPassword( user.getPassword() ); user.setPassword( user.getPassword() );
@ -995,7 +1002,7 @@ public class DefaultUserService
if ( user != null ) if ( user != null )
{ {
user.setLocked( false ); user.setLocked( false );
updateUser( user.getUsername(), user ); updateUser( user.getUserId(), user );
return ActionStatus.SUCCESS; return ActionStatus.SUCCESS;
} }
return ActionStatus.FAIL; return ActionStatus.FAIL;
@ -1009,21 +1016,21 @@ public class DefaultUserService
if ( user != null ) if ( user != null )
{ {
user.setLocked( true ); user.setLocked( true );
updateUser( user.getUsername(), user ); updateUser( user.getUserId(), user );
return ActionStatus.SUCCESS; return ActionStatus.SUCCESS;
} }
return ActionStatus.FAIL; return ActionStatus.FAIL;
} }
@Override @Override
public PasswordStatus passwordChangeRequired( String username ) public PasswordStatus passwordChangeRequired( String userId )
throws RedbackServiceException throws RedbackServiceException
{ {
User user = getUser( username ); User user = getUser( userId );
if ( user == null ) if ( user == null )
{ {
user.setPasswordChangeRequired( true ); user.setPasswordChangeRequired( true );
updateUser( user.getUsername(), user ); updateUser( user.getUserId(), user );
return new PasswordStatus( true ); return new PasswordStatus( true );
} }
return new PasswordStatus( false ); return new PasswordStatus( false );

View File

@ -0,0 +1,46 @@
package org.apache.archiva.redback.rest.services.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 org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import java.util.Collections;
import java.util.List;
/**
* Helper class for creating paged results.
*
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class PagingHelper
{
public static <T> PagedResult<T> getResultFromList( int offset, int limit, List<T> data) {
if (offset>=data.size()) {
return new PagedResult<>( data.size( ), offset, limit, Collections.emptyList( ) );
}
int lastIndex = getLastIndex( offset, limit, data.size( ) );
return new PagedResult<>( data.size(), offset, limit, data.subList( offset, lastIndex ) );
}
public static int getLastIndex(int offset, int limit, int listSize) {
return Math.min( Math.max( 0, offset + limit ), listSize );
}
}

View File

@ -20,12 +20,11 @@ package org.apache.archiva.redback.rest.services.v2;
import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants; import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.rest.api.model.GrantType; import org.apache.archiva.redback.rest.api.model.GrantType;
import org.apache.archiva.redback.rest.api.model.RequestTokenRequest; import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
import org.apache.archiva.redback.rest.api.model.TokenResponse; import org.apache.archiva.redback.rest.api.model.TokenResponse;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.services.BaseSetup; import org.apache.archiva.redback.rest.services.BaseSetup;
import org.apache.archiva.redback.users.User; import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManager;
import org.apache.archiva.redback.users.UserManagerException; import org.apache.archiva.redback.users.UserManagerException;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
@ -64,7 +63,7 @@ public class AuthenticationServiceTest
public void loginAdmin() public void loginAdmin()
throws Exception throws Exception
{ {
RequestTokenRequest request = new RequestTokenRequest( RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME, TokenRequest request = new TokenRequest( RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME,
BaseSetup.getAdminPwd() ); BaseSetup.getAdminPwd() );
request.setGrantType( GrantType.AUTHORIZATION_CODE ); request.setGrantType( GrantType.AUTHORIZATION_CODE );
@ -103,7 +102,7 @@ public class AuthenticationServiceTest
// START SNIPPET: create-user // START SNIPPET: create-user
User user = addUser( "toto", "foo123", "toto the king", "toto@toto.fr" ); User user = addUser( "toto", "foo123", "toto the king", "toto@toto.fr" );
// END SNIPPET: create-user // END SNIPPET: create-user
RequestTokenRequest request = new RequestTokenRequest( "toto", "foo123" ); TokenRequest request = new TokenRequest( "toto", "foo123" );
request.setGrantType( GrantType.AUTHORIZATION_CODE ); request.setGrantType( GrantType.AUTHORIZATION_CODE );
TokenResponse result = getLoginServiceV2( "" ).logIn( request ); TokenResponse result = getLoginServiceV2( "" ).logIn( request );
assertNotNull( result ); assertNotNull( result );

View File

@ -25,7 +25,6 @@ import org.apache.archiva.redback.rest.api.services.v2.GroupService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory; import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.impl.UriInfoImpl;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
@ -46,7 +45,6 @@ import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext; import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext; import javax.naming.directory.InitialDirContext;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -298,7 +296,7 @@ public class GroupServiceTest
{ {
GroupService service = getGroupService( authorizationHeader ); GroupService service = getGroupService( authorizationHeader );
List<String> allGroups = service.getGroups( Long.valueOf( 0 ), Long.valueOf( Long.MAX_VALUE ) ).getData( ).stream( ).map( group -> group.getName( ) ).collect( Collectors.toList( ) ); List<String> allGroups = service.getGroups( 0 , Integer.MAX_VALUE ).getData( ).stream( ).map( group -> group.getName( ) ).collect( Collectors.toList( ) );
assertNotNull( allGroups ); assertNotNull( allGroups );
assertEquals( 3, allGroups.size( ) ); assertEquals( 3, allGroups.size( ) );

View File

@ -0,0 +1,75 @@
package org.apache.archiva.redback.rest.services.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.restassured.response.Response;
import org.apache.archiva.redback.rest.api.model.Group;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Collectors;
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class NativeUserServiceTest extends AbstractNativeRestServices
{
@Override
protected String getServicePath( )
{
return "/users";
}
@BeforeAll
void setup() throws Exception
{
super.setupNative();
}
@AfterAll
void destroy() throws Exception
{
super.shutdownNative();
}
// @Test
// void getGroups() {
// String token = getAdminToken( );
// Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ).when( )
// .get( ).then( ).statusCode( 200 ).extract( ).response( );
// assertNotNull( response );
// List<Group> data = response.body( ).jsonPath( ).getList( "data", Group.class );
// assertNotNull( data );
// assertEquals( Integer.valueOf( 0 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
// assertEquals( Integer.valueOf( 1000 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
// assertEquals( Integer.valueOf( 6 ), response.body( ).jsonPath( ).get( "pagination.totalCount" ) );
// assertEquals( 6, data.size( ) );
// String[] values = data.stream( ).map( ldapInfo -> ldapInfo.getName( ) ).sorted( ).collect( Collectors.toList( ) ).toArray( new String[0] );
// assertArrayEquals( getTestGroupList( ).toArray( new String[0] ), values );
// assertEquals( "uid=admin," + this.peopleSuffix, data.get( 0 ).getMemberList( ).get( 0 ) );
// }
}

View File

@ -21,13 +21,14 @@ 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.GrantType;
import org.apache.archiva.redback.rest.api.model.Operation; import org.apache.archiva.redback.rest.api.model.Operation;
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.Permission;
import org.apache.archiva.redback.rest.api.model.PingResult; import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.RequestTokenRequest; import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
import org.apache.archiva.redback.rest.api.model.ResetPasswordRequest; import org.apache.archiva.redback.rest.api.model.ResetPasswordRequest;
import org.apache.archiva.redback.rest.api.model.TokenResponse; import org.apache.archiva.redback.rest.api.model.TokenResponse;
import org.apache.archiva.redback.rest.api.model.User; import org.apache.archiva.redback.rest.api.model.v2.User;
import org.apache.archiva.redback.rest.api.model.UserRegistrationRequest; 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.api.services.v2.UserService;
import org.apache.archiva.redback.rest.services.FakeCreateAdminService; import org.apache.archiva.redback.rest.services.FakeCreateAdminService;
import org.apache.archiva.redback.rest.services.mock.EmailMessage; import org.apache.archiva.redback.rest.services.mock.EmailMessage;
@ -121,9 +122,9 @@ public class UserServiceTest
{ {
String adminHeader = getAdminAuthzHeader( ); String adminHeader = getAdminAuthzHeader( );
UserService userService = getUserService( adminHeader ); UserService userService = getUserService( adminHeader );
List<User> users = userService.getUsers( ); PagedResult<org.apache.archiva.redback.rest.api.model.v2.User> users = userService.getUsers( 0, Integer.MAX_VALUE );
assertNotNull( users ); assertNotNull( users );
assertFalse( users.isEmpty( ) ); assertFalse( users.getData().isEmpty( ) );
} }
@Test @Test
@ -134,7 +135,7 @@ public class UserServiceTest
assertThrows( ForbiddenException.class, ( ) -> { assertThrows( ForbiddenException.class, ( ) -> {
try try
{ {
userService.getUsers( ); userService.getUsers( 0, Integer.MAX_VALUE);
} }
catch ( ForbiddenException e ) catch ( ForbiddenException e )
{ {
@ -199,11 +200,11 @@ public class UserServiceTest
UserService service = getUserService( getAdminAuthzHeader( ) ); UserService service = getUserService( getAdminAuthzHeader( ) );
User u = new User( ); User u = new User( );
u.setFullName( "the toto" ); u.setFullName( "the toto" );
u.setUsername( "toto" ); u.setUserId( "toto" );
u.setEmail( "toto@toto.fr" ); u.setEmail( "toto@toto.fr" );
u.setPassword( "toto123" ); u.setPassword( "toto123" );
u.setConfirmPassword( "toto123" ); u.setConfirmPassword( "toto123" );
String key = service.registerUser( u.getUsername(), new UserRegistrationRequest( u, "http://wine.fr/bordeaux" ) ).getKey( ); String key = service.registerUser( u.getUserId(), new UserRegistrationRequest( u, "http://wine.fr/bordeaux" ) ).getKey( );
assertNotEquals( "-1", key ); assertNotEquals( "-1", key );
@ -246,27 +247,91 @@ public class UserServiceTest
} }
@Test
public void registerWithValidation( )
throws Exception
{
try
{
mockJavaMailSender.getSendedEmails( ).clear( );
ServicesAssert assertService =
JAXRSClientFactory.create( "http://localhost:" + getServerPort( ) + "/" + getRestServicesPath( ) + "/testsService/",
ServicesAssert.class,
Collections.singletonList( getJsonProvider() ) );
assertService.clearEmailMessages();
UserService service = getUserService( getAdminAuthzHeader( ) );
User u = new User( );
u.setFullName( "the toto" );
u.setUserId( "toto" );
u.setEmail( "toto@toto.fr" );
u.setPassword( "toto123" );
u.setConfirmPassword( "toto123" );
String key = service.registerUser( u.getUserId(), new UserRegistrationRequest( u, "http://wine.fr/bordeaux" ) ).getKey( );
assertNotEquals( "-1", key );
List<EmailMessage> emailMessages = assertService.getEmailMessageSended( );
assertEquals( 1, emailMessages.size( ) );
assertEquals( "toto@toto.fr", emailMessages.get( 0 ).getTos( ).get( 0 ) );
assertEquals( "Welcome", emailMessages.get( 0 ).getSubject( ) );
String messageContent = emailMessages.get( 0 ).getText( );
log.info( "messageContent: {}", messageContent );
assertNotNull( messageContent );
assertTrue( messageContent.contains( "Use the following URL to validate your account." ) );
assertTrue( messageContent.contains( "http://wine.fr/bordeaux" ) );
assertTrue( messageContent.contains( "toto" ) );
assertTrue( service.validateUserRegistration( "toto", key ).isSuccess( ) );
service = getUserService( getAdminAuthzHeader( ) );
u = service.getUser( "toto" );
assertNotNull( u );
assertTrue( u.isValidated( ) );
assertTrue( u.isPasswordChangeRequired( ) );
// assertTrue( service.validateUserFromKey( key ).isSuccess( ) );
}
catch ( Exception e )
{
log.error( e.getMessage( ), e );
throw e;
}
finally
{
deleteUserQuietly( "toto" );
}
}
@Test @Test
public void registerNoUrl( ) public void registerNoUrl( )
throws Exception throws Exception
{ {
try try
{ {
UserService service = getUserService( getAdminAuthzHeader( ) );
User u = new User( );
u.setFullName( "the toto" );
u.setUsername( "toto" );
u.setEmail( "toto@toto.fr" );
u.setPassword( "toto123" );
u.setConfirmPassword( "toto123" );
String key = service.registerUser( u.getUsername(), new UserRegistrationRequest( u, null ) ).getKey( );
assertNotEquals( "-1", key );
ServicesAssert assertService = ServicesAssert assertService =
JAXRSClientFactory.create( "http://localhost:" + getServerPort( ) + "/" + getRestServicesPath( ) + "/testsService/", JAXRSClientFactory.create( "http://localhost:" + getServerPort( ) + "/" + getRestServicesPath( ) + "/testsService/",
ServicesAssert.class, ServicesAssert.class,
Collections.singletonList( getJsonProvider() ) ); Collections.singletonList( getJsonProvider() ) );
assertService.clearEmailMessages();
UserService service = getUserService( getAdminAuthzHeader( ) );
User u = new User( );
u.setFullName( "the toto" );
u.setUserId( "toto" );
u.setEmail( "toto@toto.fr" );
u.setPassword( "toto123" );
u.setConfirmPassword( "toto123" );
String key = service.registerUser( u.getUserId(), new UserRegistrationRequest( u, null ) ).getKey( );
assertNotEquals( "-1", key );
List<EmailMessage> emailMessages = assertService.getEmailMessageSended( ); List<EmailMessage> emailMessages = assertService.getEmailMessageSended( );
assertEquals( 1, emailMessages.size( ) ); assertEquals( 1, emailMessages.size( ) );
@ -322,11 +387,11 @@ public class UserServiceTest
UserService service = getUserService( getAdminAuthzHeader( ) ); UserService service = getUserService( getAdminAuthzHeader( ) );
User u = new User( ); User u = new User( );
u.setFullName( "the toto" ); u.setFullName( "the toto" );
u.setUsername( "toto" ); u.setUserId( "toto" );
u.setEmail( "toto@toto.fr" ); u.setEmail( "toto@toto.fr" );
u.setPassword( "toto123" ); u.setPassword( "toto123" );
u.setConfirmPassword( "toto123" ); u.setConfirmPassword( "toto123" );
String key = service.registerUser( u.getUsername(), new UserRegistrationRequest( u, "http://wine.fr/bordeaux" ) ).getKey( ); String key = service.registerUser( u.getUserId(), new UserRegistrationRequest( u, "http://wine.fr/bordeaux" ) ).getKey( );
assertNotEquals( "-1", key ); assertNotEquals( "-1", key );
@ -354,7 +419,7 @@ public class UserServiceTest
// assertTrue( service.validateUserFromKey( key ).isSuccess( ) ); // assertTrue( service.validateUserFromKey( key ).isSuccess( ) );
assertTrue( service.resetPassword(u.getUsername(), new ResetPasswordRequest( "toto", "http://foo.fr/bar" ) ).isSuccess( ) ); assertTrue( service.resetPassword(u.getUserId(), new ResetPasswordRequest( "toto", "http://foo.fr/bar" ) ).isSuccess( ) );
emailMessages = assertService.getEmailMessageSended( ); emailMessages = assertService.getEmailMessageSended( );
assertEquals( 2, emailMessages.size( ) ); assertEquals( 2, emailMessages.size( ) );
@ -433,7 +498,7 @@ public class UserServiceTest
{ {
User u = new User( ); User u = new User( );
u.setFullName( "the toto" ); u.setFullName( "the toto" );
u.setUsername( "toto" ); u.setUserId( "toto" );
u.setEmail( "toto@toto.fr" ); u.setEmail( "toto@toto.fr" );
u.setPassword( "toto123" ); u.setPassword( "toto123" );
u.setConfirmPassword( "toto123" ); u.setConfirmPassword( "toto123" );
@ -444,7 +509,7 @@ public class UserServiceTest
u.setEmail( "toto@titi.fr" ); u.setEmail( "toto@titi.fr" );
u.setPassword( "toto1234" ); u.setPassword( "toto1234" );
u.setPreviousPassword( "toto123" ); u.setPreviousPassword( "toto123" );
getUserService( getUserAuthzHeader( "toto" ) ).updateMe( u.getUsername(), u ); getUserService( getUserAuthzHeader( "toto" ) ).updateMe( u. getUserId(), u );
u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" ); u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" );
assertEquals( "the toto123", u.getFullName( ) ); assertEquals( "the toto123", u.getFullName( ) );
@ -454,7 +519,7 @@ public class UserServiceTest
u.setEmail( "toto@tititi.fr" ); u.setEmail( "toto@tititi.fr" );
u.setPassword( "toto12345" ); u.setPassword( "toto12345" );
u.setPreviousPassword( "toto1234" ); u.setPreviousPassword( "toto1234" );
getUserService( getUserAuthzHeader( "toto" )) .updateMe(u.getUsername(), u ); getUserService( getUserAuthzHeader( "toto" )) .updateMe(u.getUserId(), u );
u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" ); u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" );
assertEquals( "the toto1234", u.getFullName( ) ); assertEquals( "the toto1234", u.getFullName( ) );
@ -484,7 +549,7 @@ public class UserServiceTest
assertNotNull( user ); assertNotNull( user );
assertEquals( "toto the king", user.getFullName( ) ); assertEquals( "toto the king", user.getFullName( ) );
assertEquals( "toto@toto.fr", user.getEmail( ) ); assertEquals( "toto@toto.fr", user.getEmail( ) );
TokenResponse result = getLoginServiceV2( null ).logIn( new RequestTokenRequest( "toto", "foo123", GrantType.AUTHORIZATION_CODE ) ); TokenResponse result = getLoginServiceV2( null ).logIn( new TokenRequest( "toto", "foo123", GrantType.AUTHORIZATION_CODE ) );
getLoginServiceV2( "Bearer " + result.getAccessToken( ) ).pingWithAutz( ); getLoginServiceV2( "Bearer " + result.getAccessToken( ) ).pingWithAutz( );
userService.lockUser( "toto" ); userService.lockUser( "toto" );

View File

@ -299,4 +299,5 @@ public interface User
*/ */
String getUserManagerId(); String getUserManagerId();
} }