diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/Constants.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/Constants.java new file mode 100644 index 00000000..cd72bf52 --- /dev/null +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/Constants.java @@ -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 + */ +public class Constants +{ + public static final String DEFAULT_PAGE_LIMIT = "1000"; +} diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/PagedResult.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/PagedResult.java similarity index 82% rename from redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/PagedResult.java rename to redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/PagedResult.java index cc3d327d..1aa998f5 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/PagedResult.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/PagedResult.java @@ -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 @@ -19,6 +19,7 @@ package org.apache.archiva.redback.rest.api.model; */ import io.swagger.v3.oas.annotations.media.Schema; +import org.apache.archiva.redback.rest.api.model.PaginationInfo; import javax.xml.bind.annotation.XmlRootElement; import java.util.List; @@ -32,28 +33,28 @@ import java.util.List; public class PagedResult { PaginationInfo pagination; - T data; + List data; public PagedResult() { } - public PagedResult( long totalCount, long offset, long limit, T data ) { + public PagedResult( int totalCount, int offset, int limit, List data ) { this.data = data; this.pagination = new PaginationInfo( totalCount, offset, limit ); } - public static final PagedResult of(long totalSize, long offset, long limit, T element) { + public static final PagedResult of(int totalSize, int offset, int limit, List 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. ") - public T getData( ) + public List getData( ) { return data; } - public void setData( T data ) + public void setData( List data ) { this.data = data; } diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/PingResult.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/PingResult.java similarity index 97% rename from redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/PingResult.java rename to redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/PingResult.java index 070840d3..4cfd7b8d 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/PingResult.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/PingResult.java @@ -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 diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/Token.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/Token.java similarity index 98% rename from redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/Token.java rename to redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/Token.java index 8bec5e07..7b39d9ac 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/Token.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/Token.java @@ -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 diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/RequestTokenRequest.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/TokenRequest.java similarity index 90% rename from redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/RequestTokenRequest.java rename to redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/TokenRequest.java index 3413ffd7..a39d4fca 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/RequestTokenRequest.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/TokenRequest.java @@ -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 @@ -19,6 +19,7 @@ package org.apache.archiva.redback.rest.api.model; */ 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.XmlRootElement; @@ -29,7 +30,7 @@ import java.io.Serializable; */ @XmlRootElement(name="refreshToken") @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; GrantType grantType = null; @@ -42,24 +43,24 @@ public class RequestTokenRequest implements Serializable String password; String redirectUri; - public RequestTokenRequest() { + public TokenRequest() { } - public RequestTokenRequest( String userId, String password ) + public TokenRequest( String userId, String password ) { this.userId = userId; this.password = password; } - public RequestTokenRequest( String userId, String password, String scope ) + public TokenRequest( String userId, String password, String scope ) { this.userId = userId; this.password = password; this.scope = scope; } - public RequestTokenRequest( String userId, String password, GrantType grantType ) + public TokenRequest( String userId, String password, GrantType grantType ) { this.userId = userId; this.password = password; diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/User.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/User.java new file mode 100644 index 00000000..d7f77fe5 --- /dev/null +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/User.java @@ -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 not return on user read + * + * @since 2.0 + */ + private List 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 getAssignedRoles() + { + return assignedRoles; + } + + public void setAssignedRoles( List 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(); + } +} diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/UserRegistrationRequest.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/UserRegistrationRequest.java new file mode 100644 index 00000000..9522bde0 --- /dev/null +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/UserRegistrationRequest.java @@ -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(); + } +} diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/LoginService.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/LoginService.java index 789c72a8..00b51a02 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/LoginService.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/LoginService.java @@ -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.tags.Tag; import org.apache.archiva.redback.authorization.RedbackAuthorization; -import org.apache.archiva.redback.keys.AuthenticationKey; import org.apache.archiva.redback.rest.api.model.ActionStatus; -import org.apache.archiva.redback.rest.api.model.AuthenticationKeyResult; import org.apache.archiva.redback.rest.api.model.LoginRequest; -import org.apache.archiva.redback.rest.api.model.PingResult; import org.apache.archiva.redback.rest.api.model.User; import javax.ws.rs.GET; diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/AuthenticationService.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/AuthenticationService.java index ffd5b6c6..6ddbceee 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/AuthenticationService.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/AuthenticationService.java @@ -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.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.responses.ApiResponse; 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 org.apache.archiva.redback.authorization.RedbackAuthorization; -import org.apache.archiva.redback.rest.api.model.PingResult; -import org.apache.archiva.redback.rest.api.model.TokenRequest; -import org.apache.archiva.redback.rest.api.model.RequestTokenRequest; +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.TokenResponse; import org.apache.archiva.redback.rest.api.model.User; 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." ) } ) - TokenResponse logIn( RequestTokenRequest loginRequest ) + TokenResponse logIn( TokenRequest loginRequest ) throws RedbackServiceException; /** @@ -111,7 +107,7 @@ public interface AuthenticationService } ) @SecurityRequirement( name="BearerAuth" ) - TokenResponse token( TokenRequest tokenRequest ) + TokenResponse token( org.apache.archiva.redback.rest.api.model.TokenRequest tokenRequest ) throws RedbackServiceException; diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java index bb279021..b2164983 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java @@ -26,9 +26,10 @@ 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.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.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.services.RedbackServiceException; @@ -58,8 +59,6 @@ import java.util.List; public interface GroupService { - String DEFAULT_PAGE_LIMIT = "1000"; - @Path( "" ) @GET @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." ) } ) - PagedResult> getGroups( @QueryParam( "offset" ) @DefaultValue( "0" ) Long offset, - @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Long limit) + PagedResult getGroups( @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, + @QueryParam( "limit" ) @DefaultValue( value = Constants.DEFAULT_PAGE_LIMIT ) Integer limit) throws RedbackServiceException; diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java index ccb2e359..4ecf1e77 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java @@ -19,6 +19,8 @@ package org.apache.archiva.redback.rest.api.services.v2; * 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.tags.Tag; 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.AvailabilityStatus; 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.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.ResetPasswordRequest; -import org.apache.archiva.redback.rest.api.model.User; -import org.apache.archiva.redback.rest.api.model.UserRegistrationRequest; +import org.apache.archiva.redback.rest.api.model.v2.User; +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.services.RedbackServiceException; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; 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 java.util.List; + +import static org.apache.archiva.redback.rest.api.Constants.DEFAULT_PAGE_LIMIT; @Path( "/users" ) @Tag(name = "v2") @@ -66,7 +72,8 @@ public interface UserService @GET @Produces( { MediaType.APPLICATION_JSON } ) @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_LIST_OPERATION ) - List getUsers() + PagedResult getUsers( @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset, + @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit) throws RedbackServiceException; @Path( "" ) @@ -74,6 +81,22 @@ public interface UserService @Produces( { MediaType.APPLICATION_JSON } ) @Consumes( { MediaType.APPLICATION_JSON } ) @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 ) throws RedbackServiceException; @@ -86,12 +109,28 @@ public interface UserService @Produces( { MediaType.APPLICATION_JSON } ) @Consumes( { MediaType.APPLICATION_JSON } ) @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 ) throws RedbackServiceException; @Path( "admin/exists" ) @GET - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } ) + @Produces( { MediaType.APPLICATION_JSON } ) @RedbackAuthorization( noRestriction = true ) AvailabilityStatus isAdminUserExists() throws RedbackServiceException; @@ -106,7 +145,7 @@ public interface UserService @Path( "{userId}" ) @PUT - @Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } ) + @Produces( { MediaType.APPLICATION_JSON } ) @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION ) ActionStatus updateUser( @PathParam( "userId" ) String userId, User user ) throws RedbackServiceException; @@ -136,7 +175,7 @@ public interface UserService @GET @Produces( { MediaType.APPLICATION_JSON } ) @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_USER_EDIT_OPERATION ) - PasswordStatus passwordChangeRequired( @PathParam( "userId" ) String username ) + PasswordStatus passwordChangeRequired( @PathParam( "userId" ) String userId ) throws RedbackServiceException; /** diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/DefaultLoginService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/DefaultLoginService.java index d51d3a36..2ae00193 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/DefaultLoginService.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/DefaultLoginService.java @@ -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.MustChangePasswordException; import org.apache.archiva.redback.rest.api.model.ActionStatus; -import org.apache.archiva.redback.rest.api.model.AuthenticationKeyResult; import org.apache.archiva.redback.rest.api.model.ErrorMessage; import org.apache.archiva.redback.rest.api.model.LoginRequest; -import org.apache.archiva.redback.rest.api.model.PingResult; import org.apache.archiva.redback.rest.api.model.User; import org.apache.archiva.redback.rest.api.services.LoginService; import org.apache.archiva.redback.rest.api.services.RedbackServiceException; diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultAuthenticationService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultAuthenticationService.java index ca4d489e..2c627030 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultAuthenticationService.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultAuthenticationService.java @@ -31,16 +31,14 @@ import org.apache.archiva.redback.policy.AccountLockedException; import org.apache.archiva.redback.policy.MustChangePasswordException; 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.PingResult; -import org.apache.archiva.redback.rest.api.model.RequestTokenRequest; -import org.apache.archiva.redback.rest.api.model.TokenRequest; +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.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.services.RedbackServiceException; 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.RedbackSecurityContext; import org.apache.archiva.redback.system.SecuritySession; import org.apache.archiva.redback.system.SecuritySystem; import org.apache.archiva.redback.users.UserManagerException; @@ -125,7 +123,7 @@ public class DefaultAuthenticationService } @Override - public TokenResponse logIn( RequestTokenRequest loginRequest ) + public TokenResponse logIn( TokenRequest loginRequest ) throws RedbackServiceException { if (!GrantType.AUTHORIZATION_CODE.equals(loginRequest.getGrantType())) { @@ -208,7 +206,7 @@ public class DefaultAuthenticationService } @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())) { log.debug( "Bad grant type {}, expected: refresh_token", request.getGrantType( ).name( ).toLowerCase( ) ); diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java index fb49c70c..ff70ea79 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java @@ -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.rest.api.model.ActionStatus; 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.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.v2.GroupService; import org.slf4j.Logger; @@ -94,7 +93,7 @@ public class DefaultGroupService } @Override - public PagedResult> getGroups( Long offset, Long limit ) throws RedbackServiceException + public PagedResult getGroups( Integer offset, Integer limit ) throws RedbackServiceException { LdapConnection ldapConnection = null; diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java index 897459b0..63bc8167 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java @@ -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.ErrorMessage; 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.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.ResetPasswordRequest; import org.apache.archiva.redback.rest.api.model.Resource; -import org.apache.archiva.redback.rest.api.model.User; -import org.apache.archiva.redback.rest.api.model.UserRegistrationRequest; +import org.apache.archiva.redback.rest.api.model.v2.User; +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.services.RedbackServiceException; 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.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -159,17 +161,17 @@ public class DefaultUserService 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 ) { throw new RedbackServiceException( - new ErrorMessage( "user " + user.getUsername() + " already exists" ) ); + new ErrorMessage( "user " + user.getUserId() + " already exists" ) ); } } catch ( UserNotFoundException e ) { //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 ) { @@ -177,7 +179,7 @@ public class DefaultUserService } // data validation - if ( StringUtils.isEmpty( user.getUsername() ) ) + if ( StringUtils.isEmpty( user.getUserId() ) ) { throw new RedbackServiceException( new ErrorMessage( "username cannot be empty" ) ); } @@ -196,7 +198,7 @@ public class DefaultUserService { 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.setLocked( user.isLocked() ); u.setPasswordChangeRequired( user.isPasswordChangeRequired() ); @@ -292,20 +294,25 @@ public class DefaultUserService } @Override - public List getUsers() + public PagedResult getUsers(Integer offset, + Integer limit) throws RedbackServiceException { try { List users = userManager.getUsers(); - List 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 resultList = users.subList( offset, endIndex ); + List 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 ) ); } - - return simpleUsers; + return new PagedResult<>( users.size( ), offset, limit, simpleUsers ); } catch ( UserManagerException e ) { @@ -330,7 +337,7 @@ public class DefaultUserService throw new RedbackServiceException( new ErrorMessage( "user parameter is mandatory" ), 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" ), Response.Status.FORBIDDEN.getStatusCode() ); @@ -342,11 +349,11 @@ public class DefaultUserService Response.Status.BAD_REQUEST.getStatusCode() ); } - User realUser = getUser( user.getUsername() ); + User realUser = getUser( user.getUserId() ); try { String previousEncodedPassword = - securitySystem.getUserManager().findUser( user.getUsername(), false ).getEncodedPassword(); + securitySystem.getUserManager().findUser( user.getUserId(), false ).getEncodedPassword(); // check oldPassword with the current one @@ -374,12 +381,12 @@ public class DefaultUserService // ui can limit to not update password if ( StringUtils.isNotBlank( user.getPassword() ) ) { - passwordValidator.validatePassword( user.getPassword(), user.getUsername() ); + passwordValidator.validatePassword( user.getPassword(), user.getUserId() ); realUser.setPassword( user.getPassword() ); } - updateUser( realUser.getUsername(), realUser ); + updateUser( realUser.getUserId(), realUser ); return ActionStatus.SUCCESS; } @@ -390,7 +397,7 @@ public class DefaultUserService { 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.setEmail( user.getEmail() ); rawUser.setValidated( user.isValidated() ); @@ -520,9 +527,9 @@ public class DefaultUserService log.warn( "Admin user exists already" ); return ActionStatus.FAIL; } - log.debug("Creating admin admin user '{}'", adminUser.getUsername()); - if (!RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME.equals(adminUser.getUsername())) { - log.error("Wrong admin user name {}", adminUser.getUsername()); + log.debug("Creating admin admin user '{}'", adminUser.getUserId()); + if (!RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME.equals(adminUser.getUserId())) { + log.error("Wrong admin user name {}", adminUser.getUserId()); throw new RedbackServiceException(new ErrorMessage("admin.wrongUsername")); } @@ -657,13 +664,13 @@ public class DefaultUserService // NOTE: Do not perform Password Rules Validation Here. - if ( userManager.userExists( user.getUsername() ) ) + if ( userManager.userExists( user.getUserId() ) ) { 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.setValidated( false ); u.setLocked( false ); @@ -904,13 +911,13 @@ public class DefaultUserService { RedbackServiceException redbackServiceException = new RedbackServiceException( "issues during validating user" ); - if ( StringUtils.isEmpty( user.getUsername() ) ) + if ( StringUtils.isEmpty( user.getUserId() ) ) { redbackServiceException.addErrorMessage( new ErrorMessage( "username.required", null ) ); } else { - if ( !user.getUsername().matches( VALID_USERNAME_CHARS ) ) + if ( !user.getUserId().matches( VALID_USERNAME_CHARS ) ) { redbackServiceException.addErrorMessage( new ErrorMessage( "username.invalid.characters", null ) ); } @@ -955,7 +962,7 @@ public class DefaultUserService try { 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() ); @@ -995,7 +1002,7 @@ public class DefaultUserService if ( user != null ) { user.setLocked( false ); - updateUser( user.getUsername(), user ); + updateUser( user.getUserId(), user ); return ActionStatus.SUCCESS; } return ActionStatus.FAIL; @@ -1009,21 +1016,21 @@ public class DefaultUserService if ( user != null ) { user.setLocked( true ); - updateUser( user.getUsername(), user ); + updateUser( user.getUserId(), user ); return ActionStatus.SUCCESS; } return ActionStatus.FAIL; } @Override - public PasswordStatus passwordChangeRequired( String username ) + public PasswordStatus passwordChangeRequired( String userId ) throws RedbackServiceException { - User user = getUser( username ); + User user = getUser( userId ); if ( user == null ) { user.setPasswordChangeRequired( true ); - updateUser( user.getUsername(), user ); + updateUser( user.getUserId(), user ); return new PasswordStatus( true ); } return new PasswordStatus( false ); diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/PagingHelper.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/PagingHelper.java new file mode 100644 index 00000000..1fa2756f --- /dev/null +++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/PagingHelper.java @@ -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 + */ +public class PagingHelper +{ + public static PagedResult getResultFromList( int offset, int limit, List 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 ); + } + + +} diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/AuthenticationServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/AuthenticationServiceTest.java index f92dd587..b6e99e6a 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/AuthenticationServiceTest.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/AuthenticationServiceTest.java @@ -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.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.services.RedbackServiceException; import org.apache.archiva.redback.rest.services.BaseSetup; import org.apache.archiva.redback.users.User; -import org.apache.archiva.redback.users.UserManager; import org.apache.archiva.redback.users.UserManagerException; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterEach; @@ -64,7 +63,7 @@ public class AuthenticationServiceTest public void loginAdmin() throws Exception { - RequestTokenRequest request = new RequestTokenRequest( RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME, + TokenRequest request = new TokenRequest( RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME, BaseSetup.getAdminPwd() ); request.setGrantType( GrantType.AUTHORIZATION_CODE ); @@ -103,7 +102,7 @@ public class AuthenticationServiceTest // START SNIPPET: create-user User user = addUser( "toto", "foo123", "toto the king", "toto@toto.fr" ); // END SNIPPET: create-user - RequestTokenRequest request = new RequestTokenRequest( "toto", "foo123" ); + TokenRequest request = new TokenRequest( "toto", "foo123" ); request.setGrantType( GrantType.AUTHORIZATION_CODE ); TokenResponse result = getLoginServiceV2( "" ).logIn( request ); assertNotNull( result ); diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java index 0828e865..2b5f8ef2 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java @@ -25,7 +25,6 @@ import org.apache.archiva.redback.rest.api.services.v2.GroupService; import org.apache.commons.lang3.StringUtils; import org.apache.cxf.jaxrs.client.JAXRSClientFactory; 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.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -46,7 +45,6 @@ import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriInfo; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -298,7 +296,7 @@ public class GroupServiceTest { GroupService service = getGroupService( authorizationHeader ); - List allGroups = service.getGroups( Long.valueOf( 0 ), Long.valueOf( Long.MAX_VALUE ) ).getData( ).stream( ).map( group -> group.getName( ) ).collect( Collectors.toList( ) ); + List allGroups = service.getGroups( 0 , Integer.MAX_VALUE ).getData( ).stream( ).map( group -> group.getName( ) ).collect( Collectors.toList( ) ); assertNotNull( allGroups ); assertEquals( 3, allGroups.size( ) ); diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeUserServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeUserServiceTest.java new file mode 100644 index 00000000..9fecfd99 --- /dev/null +++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeUserServiceTest.java @@ -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 + */ +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 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 ) ); +// } + +} diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/UserServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/UserServiceTest.java index ee8341c3..5cacbc7f 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/UserServiceTest.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/UserServiceTest.java @@ -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.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.PingResult; -import org.apache.archiva.redback.rest.api.model.RequestTokenRequest; +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.ResetPasswordRequest; 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.UserRegistrationRequest; +import org.apache.archiva.redback.rest.api.model.v2.User; +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; import org.apache.archiva.redback.rest.services.mock.EmailMessage; @@ -121,9 +122,9 @@ public class UserServiceTest { String adminHeader = getAdminAuthzHeader( ); UserService userService = getUserService( adminHeader ); - List users = userService.getUsers( ); + PagedResult users = userService.getUsers( 0, Integer.MAX_VALUE ); assertNotNull( users ); - assertFalse( users.isEmpty( ) ); + assertFalse( users.getData().isEmpty( ) ); } @Test @@ -134,7 +135,7 @@ public class UserServiceTest assertThrows( ForbiddenException.class, ( ) -> { try { - userService.getUsers( ); + userService.getUsers( 0, Integer.MAX_VALUE); } catch ( ForbiddenException e ) { @@ -199,11 +200,11 @@ public class UserServiceTest UserService service = getUserService( getAdminAuthzHeader( ) ); User u = new User( ); u.setFullName( "the toto" ); - u.setUsername( "toto" ); + u.setUserId( "toto" ); u.setEmail( "toto@toto.fr" ); u.setPassword( "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 ); @@ -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 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 public void registerNoUrl( ) throws Exception { 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 = 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, null ) ).getKey( ); + + assertNotEquals( "-1", key ); + List emailMessages = assertService.getEmailMessageSended( ); assertEquals( 1, emailMessages.size( ) ); @@ -322,11 +387,11 @@ public class UserServiceTest UserService service = getUserService( getAdminAuthzHeader( ) ); User u = new User( ); u.setFullName( "the toto" ); - u.setUsername( "toto" ); + u.setUserId( "toto" ); u.setEmail( "toto@toto.fr" ); u.setPassword( "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 ); @@ -354,7 +419,7 @@ public class UserServiceTest // 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( ); assertEquals( 2, emailMessages.size( ) ); @@ -433,7 +498,7 @@ public class UserServiceTest { User u = new User( ); u.setFullName( "the toto" ); - u.setUsername( "toto" ); + u.setUserId( "toto" ); u.setEmail( "toto@toto.fr" ); u.setPassword( "toto123" ); u.setConfirmPassword( "toto123" ); @@ -444,7 +509,7 @@ public class UserServiceTest u.setEmail( "toto@titi.fr" ); u.setPassword( "toto1234" ); u.setPreviousPassword( "toto123" ); - getUserService( getUserAuthzHeader( "toto" ) ).updateMe( u.getUsername(), u ); + getUserService( getUserAuthzHeader( "toto" ) ).updateMe( u. getUserId(), u ); u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" ); assertEquals( "the toto123", u.getFullName( ) ); @@ -454,7 +519,7 @@ public class UserServiceTest u.setEmail( "toto@tititi.fr" ); u.setPassword( "toto12345" ); u.setPreviousPassword( "toto1234" ); - getUserService( getUserAuthzHeader( "toto" )) .updateMe(u.getUsername(), u ); + getUserService( getUserAuthzHeader( "toto" )) .updateMe(u.getUserId(), u ); u = getUserService( getAdminAuthzHeader( ) ).getUser( "toto" ); assertEquals( "the toto1234", u.getFullName( ) ); @@ -484,7 +549,7 @@ public class UserServiceTest assertNotNull( user ); assertEquals( "toto the king", user.getFullName( ) ); 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( ); userService.lockUser( "toto" ); diff --git a/redback-users/redback-users-api/src/main/java/org/apache/archiva/redback/users/User.java b/redback-users/redback-users-api/src/main/java/org/apache/archiva/redback/users/User.java index e615101d..392e906d 100644 --- a/redback-users/redback-users-api/src/main/java/org/apache/archiva/redback/users/User.java +++ b/redback-users/redback-users-api/src/main/java/org/apache/archiva/redback/users/User.java @@ -298,5 +298,6 @@ public interface User * @return userManager id */ String getUserManagerId(); + }