Refactoring of role API and new Role V2 REST service

This commit is contained in:
Martin Stockhammer 2020-11-24 21:28:42 +01:00
parent 04e2abdce9
commit de23f72bf1
44 changed files with 3173 additions and 378 deletions

View File

@ -2,6 +2,17 @@ Archiva Redback - Documentation
===============================
:toc:
== Update Information for 3.0
=== Database Schema Changes
==== org.apache.archiva.redback.rbac.Role
New fields:
id, modelId, isTemplateInstance, resource
Primary key changed from name to combined key id,name
== How to build and publish the pages for the archiva web content

View File

@ -66,7 +66,6 @@ public interface LdapRoleMapper
boolean hasRole( DirContext context, String role )
throws MappingException;
/**
* @return the base dn which contains all ldap groups
*/

View File

@ -23,7 +23,7 @@ package org.apache.archiva.redback.rest.api;
*/
public interface Constants
{
String DEFAULT_PAGE_LIMIT = "1000";
String DEFAULT_PAGE_LIMIT = "100";
}

View File

@ -40,10 +40,19 @@ public interface MessageKeys
String ERR_USER_ADMIN_EXISTS = "rb.user.admin.exists";
String ERR_USER_ADMIN_BAD_NAME = "rb.user.admin.badname";
String ERR_USER_NOT_FOUND = "rb.user.not_found";
String ERR_USER_BAD_PASSWORD = "rb.user.bad.password";
String ERR_PASSWORD_VIOLATION = "rb.user.password_violation";
String ERR_LDAP_GENERIC = "rb.ldap.error";
String ERR_ROLE_MAPPING = "rb.role.mapping.error";
String ERR_ROLE_MAPPING_NOT_FOUND = "rb.role.mapping.not_found";
String ERR_ROLE_NOT_FOUND = "rb.role.not_found";
// A template instance not found. With arguments templateId, resource
String ERR_ROLE_INSTANCE_NOT_FOUND = "rb.role.instance.not_found";
String ERR_ROLE_EXISTS = "rb.role.exists";
// A template instance exists. With arguments templateId, resource
String ERR_ROLE_INSTANCE_EXISTS = "rb.role.instance.exists";
String ERR_AUTH_BAD_CODE = "rb.auth.bad_authorization_code";
String ERR_AUTH_INVALID_CREDENTIALS = "rb.auth.invalid_credentials";
String ERR_AUTH_FAIL_MSG = "rb.auth.fail";
@ -52,9 +61,11 @@ public interface MessageKeys
String ERR_AUTH_UNSUPPORTED_GRANT_TYPE = "rb.auth.unsupported_grant";
String ERR_AUTH_INVALID_TOKEN = "rb.auth.invalid_token";
String ERR_AUTH_UNAUTHORIZED_REQUEST = "rb.auth.unauthorized_request";
String ERR_PASSWD_RESET_FAILED = "rb.passwd.reset.fail";
String ERR_USER_BAD_PASSWORD = "rb.user.bad.password";
String ERR_REGISTRATION_KEY_INVALID = "rb.registration.key.invalid";
String ERR_REGISTRATION_USER_VALIDATED = "rb.registration.user.validated";
String ERR_REGISTRATION_ROLE_ASSIGNMENT_FAILED = "rb.registration.role.assignment.failed";
}

View File

@ -0,0 +1,89 @@
package org.apache.archiva.redback.rest.api.model.v2;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
/**
* @author Olivier Lamy
*/
@XmlRootElement( name = "application" )
@Schema(name="Application", description = "A single application that is used for defining roles")
public class Application
implements Serializable
{
private static final long serialVersionUID = -4738856943947960583L;
private String version;
private String id;
private String description;
private String longDescription;
public Application()
{
// no op
}
@Schema(description = "The application version. Used to separate different sets of roles.")
public String getVersion()
{
return version;
}
public void setVersion( String version )
{
this.version = version;
}
@Schema(description = "The identifier of the application")
public String getId()
{
return id;
}
public void setId( String id )
{
this.id = id;
}
@Schema(description = "A short description.")
public String getDescription()
{
return description;
}
public void setDescription( String description )
{
this.description = description;
}
@Schema(description = "May be a longer explanation, of the application purpose and its defined roles.")
public String getLongDescription()
{
return longDescription;
}
public void setLongDescription( String longDescription )
{
this.longDescription = longDescription;
}
}

View File

@ -0,0 +1,80 @@
package org.apache.archiva.redback.rest.api.model.v2;/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
/**
* Information about a group.
*
* @since 3.0
* @author Martin Stockhammer <martin_s@apache.org>
*/
@Schema( name = "Group", description = "Group information" )
public class BaseGroupInfo implements Serializable
{
private static final long serialVersionUID = 2945927911204165322L;
private String id;
private String groupName;
private String description = "";
public BaseGroupInfo( )
{
}
public BaseGroupInfo( String id, String groupName )
{
this.id = id;
this.groupName = groupName;
}
@Schema(description = "The name of the group")
public String getGroupName( )
{
return groupName;
}
public void setGroupName( String groupName )
{
this.groupName = groupName;
}
@Schema( description = "The unique identifier of the group" )
public String getId( )
{
return id;
}
public void setId( String id )
{
this.id = id;
}
@Schema( description = "A description of the group" )
public String getDescription( )
{
return description;
}
public void setDescription( String description )
{
this.description = description;
}
}

View File

@ -0,0 +1,262 @@
package org.apache.archiva.redback.rest.api.model.v2;/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.archiva.redback.rbac.Role;
import org.apache.archiva.redback.role.model.ModelRole;
import javax.xml.bind.annotation.XmlTransient;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Basic role information. This class contains only the standard attributes used for displaying a role.
*
* @author Martin Stockhammer <martin_s@apache.org>
*/
@Schema(name="BaseRoleInfo", description = "Basic role attributes")
public class BaseRoleInfo implements Serializable
{
private static final long serialVersionUID = -6725489773301720068L;
protected String id;
protected String name;
protected String description = "";
protected boolean permanent = false;
protected String modelId = "";
protected String resource = "";
protected boolean isTemplateInstance = false;
protected boolean assignable = true;
private String applicationId = "";
private boolean isChild = false;
protected boolean assigned = false;
private List<BaseRoleInfo> children = new ArrayList<>( 0 );
public BaseRoleInfo() {
}
public static BaseRoleInfo ofName(String name) {
BaseRoleInfo info = new BaseRoleInfo( );
info.setName( name );
return info;
}
public static BaseRoleInfo ofId(String id) {
BaseRoleInfo info = new BaseRoleInfo( );
info.setId( id );
return info;
}
public static BaseRoleInfo of(Role rbacRole) {
return of( rbacRole, new BaseRoleInfo( ) );
}
public static <T extends BaseRoleInfo> T of( Role rbacRole, T role ) {
role.id = rbacRole.getId( );
role.name = rbacRole.getName( );
role.description = rbacRole.getDescription( ) == null ?"": rbacRole.getDescription();
role.permanent = rbacRole.isPermanent( );
role.modelId = rbacRole.getModelId( );
role.resource = rbacRole.getResource( );
role.isTemplateInstance = rbacRole.isTemplateInstance( );
role.assignable = rbacRole.isAssignable( );
return role;
}
@Schema(description = "The role name")
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
@Schema( description = "A description of the role" )
public String getDescription( )
{
return description;
}
public void setDescription( String description )
{
this.description = description;
}
@Schema( description = "True, if this role cannot be deleted.")
public boolean isPermanent()
{
return permanent;
}
public void setPermanent( boolean permanent )
{
this.permanent = permanent;
}
@Schema(description = "The identifier of this role")
public String getId( )
{
return id;
}
public void setId( String id )
{
this.id = id;
}
@Schema(description = "The model this role is derived from")
public String getModelId( )
{
return modelId;
}
public void setModelId( String modelId )
{
this.modelId = modelId;
}
@Schema(description = "The resource this model is built for, if it is built by a template.")
public String getResource( )
{
return resource;
}
public void setResource( String resource )
{
this.resource = resource;
}
@Schema(description = "True, if this is a instance of a role template")
public boolean isTemplateInstance( )
{
return isTemplateInstance;
}
public void setTemplateInstance( boolean templateInstance )
{
isTemplateInstance = templateInstance;
}
@Schema(description = "Roles that are children of this role. This field may not be populated, depending on the REST method call.")
public List<BaseRoleInfo> getChildren( )
{
return children;
}
public void setChildren( List<BaseRoleInfo> children )
{
this.children = children;
}
public void addChild(BaseRoleInfo child) {
if (!this.children.contains( child ))
{
this.children.add( child );
}
}
@Schema(description = "This attribute is only set at specific REST calls, that return roles, that are either assigned or not assigned to a given user.")
public boolean isAssigned( )
{
return assigned;
}
public void setAssigned( boolean assigned )
{
this.assigned = assigned;
}
@Override
public boolean equals( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass( ) != o.getClass( ) ) return false;
BaseRoleInfo that = (BaseRoleInfo) o;
return id.equals( that.id );
}
@Schema( description = "If true, the role is assignable to users or roles. Otherwise, it can be used only as parent role.")
public boolean isAssignable()
{
return assignable;
}
public void setAssignable( boolean assignable )
{
this.assignable = assignable;
}
@Override
public int hashCode( )
{
return id.hashCode( );
}
@Override
public String toString( )
{
final StringBuilder sb = new StringBuilder( "BaseRoleInfo{" );
sb.append( "id='" ).append( id ).append( '\'' );
sb.append( ", name='" ).append( name ).append( '\'' );
sb.append( ", description='" ).append( description ).append( '\'' );
sb.append( ", permanent=" ).append( permanent );
sb.append( ", modelId='" ).append( modelId ).append( '\'' );
sb.append( ", resource='" ).append( resource ).append( '\'' );
sb.append( ", isTemplateInstance=" ).append( isTemplateInstance );
sb.append( '}' );
return sb.toString( );
}
@Schema(description = "Application id, where this role belongs to. This is only filled by certain REST methods.")
public String getApplicationId( )
{
return applicationId;
}
public void setApplicationId( String applicationId )
{
this.applicationId = applicationId;
}
public boolean isChild( )
{
return isChild;
}
public void setChild( boolean child )
{
isChild = child;
}
@XmlTransient
public boolean isNotChild() {
return !isChild;
}
}

View File

@ -0,0 +1,67 @@
package org.apache.archiva.redback.rest.api.model.v2;/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlElement;
import java.io.Serializable;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@Schema( name = "BaseUserInfo", description = "Basic user information" )
public class BaseUserInfo implements Serializable
{
private static final long serialVersionUID = 4643187400578104895L;
protected String userId;
private String id;
public BaseUserInfo( )
{
}
public BaseUserInfo( String id , String userId )
{
this.userId = userId;
this.id = id;
}
@Schema( name = "user_id", description = "The user id" )
@XmlElement( name = "user_id" )
public String getUserId( )
{
return userId;
}
public void setUserId( String userId )
{
this.userId = userId;
}
@Schema( description = "User id that is unique over all user managers" )
public String getId( )
{
return id;
}
public void setId( String id )
{
this.id = id;
}
}

View File

@ -0,0 +1,104 @@
package org.apache.archiva.redback.rest.api.model.v2;/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* This class is used for role update. Contains only the role attributes, that can be updated.
*
* @author Martin Stockhammer <martin_s@apache.org>
*/
@Schema(name="Role",description="Role attributes that are used for updating a role")
public class Role implements Serializable
{
private static final long serialVersionUID = 3238571295658509062L;
protected String name;
protected String id;
protected String description;
protected boolean permanent = false;
/**
* The ids of all the assigned users.
*/
protected List<BaseUserInfo> assignedUsers = new ArrayList<>( 0 );
@Schema(description = "The role name")
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
@Schema( description = "A description of the role" )
public String getDescription( )
{
return description;
}
public void setDescription( String description )
{
this.description = description;
}
@Schema( description = "True, if this role cannot be deleted.")
public boolean isPermanent()
{
return permanent;
}
public void setPermanent( boolean permanent )
{
this.permanent = permanent;
}
@Schema(description = "The identifier of this role")
public String getId( )
{
return id;
}
public void setId( String id )
{
this.id = id;
}
@Schema( description = "List of user ids that are assigned to this role.")
public List<BaseUserInfo> getAssignedUsers( )
{
return assignedUsers;
}
public void setAssignedUsers( List<BaseUserInfo> assignedUsers )
{
this.assignedUsers = assignedUsers;
}
public void addAssignedUser( BaseUserInfo id) {
this.assignedUsers.add( id );
}
}

View File

@ -0,0 +1,182 @@
package org.apache.archiva.redback.rest.api.model.v2;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.archiva.redback.rbac.Role;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Result object for role information.
*
* @author Martin Stockhammer
* @since 3.0
*/
@XmlRootElement( name = "role" )
@Schema(name="RoleInfo",description = "Information about role")
public class RoleInfo extends BaseRoleInfo
implements Serializable
{
private static final long serialVersionUID = -3506615158923923845L;
/**
* Field childRoleNames
*/
private List<String> childRoleIds = new ArrayList<>(0);
/**
* Field permissions
*/
private List<Permission> permissions = new ArrayList<>(0);
/**
* The names of all parent roles
*/
private List<String> parentRoleIds = new ArrayList<>(0);
/**
* The ids of all the assigned users.
*/
protected List<BaseUserInfo> assignedUsers = new ArrayList<>( 0 );
@Schema( description = "List of user ids that are assigned to this role.")
public List<BaseUserInfo> getAssignedUsers( )
{
return assignedUsers;
}
public void setAssignedUsers( List<BaseUserInfo> assignedUsers )
{
this.assignedUsers = assignedUsers;
}
public void addAssignedUser( BaseUserInfo id) {
this.assignedUsers.add( id );
}
public RoleInfo()
{
// no op
}
public static RoleInfo of( Role rbacRole) {
RoleInfo role = BaseRoleInfo.of( rbacRole, new RoleInfo( ) );
return role;
}
@XmlTransient
@Override
public List<BaseRoleInfo> getChildren( )
{
return super.getChildren( );
}
@Schema( description = "List of names of children roles")
public List<String> getChildRoleIds()
{
return childRoleIds;
}
public void setChildRoleIds( List<String> childRoleIds )
{
this.childRoleIds = childRoleIds;
}
@Schema( description = "List of permissions assigned to this role.")
public List<Permission> getPermissions()
{
return permissions;
}
public void setPermissions( List<Permission> permissions )
{
this.permissions = permissions;
}
@Schema(description = "List of names of roles that are parents of this role.")
public List<String> getParentRoleIds()
{
return parentRoleIds;
}
public void setParentRoleIds( List<String> parentRoleIds )
{
this.parentRoleIds = parentRoleIds;
}
@Override
public boolean isChild( )
{
return getParentRoleIds( ).size( ) > 0;
}
@Override
public int hashCode()
{
return getName( ) != null ? getName( ).hashCode() : 0;
}
@Override
public String toString( )
{
final StringBuilder sb = new StringBuilder( "RoleInfo{" );
sb.append( "name='" ).append( getName( ) ).append( '\'' );
sb.append( ", id='" ).append( getId( ) ).append( '\'' );
sb.append( ", description='" ).append( getDescription( ) ).append( '\'' );
sb.append( ", assignable=" ).append( assignable );
sb.append( ", childRoleNames=" ).append( childRoleIds );
sb.append( ", permissions=" ).append( permissions );
sb.append( ", parentRoleNames=" ).append( parentRoleIds );
sb.append( ", assignedUsers=" ).append( assignedUsers );
sb.append( ", permanent=" ).append( isPermanent( ) );
sb.append( ", modelId='" ).append( modelId ).append( '\'' );
sb.append( ", resource='" ).append( resource ).append( '\'' );
sb.append( ", isTemplateInstance=" ).append( isTemplateInstance );
sb.append( '}' );
return sb.toString( );
}
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( o == null || getClass() != o.getClass() )
{
return false;
}
RoleInfo role = (RoleInfo) o;
return Objects.equals( getName( ), role.getName( ) );
}
}

View File

@ -0,0 +1,74 @@
package org.apache.archiva.redback.rest.api.model.v2;/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* Information about roles of a application.
*
* @author Martin Stockhammer <martin_s@apache.org>
*/
@Schema(name="RoleTree",description = "Tree of roles defined. The root roles have no parent. Each role may have children recursively.")
public class RoleTree implements Serializable
{
private static final long serialVersionUID = 6893397477073625729L;
String userId;
Map<String, Application> applications;
List<BaseRoleInfo> rootRoles;
@Schema(description = "The user id for which the assigned flags are set on the roles.")
public String getUserId( )
{
return userId;
}
public void setUserId( String userId )
{
this.userId = userId;
}
@Schema(description = "Information about the applications that define roles. The keys of the map are the application ids.")
public Map<String, Application> getApplications( )
{
return applications;
}
public void setApplications( Map<String, Application> applications )
{
this.applications = applications;
}
@Schema(description = "The list of roles directly assigned to this application. Roles may contain children roles.")
public List<BaseRoleInfo> getRootRoles( )
{
return rootRoles;
}
public void setRootRoles( List<BaseRoleInfo> rootRoles )
{
this.rootRoles = rootRoles;
}
}

View File

@ -2,13 +2,11 @@ package org.apache.archiva.redback.rest.api.model.v2;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.List;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@ -31,14 +29,11 @@ import java.util.List;
@XmlRootElement( name = "user" )
@Schema(name="User", description = "User information data")
public class UserInfo
public class UserInfo extends BaseUserInfo
implements Serializable
{
private static final long serialVersionUID = 822423853981984867L;
private String id;
private String userId;
private String fullName;
@ -125,18 +120,6 @@ public class UserInfo
}
@Schema( name = "user_id", description = "The user id" )
@XmlElement( name = "user_id" )
public String getUserId( )
{
return userId;
}
public void setUserId( String userId )
{
this.userId = userId;
}
@Schema( description = "The full name of the user" )
public String getFullName( )
{
@ -282,22 +265,11 @@ public class UserInfo
this.validationToken = validationToken;
}
@Schema( description = "User id that is unique over all user managers")
public String getId( )
{
return id;
}
public void setId( String id )
{
this.id = id;
}
@Override
public String toString()
{
return "User{" +
"username='" + userId + '\'' +
"username='" + getUserId( ) + '\'' +
", fullName='" + fullName + '\'' +
", email='" + email + '\'' +
", validated=" + validated +
@ -328,7 +300,7 @@ public class UserInfo
UserInfo user = (UserInfo) o;
if ( !userId.equals( user.userId ) )
if ( !getUserId( ).equals( user.getUserId( ) ) )
{
return false;
}
@ -339,6 +311,6 @@ public class UserInfo
@Override
public int hashCode()
{
return userId.hashCode();
return getUserId( ).hashCode();
}
}

View File

@ -20,6 +20,7 @@ package org.apache.archiva.redback.rest.api.services.v2;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@ -31,7 +32,6 @@ import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.Application;
import org.apache.archiva.redback.rest.api.model.ApplicationRoles;
import org.apache.archiva.redback.rest.api.model.RedbackRestError;
import org.apache.archiva.redback.rest.api.model.v2.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.Role;
import org.apache.archiva.redback.rest.api.model.User;
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
@ -40,14 +40,19 @@ import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
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.HEAD;
import javax.ws.rs.PATCH;
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 javax.ws.rs.core.Response;
import java.util.List;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@ -60,15 +65,12 @@ import static org.apache.archiva.redback.rest.api.Constants.DEFAULT_PAGE_LIMIT;
@Tag(name = "v2")
@Tag(name = "v2/Roles")
@SecurityRequirement(name = "BearerAuth")
public interface RoleManagementService
public interface RoleService
{
/**
* @since 2.0
*/
@Path( "" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
@Operation( summary = "Returns all roles defined. The result is paged.",
parameters = {
@ -99,47 +101,181 @@ public interface RoleManagementService
@QueryParam("order") @DefaultValue( "asc" ) String order)
throws RedbackServiceException;
@Path( "createTemplatedRole" )
@Path( "{roleId}" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus createTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
@Operation( summary = "Returns information about a specific role. Use HTTP HEAD method for checking, if the resource exists.",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION
)
},
responses = {
@ApiResponse( responseCode = "200",
description = "If role was found in the database",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RoleInfo.class))
),
@ApiResponse( responseCode = "404", description = "Role does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class ))
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
RoleInfo getRole( @PathParam( "roleId" ) String roleId )
throws RedbackServiceException;
@Path( "{roleId}" )
@HEAD
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
@Operation( summary = "Returns information about a specific role. Use HTTP HEAD method for checking, if the resource exists.",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION
)
},
responses = {
@ApiResponse( responseCode = "200",
description = "If role was found in the database"
),
@ApiResponse( responseCode = "404", description = "Role does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class ))
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
Response checkRole( @PathParam( "roleId" ) String roleId )
throws RedbackServiceException;
/**
* Moves a templated role from one resource to another resource
* @TODO: Not sure, if it makes sense to keep the child template at the source. Shouldn't we move the childs too?
*
* @param templateId the template identifier
* @param oldResource the resource of the current role
* @param newResource the resource of the new role
*/
@Path( "template/{templateId}/{oldResource}/moveto/{newResource}" )
@POST
@Produces( {APPLICATION_JSON} )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
@Operation( summary = "Moves a templated role from one resource to another resource. If the template has child templates," +
" then child instances will be created on for the destination resource. But the child instances on the source are not deleted.",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION
)
},
responses = {
@ApiResponse( responseCode = "201",
description = "If user creation was successful",
headers = {
@Header( name="Location", description = "The URL of the moved role", schema = @Schema(type="string"))
},
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RoleInfo.class))
),
@ApiResponse( responseCode = "404", description = "The source role does not exist" ),
@ApiResponse( responseCode = "303", description = "The destination role exists already" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission to move the role.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
RoleInfo moveTemplatedRole( @PathParam( "templateId" ) String templateId, @PathParam( "oldResource" ) String oldResource,
@PathParam( "newResource" ) String newResource )
throws RedbackServiceException;
@Path( "template/{templateId}/{resource}" )
@HEAD
@Produces( { APPLICATION_JSON} )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
@Operation( summary = "Checks, if a instance of the role template exists for the given resource",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION
)
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the role instance exists"
),
@ApiResponse( responseCode = "404", description = "Role does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class ))
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
Response checkTemplateRole( @PathParam( "templateId" ) String templateId,
@PathParam( "resource" ) String resource )
throws RedbackServiceException;
@Path( "template/{templateId}/{resource}" )
@PUT
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
@Operation( summary = "Creates a role instance from a template for the given resource",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION
)
},
responses = {
@ApiResponse( responseCode = "201",
description = "If user creation was successful",
headers = {
@Header( name = "Location", description = "The URL of the created role", schema = @Schema( type = "string" ) )
},
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RoleInfo.class ) )
),
@ApiResponse( responseCode = "200",
description = "If the role instance existed before and was updated",
headers = {
@Header( name = "Location", description = "The URL of the updated role", schema = @Schema( type = "string" ) )
},
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RoleInfo.class ) )
),
@ApiResponse( responseCode = "404", description = "The template does not exist" ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role creation.",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = RedbackRestError.class ) ) )
}
)
RoleInfo createTemplatedRole( @PathParam( "templateId" ) String templateId,
@PathParam( "resource" ) String resource )
throws RedbackServiceException;
/**
* removes a role corresponding to the role Id that was manufactured with the given resource
*
* Removes a role corresponding to the role Id that was manufactured with the given resource
* it also removes any user assignments for that role
*
* @param templateId
* @param resource
*/
@Path( "removeTemplatedRole" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Path( "template/{templateId}/{resource}" )
@DELETE
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus removeTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
throws RedbackServiceException;
/**
* allows for a role coming from a template to be renamed effectively swapping out the bits of it that
* were labeled with the oldResource with the newResource
*
* it also manages any user assignments for that role
*
* @param templateId
* @param oldResource
* @param newResource
*/
@Path( "updateRole" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus updateRole( @QueryParam( "templateId" ) String templateId, @QueryParam( "oldResource" ) String oldResource,
@QueryParam( "newResource" ) String newResource )
@Operation( summary = "Deletes a role template instance",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If role deletion was successful"
),
@ApiResponse( responseCode = "404", description = "Role does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for deletion.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
Response removeTemplatedRole( @PathParam( "templateId" ) String templateId,
@PathParam( "resource" ) String resource )
throws RedbackServiceException;
@ -147,27 +283,27 @@ public interface RoleManagementService
* Assigns the role indicated by the roleId to the given principal
*
* @param roleId
* @param principal
* @param userId
*/
@Path( "assignRole" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Path( "{roleId}/assign/{userId}" )
@PUT
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus assignRole( @QueryParam( "roleId" ) String roleId, @QueryParam( "principal" ) String principal )
throws RedbackServiceException;
/**
* Assigns the role indicated by the roleName to the given principal
*
* @param roleName
* @param principal
* @throws RedbackServiceException
*/
@Path( "assignRoleByName" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus assignRoleByName( @QueryParam( "roleName" ) String roleName, @QueryParam( "principal" ) String principal )
@Operation( summary = "Assigns a role to a given user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the role was assigned"
),
@ApiResponse( responseCode = "404", description = "Role does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role assignment.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
RoleInfo assignRole( @PathParam( "roleId" ) String roleId, @PathParam( "userId" ) String userId )
throws RedbackServiceException;
/**
@ -179,11 +315,25 @@ public interface RoleManagementService
* @param resource
* @param principal
*/
@Path( "assignTemplatedRole" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Path( "template/{templateId}/{resource}/assign/{userId}" )
@POST
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus assignTemplatedRole( @QueryParam( "templateId" ) String templateId,
@Operation( summary = "Assigns a template role instance to a given user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the role instance was assigned"
),
@ApiResponse( responseCode = "404", description = "Role instance does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role assignment.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
RoleInfo assignTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource,
@QueryParam( "principal" ) String principal )
throws RedbackServiceException;
@ -195,161 +345,53 @@ public interface RoleManagementService
* @param principal
* @throws RedbackServiceException
*/
@Path( "unassignRole" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Path( "{roleId}/{userId}" )
@DELETE
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus unassignRole( @QueryParam( "roleId" ) String roleId, @QueryParam( "principal" ) String principal )
@Operation( summary = "Removes a role assignment for the given role and user",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the role assignment was removed"
),
@ApiResponse( responseCode = "404", description = "Role instance does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role assignment.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
RoleInfo unassignRole( @QueryParam( "roleId" ) String roleId, @QueryParam( "principal" ) String principal )
throws RedbackServiceException;
/**
* Unassigns the role indicated by the role name from the given principal
* Updates a role. Attributes that are empty or null will be ignored.
*
* @param roleName
* @param principal
* @throws RedbackServiceException
* @since 3.0
*/
@Path( "unassignRoleByName" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@Path( "{roleId}" )
@PATCH
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus unassignRoleByName( @QueryParam( "roleName" ) String roleName, @QueryParam( "principal" ) String principal )
@Operation( summary = "Creates or updates the given role",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the update was successful"
),
@ApiResponse( responseCode = "404", description = "Role does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role assignment.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
RoleInfo updateRole( @QueryParam("roleId") String roleId, Role role )
throws RedbackServiceException;
/**
* true of a role exists with the given roleId
*
* @param roleId
* @return
* @throws RedbackServiceException
*/
@Path( "roleExists" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
AvailabilityStatus roleExists( @QueryParam( "roleId" ) String roleId )
throws RedbackServiceException;
/**
* true of a role exists with the given roleId
*
* @param templateId
* @param resource
* @return
* @throws RedbackServiceException
*/
@Path( "templatedRoleExists" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
AvailabilityStatus templatedRoleExists( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
throws RedbackServiceException;
/**
* Check a role template is complete in the RBAC store.
*
* @param templateId the templated role
* @param resource the resource to verify
* @throws RedbackServiceException
*/
@Path( "verifyTemplatedRole" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
VerificationStatus verifyTemplatedRole( @QueryParam( "templateId" ) String templateId,
@QueryParam( "resource" ) String resource )
throws RedbackServiceException;
/**
* @since 1.4
*/
@Path( "getEffectivelyAssignedRoles/{username}" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
List<Role> getEffectivelyAssignedRoles( @PathParam( "username" ) String username )
throws RedbackServiceException;
/**
* @since 2.0
*/
@Path( "detailledAllRoles" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
List<Role> getDetailedAllRoles()
throws RedbackServiceException;
/**
* @since 2.0
*/
@Path( "getApplications/{username}" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
List<Application> getApplications( @PathParam( "username" ) String username )
throws RedbackServiceException;
/**
* @since 2.0
*/
@Path( "getRole/{roleName}" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
Role getRole( @PathParam( "roleName" ) String roleName )
throws RedbackServiceException;
/**
* @since 2.0
*/
@Path( "updateRoleDescription" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus updateRoleDescription( @QueryParam( "roleName" ) String roleName,
@QueryParam( "roleDescription" ) String description )
throws RedbackServiceException;
/**
* update users assigned to a role
* @since 2.0
*/
@Path( "updateRoleUsers" )
@POST
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus updateRoleUsers( Role role )
throws RedbackServiceException;
/**
* @since 2.0
*/
@Path( "getApplicationRoles/{username}" )
@GET
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
List<ApplicationRoles> getApplicationRoles( @PathParam( "username" ) String username )
throws RedbackServiceException;
/**
* update roles assigned to a user
* @since 2.0
*/
@Path( "updateUserRoles" )
@POST
@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@Consumes( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
ActionStatus updateUserRoles( User user )
throws RedbackServiceException;
}

View File

@ -31,12 +31,15 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.redback.authorization.RedbackAuthorization;
import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.Application;
import org.apache.archiva.redback.rest.api.model.RedbackRestError;
import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.RoleTree;
import org.apache.archiva.redback.rest.api.model.v2.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.v2.RegistrationKey;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.SelfUserData;
import org.apache.archiva.redback.rest.api.model.v2.User;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
@ -54,6 +57,7 @@ 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;
@ -594,4 +598,59 @@ public interface UserService
)
VerificationStatus validateUserRegistration( @PathParam( "userId" ) String userId, @PathParam( "key" ) String key )
throws RedbackServiceException;
/**
* Returns all roles for a given user id. Recurses all child roles.
*
* @since 3.0
*/
@Path( "{userId}/roles" )
@GET
@Produces( { MediaType.APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
@Operation( summary = "Returns a list of all roles effectively assigned to the given user.",
responses = {
@ApiResponse( responseCode = "200",
description = "The list of roles assigned to the given user",
content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(schema =
@Schema(implementation = org.apache.archiva.redback.rest.api.model.v2.RoleInfo.class )))
),
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for retrieving the information.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
List<RoleInfo> getEffectivelyAssignedRoles( @PathParam( "userId" ) String username )
throws RedbackServiceException;
/**
* @since 3.0
*/
@Path( "{userId}/roletree" )
@GET
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
@Operation( summary = "Returns a list of all roles that are assigned, or can be assigned to the given user. "+
"This method sets the 'assigned' flag on all returned role objects.",
security = {
@SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
},
responses = {
@ApiResponse( responseCode = "200",
description = "The list of roles separated by application that are assigned or assignable for the given user",
content = @Content(mediaType = APPLICATION_JSON, array = @ArraySchema(schema =
@Schema(implementation = Application.class )))
),
@ApiResponse( responseCode = "404", description = "User does not exist",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
@ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for retrieving the information.",
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
RoleTree getRoleTree( @PathParam( "userId" ) String username )
throws RedbackServiceException;
}

View File

@ -29,7 +29,6 @@ import org.apache.archiva.redback.rbac.UserAssignment;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.Application;
import org.apache.archiva.redback.rest.api.model.ApplicationRoles;
import org.apache.archiva.redback.rest.api.model.v2.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.Role;
import org.apache.archiva.redback.rest.api.model.RoleTemplate;
@ -127,7 +126,7 @@ public class DefaultRoleManagementService
{
try
{
roleManager.updateRole( templateId, oldResource, newResource );
roleManager.moveTemplatedRole( templateId, oldResource, newResource );
}
catch ( RoleManagerException e )
{
@ -391,7 +390,7 @@ public class DefaultRoleManagementService
org.apache.archiva.redback.rbac.Role rbacRole = rbacManager.getRole( roleName );
Role role = new Role( rbacRole );
Map<String, ? extends org.apache.archiva.redback.rbac.Role> parentRoles = rbacManager.getParentRoles( rbacRole );
Map<String, ? extends org.apache.archiva.redback.rbac.Role> parentRoles = rbacManager.getParentRoleNames( rbacRole );
for ( String parentRoleName : parentRoles.keySet() )
{
role.getParentRoleNames().add( parentRoleName );

View File

@ -0,0 +1,145 @@
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.rbac.RBACManager;
import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.Role;
import org.apache.archiva.redback.rest.api.MessageKeys;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.v2.BaseUserInfo;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManager;
import org.apache.archiva.redback.users.UserManagerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Named;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class BaseRedbackService
{
private static final Logger log = LoggerFactory.getLogger( BaseRedbackService.class );
protected RBACManager rbacManager;
protected UserManager userManager;
public BaseRedbackService( @Named( value = "rbacManager#default" ) RBACManager rbacManager, @Named( value = "userManager#default" ) UserManager userManager )
{
this.rbacManager = rbacManager;
this.userManager = userManager;
}
protected RoleInfo getRoleInfo( org.apache.archiva.redback.rbac.Role rbacRole ) throws RedbackServiceException
{
try
{
RoleInfo role = RoleInfo.of( rbacRole );
role.setParentRoleIds( getParentRoles( rbacRole ) );
role.setChildRoleIds( getChildRoles( rbacRole ) );
role.setAssignedUsers( getAssignedUsersRecursive( rbacRole ) );
return role;
}
catch ( RbacManagerException e )
{
log.error( "Error while retrieving role information {}", e.getMessage( ), e );
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
protected List<String> getParentRoles( org.apache.archiva.redback.rbac.Role rbacRole ) throws RbacManagerException
{
return new ArrayList<>( rbacManager.getParentRoleIds( rbacRole ).keySet( ));
}
protected List<String> getChildRoles( Role rbacRole) throws RbacManagerException
{
return new ArrayList<>( rbacManager.getChildRoleIds( rbacRole ).keySet( ) );
}
protected List<BaseUserInfo> getAssignedUsersRecursive( org.apache.archiva.redback.rbac.Role rbacRole ) throws RbacManagerException
{
try
{
return rbacManager.getUserAssignmentsForRoles( recurseRoles( rbacRole ).map( role -> role.getName( ) ).collect( Collectors.toList( ) ) )
.stream( ).map( assignment -> getUserInfo( assignment.getPrincipal( ) ) ).collect( Collectors.toList( ) );
}
catch ( RuntimeException e )
{
log.error( "Could not recurse roles for assignments {}", e.getMessage( ) );
throw new RbacManagerException( e.getCause( ) );
}
}
private Stream<Role> recurseRoles( Role startRole )
{
return Stream.concat( Stream.of( startRole ), getParentRoleStream( startRole ).flatMap( this::recurseRoles ) ).distinct( );
}
private Stream<? extends Role> getParentRoleStream( Role role )
{
try
{
return rbacManager.getParentRoleNames( role ).values( ).stream( );
}
catch ( RbacManagerException e )
{
throw new RuntimeException( e );
}
}
BaseUserInfo getUserInfo( String userId )
{
try
{
User user = userManager.findUser( userId );
return new BaseUserInfo( user.getId( ), user.getUsername( ) );
}
catch ( UserManagerException e )
{
throw new RuntimeException( e );
}
}
protected Optional<RoleInfo> getRoleInfoOptional( Role rbacRole )
{
try
{
RoleInfo role = RoleInfo.of( rbacRole );
role.setParentRoleIds( getParentRoles( rbacRole ) );
role.setChildRoleIds( getChildRoles( rbacRole ) );
role.setAssignedUsers( getAssignedUsersRecursive( rbacRole ) );
return Optional.of( role );
}
catch ( RbacManagerException e )
{
log.error( "Error while retrieving role information {}", e.getMessage( ), e );
return Optional.empty( );
}
}
}

View File

@ -61,6 +61,7 @@ import java.util.stream.Collectors;
* @author Martin Stockhammer
* @since 3.0
*/
@SuppressWarnings( "SpringJavaAutowiredFieldsWarningInspection" )
@Service("v2.groupService#rest")
public class DefaultGroupService
implements GroupService
@ -85,7 +86,10 @@ public class DefaultGroupService
@Named(value = "ldapConnectionFactory#configurable")
private LdapConnectionFactory ldapConnectionFactory;
private static final Group getGroupFromLdap( LdapGroup ldapGroup ) {
public DefaultGroupService( ) {
}
private static Group getGroupFromLdap( LdapGroup ldapGroup ) {
Group group = new Group( );
group.setName( ldapGroup.getName() );
group.setUniqueName( ldapGroup.getDn() );
@ -128,7 +132,7 @@ public class DefaultGroupService
* be found, it will set "" for the uniqueName
*
* @return the list of mapping
* @throws RedbackServiceException
* @throws RedbackServiceException if there was an error retrieving the mapping data
*/
@Override
public List<GroupMapping> getGroupMappings()

View File

@ -0,0 +1,434 @@
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.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.integration.util.RoleSorter;
import org.apache.archiva.redback.rbac.Permission;
import org.apache.archiva.redback.rbac.RBACManager;
import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
import org.apache.archiva.redback.rbac.Resource;
import org.apache.archiva.redback.rest.api.MessageKeys;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.Role;
import org.apache.archiva.redback.rest.api.model.RoleTemplate;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.v2.RoleService;
import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
import org.apache.archiva.redback.rest.services.RedbackRequestInformation;
import org.apache.archiva.redback.role.RoleExistsException;
import org.apache.archiva.redback.role.RoleManager;
import org.apache.archiva.redback.role.RoleManagerException;
import org.apache.archiva.redback.role.RoleNotFoundException;
import org.apache.archiva.redback.role.model.ModelTemplate;
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.UserNotFoundException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @author Olivier Lamy
* @since 1.3
*/
@Service("v2.roleService#rest")
public class DefaultRoleService extends BaseRedbackService
implements RoleService
{
private Logger log = LoggerFactory.getLogger( DefaultRoleService.class );
private RoleManager roleManager;
@Context
private HttpServletRequest httpServletRequest;
@Context
private HttpServletResponse httpServletResponse;
@Context
private UriInfo uriInfo;
private static final String[] DEFAULT_SEARCH_FIELDS = {"name", "description"};
private static final Map<String, BiPredicate<String, org.apache.archiva.redback.rbac.Role>> FILTER_MAP = new HashMap<>( );
private static final Map<String, Comparator<org.apache.archiva.redback.rbac.Role>> ORDER_MAP = new HashMap<>( );
private static final QueryHelper<org.apache.archiva.redback.rbac.Role> QUERY_HELPER;
static
{
QUERY_HELPER = new QueryHelper<>( FILTER_MAP, ORDER_MAP, DEFAULT_SEARCH_FIELDS );
QUERY_HELPER.addStringFilter( "name", org.apache.archiva.redback.rbac.Role::getName );
QUERY_HELPER.addStringFilter( "description", org.apache.archiva.redback.rbac.Role::getDescription );
QUERY_HELPER.addBooleanFilter( "assignable", org.apache.archiva.redback.rbac.Role::isAssignable );
// The simple Comparator.comparing(attribute) is not null safe
// As there are attributes that may have a null value, we have to use a comparator with nullsLast(naturalOrder)
// and the wrapping Comparator.nullsLast(Comparator.comparing(attribute)) does not work, because the attribute is not checked by the nullsLast-Comparator
QUERY_HELPER.addNullsafeFieldComparator( "name", org.apache.archiva.redback.rbac.Role::getName );
QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.redback.rbac.Role::getId );
QUERY_HELPER.addNullsafeFieldComparator( "resource", org.apache.archiva.redback.rbac.Role::getResource );
QUERY_HELPER.addNullsafeFieldComparator( "assignable", org.apache.archiva.redback.rbac.Role::isAssignable );
QUERY_HELPER.addNullsafeFieldComparator( "template_instance", org.apache.archiva.redback.rbac.Role::isTemplateInstance );
}
@Inject
public DefaultRoleService( RoleManager roleManager,
@Named(value = "rbacManager#default") RBACManager rbacManager,
@Named(value = "userManager#default") UserManager userManager )
{
super( rbacManager, userManager );
this.roleManager = roleManager;
log.debug( "use rbacManager impl: {}", rbacManager.getClass().getName() );
log.debug( "use userManager impl: {}", userManager.getClass().getName() );
}
@Override
public PagedResult<RoleInfo> getAllRoles( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws RedbackServiceException
{
boolean ascending = !"desc".equals( order );
try
{
// UserQuery does not work here, because the configurable user manager does only return the query for
// the first user manager in the list. So we have to fetch the whole role list
List<? extends org.apache.archiva.redback.rbac.Role> rawRoles = rbacManager.getAllRoles( );
Predicate<org.apache.archiva.redback.rbac.Role> filter = QUERY_HELPER.getQueryFilter( searchTerm );
long size = rawRoles.stream( ).filter( filter ).count( );
List<RoleInfo> users = rawRoles.stream( )
.filter( filter )
.sorted( QUERY_HELPER.getComparator( orderBy, ascending ) ).skip( offset ).limit( limit )
.map( role -> {
try
{
return Optional.of( getRoleInfo( role ) );
}
catch ( RedbackServiceException e )
{
return Optional.<RoleInfo>empty();
}
} ).filter(Optional::isPresent)
.map(Optional::get)
.collect( Collectors.toList( ) );
return new PagedResult<>( (int) size, offset, limit, users );
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL , e.getMessage( )) );
}
}
@Override
public RoleInfo getRole( String roleId ) throws RedbackServiceException
{
try
{
org.apache.archiva.redback.rbac.Role rbacRole = rbacManager.getRoleById( roleId );
RoleInfo role = getRoleInfo( rbacRole );
return role;
}
catch ( RbacObjectNotFoundException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND, roleId ), 404 );
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
@Override
public Response checkRole( String roleId ) throws RedbackServiceException
{
try
{
org.apache.archiva.redback.rbac.Role rbacRole = rbacManager.getRoleById( roleId );
if (rbacRole==null) {
return Response.status( 404 ).build();
} else
{
return Response.ok( ).build( );
}
}
catch ( RbacObjectNotFoundException e )
{
return Response.status( 404 ).build();
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
@Override
public RoleInfo moveTemplatedRole( String templateId, String oldResource, String newResource )
throws RedbackServiceException
{
try
{
if (StringUtils.isEmpty( templateId ) || StringUtils.isEmpty( oldResource ) || StringUtils.isEmpty( newResource )) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND ), 404 );
}
boolean sourceExists = roleManager.templatedRoleExists( templateId, oldResource );
if (!sourceExists) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_INSTANCE_NOT_FOUND, templateId, oldResource ), 404 );
}
boolean destExists = roleManager.templatedRoleExists( templateId, newResource );
if (destExists) {
httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder().path("../../..").path(newResource).build( ).normalize().toString() );
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_INSTANCE_EXISTS, templateId, newResource ), 303 );
}
String roleId = roleManager.moveTemplatedRole( templateId, oldResource, newResource );
httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder().path("../../..").path(newResource).build( ).normalize().toString() );
httpServletResponse.setStatus( 201 );
return getRoleInfo( rbacManager.getRoleById( roleId ) );
}
catch ( RoleExistsException e ) {
httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder().path("../../..").path(newResource).build( ).normalize().toString() );
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_INSTANCE_EXISTS, templateId, newResource ), 303 );
}
catch ( RoleManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLEMANAGER_FAIL, e.getMessage( ) ) );
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
@Override
public Response checkTemplateRole( String templateId, String resource )
throws RedbackServiceException
{
try
{
if (roleManager.templatedRoleExists( templateId, resource )) {
return Response.ok( ).build( );
} else {
return Response.status( 404 ).build();
}
}
catch ( RoleManagerException e )
{
throw new RedbackServiceException( e.getMessage() );
}
}
@Override
public RoleInfo createTemplatedRole( String templateId, String resource )
throws RedbackServiceException
{
if (StringUtils.isEmpty( templateId )) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND ), 404 );
}
if (StringUtils.isEmpty( resource )) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND ), 404 );
}
try
{
boolean exists = roleManager.templatedRoleExists( templateId, resource );
String roleId = roleManager.createTemplatedRole( templateId, resource );
httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder().path("../../..").path(roleId).build( ).normalize().toString() );
if (exists)
{
httpServletResponse.setStatus( 200 );
} else {
httpServletResponse.setStatus( 201 );
}
return getRoleInfo( rbacManager.getRoleById( roleId ) );
} catch (RoleNotFoundException e) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND, templateId, resource ), 404 );
} catch (RoleExistsException e) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_INSTANCE_EXISTS, templateId, resource ), 303 );
}
catch ( RoleManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLEMANAGER_FAIL, e.getMessage( ) ) );
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
@Override
public Response removeTemplatedRole( String templateId, String resource )
throws RedbackServiceException
{
try
{
roleManager.removeTemplatedRole( templateId, resource );
return Response.ok( ).build( );
}
catch ( RoleNotFoundException e ) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_INSTANCE_NOT_FOUND, templateId, resource ), 404 );
}
catch ( RoleManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLEMANAGER_FAIL, e.getMessage( ) ) );
}
}
@Override
public RoleInfo assignRole( String roleId, String userId )
throws RedbackServiceException
{
try
{
userManager.findUser( userId );
roleManager.assignRole( roleId, userId );
return getRoleInfo( rbacManager.getRoleById( roleId ) );
}
catch ( RoleNotFoundException e ) {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND, e.getMessage( ) ), 404 );
}
catch ( RoleManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLEMANAGER_FAIL, e.getMessage( ) ) );
}
catch ( UserNotFoundException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_USER_NOT_FOUND, e.getMessage( ) ), 404 );
}
catch ( UserManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_USERMANAGER_FAIL, e.getMessage( ) ) );
}
catch ( RbacObjectNotFoundException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
@Override
public RoleInfo assignTemplatedRole( String templateId, String resource, String principal )
throws RedbackServiceException
{
try
{
roleManager.assignTemplatedRole( templateId, resource, principal );
}
catch ( RoleManagerException e )
{
throw new RedbackServiceException( e.getMessage() );
}
return null;
}
@Override
public RoleInfo unassignRole( String roleId, String principal )
throws RedbackServiceException
{
try
{
roleManager.unassignRole( roleId, principal );
}
catch ( RoleManagerException e )
{
throw new RedbackServiceException( e.getMessage() );
}
return null;
}
@Override
public RoleInfo updateRole( String roleId, Role role ) throws RedbackServiceException
{
return null;
}
// public List<Role> getEffectivelyAssignedRoles( String username )
// throws RedbackServiceException
// {
// if ( StringUtils.isEmpty( username ) )
// {
// throw new RedbackServiceException( new ErrorMessage( "user.cannot.be.null" ) );
// }
// try
// {
// List<? extends org.apache.archiva.redback.rbac.Role> roles =
// filterAssignableRoles( rbacManager.getEffectivelyAssignedRoles( username ) );
//
// List<Role> effectivelyAssignedRoles = new ArrayList<Role>( roles.size() );
//
// for ( org.apache.archiva.redback.rbac.Role r : roles )
// {
// effectivelyAssignedRoles.add( new Role( r ) );
// }
//
// Collections.sort( effectivelyAssignedRoles, RoleComparator.INSTANCE );
//
// return effectivelyAssignedRoles;
// }
// catch ( RbacManagerException rme )
// {
// // ignore, this can happen when the user has no roles assigned
// }
// return new ArrayList<Role>( 0 );
// }
//----------------------------------------------------------------
// Internal methods
//----------------------------------------------------------------
}

View File

@ -41,17 +41,22 @@ import org.apache.archiva.redback.policy.PasswordRuleViolationException;
import org.apache.archiva.redback.policy.UserSecurityPolicy;
import org.apache.archiva.redback.rbac.RBACManager;
import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.Role;
import org.apache.archiva.redback.rbac.UserAssignment;
import org.apache.archiva.redback.rest.api.MessageKeys;
import org.apache.archiva.redback.rest.api.model.ActionStatus;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.v2.Application;
import org.apache.archiva.redback.rest.api.model.v2.AvailabilityStatus;
import org.apache.archiva.redback.rest.api.model.v2.BaseRoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.Operation;
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
import org.apache.archiva.redback.rest.api.model.v2.RegistrationKey;
import org.apache.archiva.redback.rest.api.model.v2.Resource;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.RoleTree;
import org.apache.archiva.redback.rest.api.model.v2.SelfUserData;
import org.apache.archiva.redback.rest.api.model.v2.User;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
@ -65,6 +70,7 @@ import org.apache.archiva.redback.rest.services.interceptors.RedbackPrincipal;
import org.apache.archiva.redback.rest.services.utils.PasswordValidator;
import org.apache.archiva.redback.role.RoleManager;
import org.apache.archiva.redback.role.RoleManagerException;
import org.apache.archiva.redback.role.model.ModelApplication;
import org.apache.archiva.redback.system.SecuritySession;
import org.apache.archiva.redback.system.SecuritySystem;
import org.apache.archiva.redback.users.UserManager;
@ -91,17 +97,19 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service( "v2.userService#rest" )
public class DefaultUserService
public class DefaultUserService extends BaseRedbackService
implements UserService
{
@ -113,6 +121,7 @@ public class DefaultUserService
private static final String[] DEFAULT_SEARCH_FIELDS = {"user_id", "full_name", "email"};
private static final Map<String, BiPredicate<String, org.apache.archiva.redback.users.User>> FILTER_MAP = new HashMap<>( );
private static final Map<String, Comparator<org.apache.archiva.redback.users.User>> ORDER_MAP = new HashMap<>( );
private static final QueryHelper<org.apache.archiva.redback.users.User> QUERY_HELPER;
static
{
@ -133,11 +142,10 @@ public class DefaultUserService
FILTER_MAP.put( "user_id", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getUsername( ), q ) );
FILTER_MAP.put( "full_name", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getFullName( ), q ) );
FILTER_MAP.put( "email", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getEmail( ), q ) );
QUERY_HELPER = new QueryHelper<>( FILTER_MAP, ORDER_MAP, DEFAULT_SEARCH_FIELDS );
}
private UserManager userManager;
private SecuritySystem securitySystem;
@Inject
@ -174,9 +182,10 @@ public class DefaultUserService
@Inject
private Mailer mailer;
@Inject
@Named( value = "rbacManager#default" )
private RBACManager rbacManager;
@Named( value = "v2.roleService#rest" )
private DefaultRoleService roleManagementService;
private HttpAuthenticator httpAuthenticator;
@ -196,10 +205,11 @@ public class DefaultUserService
private SecurityContext securityContext;
@Inject
public DefaultUserService( @Named( value = "userManager#default" ) UserManager userManager,
public DefaultUserService(@Named( value = "rbacManager#default" ) RBACManager rbacManager,
@Named( value = "userManager#default" ) UserManager userManager ,
SecuritySystem securitySystem )
{
this.userManager = userManager;
super( rbacManager, userManager );
this.securitySystem = securitySystem;
}
@ -220,7 +230,8 @@ public class DefaultUserService
public UserInfo createUser( User user )
throws RedbackServiceException
{
if (user==null) {
if ( user == null )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_USER_ID_EMPTY ), 422 );
}
UserInfo result;
@ -311,7 +322,8 @@ public class DefaultUserService
public void deleteUser( String userId )
throws RedbackServiceException
{
if (StringUtils.isEmpty( userId )) {
if ( StringUtils.isEmpty( userId ) )
{
throw new RedbackServiceException( MessageKeys.ERR_USER_ID_EMPTY, 404 );
}
@ -355,7 +367,8 @@ public class DefaultUserService
public UserInfo getUser( String userId )
throws RedbackServiceException
{
if (StringUtils.isEmpty( userId)) {
if ( StringUtils.isEmpty( userId ) )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_USER_ID_EMPTY ), 404 );
}
try
@ -377,55 +390,6 @@ public class DefaultUserService
}
}
Comparator<org.apache.archiva.redback.users.User> getAttributeComparator( String attributeName )
{
return ORDER_MAP.get( attributeName );
}
Comparator<org.apache.archiva.redback.users.User> getComparator( List<String> orderBy, boolean ascending )
{
if ( ascending )
{
return orderBy.stream( ).map( ( String name ) -> getAttributeComparator( name ) ).filter( Objects::nonNull ).reduce( Comparator::thenComparing ).get( );
}
else
{
return orderBy.stream( ).map( ( String name ) -> getAttributeComparator( name ) == null ? null : getAttributeComparator( name ).reversed( ) ).filter( Objects::nonNull ).reduce( Comparator::thenComparing ).get( );
}
}
static Predicate<org.apache.archiva.redback.users.User> getFilter( final String attribute, final String queryToken )
{
if ( FILTER_MAP.containsKey( attribute ) )
{
return ( org.apache.archiva.redback.users.User u ) -> FILTER_MAP.get( attribute ).test( queryToken, u );
}
else
{
return Arrays.stream( DEFAULT_SEARCH_FIELDS )
.map( att -> getFilter( att, queryToken ) ).reduce( Predicate::or ).get( );
}
}
Predicate<org.apache.archiva.redback.users.User> getUserFilter( String queryTerms )
{
return Arrays.stream( queryTerms.split( "\\s+" ) )
.map( s -> {
if ( s.contains( ":" ) )
{
String attr = StringUtils.substringBefore( s, ":" );
String term = StringUtils.substringAfter( s, ":" );
return getFilter( attr, term );
}
else
{
return Arrays.stream( DEFAULT_SEARCH_FIELDS )
.map( att -> getFilter( att, s ) ).reduce( Predicate::or ).get( );
}
}
).reduce( Predicate::or ).get( );
}
@Override
public PagedResult<UserInfo> getUsers( String q, Integer offset,
Integer limit, List<String> orderBy, String order )
@ -437,11 +401,11 @@ public class DefaultUserService
// UserQuery does not work here, because the configurable user manager does only return the query for
// the first user manager in the list. So we have to fetch the whole user list
List<? extends org.apache.archiva.redback.users.User> rawUsers = userManager.getUsers( );
Predicate<org.apache.archiva.redback.users.User> filter = getUserFilter( q );
Predicate<org.apache.archiva.redback.users.User> filter = QUERY_HELPER.getQueryFilter( q );
long size = rawUsers.stream( ).filter( filter ).count( );
List<UserInfo> users = rawUsers.stream( )
.filter( filter )
.sorted( getComparator( orderBy, ascending ) ).skip( offset ).limit( limit )
.sorted( QUERY_HELPER.getComparator( orderBy, ascending ) ).skip( offset ).limit( limit )
.map( user -> getRestUser( user ) )
.collect( Collectors.toList( ) );
return new PagedResult<>( (int) size, offset, limit, users );
@ -974,6 +938,101 @@ public class DefaultUserService
}
}
@Override
public List<RoleInfo> getEffectivelyAssignedRoles( String username ) throws RedbackServiceException
{
try
{
return rbacManager.getEffectivelyAssignedRoles( username ).stream( )
.filter( org.apache.archiva.redback.rbac.Role::isAssignable )
.map( this::getRoleInfoOptional )
.filter( Optional::isPresent )
.map(Optional::get).collect( Collectors.toList());
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
private static final Application toApplication( ModelApplication app )
{
Application application = new Application( );
application.setId( app.getId( ) );
application.setVersion( app.getVersion( ) );
application.setDescription( app.getDescription( ) == null ? "" :app.getDescription() );
application.setLongDescription( app.getLongDescription( ) == null ? "" : app.getLongDescription( ) );
return application;
}
private List<Application> getAllApplications( )
{
return roleManager.getModel( ).getApplications( ).stream( ).map( DefaultUserService::toApplication ).collect( Collectors.toList( ) );
}
@Override
public RoleTree getRoleTree( final String username ) throws RedbackServiceException
{
final Map<String, String> roleApplicationMap = roleManager.getModel( ).getApplications( ).stream( )
.flatMap( modelApplication -> modelApplication.getRoles( ).stream( ).map( role -> {
BaseRoleInfo roleInfo = new BaseRoleInfo( );
roleInfo.setId( role.getId( ) );
roleInfo.setApplicationId( modelApplication.getId( ) );
return roleInfo;
} ) ).collect( Collectors.toMap( BaseRoleInfo::getId, BaseRoleInfo::getApplicationId ) );
try
{
final Set<String> assignedRoleNames = new HashSet( rbacManager.getUserAssignment( username ).getRoleNames( ) );
// We have to reuse the BaseRoleInfo objects, because the roles are not returned starting from the roots
final Map<String, BaseRoleInfo> roleNameCache = new HashMap<>( );
List<BaseRoleInfo> roleList = rbacManager.getAllRoles( ).stream( ).flatMap( this::flattenRole ).map( role ->
{
BaseRoleInfo roleInfo = roleNameCache.computeIfAbsent( role.getName( ), s -> new BaseRoleInfo( ) );
// Setting the role data, as there may be child role objects that are not completely initialized
roleInfo = BaseRoleInfo.of( role, roleInfo );
roleInfo.setApplicationId( roleApplicationMap.get( role.getId( ) ) );
roleInfo.setAssigned( assignedRoleNames.contains( role.getName( ) ) );
roleInfo.setChildren( role.getChildRoleNames( ).stream( )
.map( roleName ->
{
BaseRoleInfo childRoleInfo = roleNameCache.computeIfAbsent( roleName, s -> BaseRoleInfo.ofName( roleName ) );
childRoleInfo.setChild( true );
return childRoleInfo;
} )
.collect( Collectors.toList( ) ) );
return roleInfo;
} ).collect( Collectors.toList( ) );
RoleTree roleTree = new RoleTree( );
roleTree.setApplications( getAllApplications( ).stream( ).collect( Collectors.toMap( Application::getId, Function.identity( ) ) ) );
roleTree.setRootRoles( roleList.stream( ).filter( BaseRoleInfo::isNotChild ).collect( Collectors.toList( ) ) );
roleTree.setUserId( username );
return roleTree;
}
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
}
private Stream<Role> flattenRole( Role role )
{
return Stream.concat( Stream.of( role ), this.getChildren( role ).flatMap( this::flattenRole ) ).distinct( );
}
private Stream<? extends Role> getChildren( Role role )
{
try
{
return rbacManager.getChildRoleNames( role ).values( ).stream( );
}
catch ( RbacManagerException e )
{
throw new RuntimeException( e );
}
}
@Override
public Collection<Operation> getUserOperations( String userName )
throws RedbackServiceException

View File

@ -0,0 +1,168 @@
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.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
/**
*
* Helper class that returns combined filter and comparison objects for ordering.
*
* The query term may be consist of simple query terms separated by whitespace or attribute queries
* in the form <code>attribute:query</code>, which means only the attribute is searched for the query string.
* <br />
* Example:
* <dl>
* <dt>`user1 test`</dt>
* <dd>
* searches for the tokens user1 and test in the default attributes.
* </dd>
* <dt>`user1 name:test`</dt>
* <dd>searches for the token user1 in the default attributes and for the token test in the attribute name.</dd>
* </dl>
*
*
* @since 3.0
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class QueryHelper<T>
{
private final Map<String, BiPredicate<String, T>> FILTER_MAP;
private final Map<String, Comparator<T>> ORDER_MAP;
private final String[] DEFAULT_SEARCH_FIELDS;
private final Predicate<T> DEFAULT_FILTER = ( T att ) -> false;
/**
* Creates a new query helper with the given filters and comparators.
*
* @param filterMap a map of filters, where the key is the attribute name and the value is a predicate that matches
* the filter value and the object instance.
* @param orderMap a map of comparators, where key is the attribute name and the value is a comparator for the given
* object instance
* @param defaultSearchFields A array of attribute names, that are used as default search fields.
*/
public QueryHelper(Map<String, BiPredicate<String, T>> filterMap, Map<String, Comparator<T>> orderMap,
String[] defaultSearchFields)
{
this.FILTER_MAP = filterMap;
this.DEFAULT_SEARCH_FIELDS = defaultSearchFields;
this.ORDER_MAP = new HashMap<>( orderMap );
}
public <U extends Comparable<? super U>> void addNullsafeFieldComparator( String fieldName, Function<? super T, U> keyExtractor) {
ORDER_MAP.put( fieldName, Comparator.comparing( keyExtractor, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
}
public void addStringFilter(String attribute, Function<? super T, String> keyExtractor) {
this.FILTER_MAP.put( attribute, ( String q, T r ) -> StringUtils.containsIgnoreCase( keyExtractor.apply( r ), q ) );
}
public void addBooleanFilter(String attribute, Function<? super T, Boolean> keyExtractor) {
this.FILTER_MAP.put( attribute, ( String q, T r ) -> Boolean.valueOf( q ) == keyExtractor.apply( r ) );
}
/**
* Get the comparator for a specific attribute.
* @param attributeName the name of the attribute.
* @return
*/
Comparator<T> getAttributeComparator( String attributeName )
{
return ORDER_MAP.get( attributeName );
}
/**
* Get the combined order for the given attributes in the given order.
*
* @param orderBy the attributes to compare. The first attribute in the list will be used first for comparing.
* @param ascending
* @return
*/
Comparator<T> getComparator( List<String> orderBy, boolean ascending )
{
if ( ascending )
{
return orderBy.stream( ).map( ( String name ) -> getAttributeComparator( name ) ).filter( Objects::nonNull )
.reduce( Comparator::thenComparing )
.orElseThrow( () -> new IllegalArgumentException( "No attribute ordering found" ) );
}
else
{
return orderBy.stream( ).map( ( String name ) -> getAttributeComparator( name ) == null ? null : getAttributeComparator( name )
.reversed( ) ).filter( Objects::nonNull ).reduce( Comparator::thenComparing )
.orElseThrow( () -> new IllegalArgumentException( "No attribute ordering found" ) );
}
}
/**
* Returns a query filter for a specific attribute and query token.
* @param attribute the attribute name to filter for.
* @param queryToken the search token.
* @return The predicate used to filter the token
*/
Predicate<T> getAttributeQueryFilter( final String attribute, final String queryToken )
{
if ( FILTER_MAP.containsKey( attribute ) )
{
return ( T u ) -> FILTER_MAP.get( attribute ).test( queryToken, u );
}
else
{
return DEFAULT_FILTER;
}
}
/**
* Returns the combined query filter for the given query terms.
* The query terms may be either simple strings separated by whitespace or use the
* <code>attribute:query</code> syntax, that searches only the attribute for the query term.
* @param queryTerms the query string
* @return the combined query filter
*/
Predicate<T> getQueryFilter( String queryTerms )
{
return Arrays.stream( queryTerms.split( "\\s+" ) )
.map( s -> {
if ( s.contains( ":" ) )
{
String attr = StringUtils.substringBefore( s, ":" );
String term = StringUtils.substringAfter( s, ":" );
return getAttributeQueryFilter( attr, term );
}
else
{
return Arrays.stream( DEFAULT_SEARCH_FIELDS )
.map( att -> getAttributeQueryFilter( att, s ) ).reduce( Predicate::or ).get( );
}
}
).reduce( Predicate::or ).get( );
}
}

View File

@ -93,7 +93,7 @@
<jaxrs:serviceBeans>
<ref bean="v2.userService#rest"/>
<ref bean="v2.authenticationService#rest"/>
<ref bean="roleManagementService#rest"/>
<ref bean="v2.roleService#rest"/>
<ref bean="utilServices#rest"/>
<ref bean="passwordService#rest"/>
<ref bean="v2.groupService#rest"/>

View File

@ -128,7 +128,7 @@ public abstract class AbstractNativeRestServices
}
private String getServiceBasePath( )
protected String getServiceBasePath( )
{
return "/v2/redback";
}

View File

@ -0,0 +1,505 @@
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.v2.RoleInfo;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
import static org.apache.archiva.redback.rest.api.Constants.DEFAULT_PAGE_LIMIT;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@ExtendWith( SpringExtension.class )
@ContextConfiguration(
locations = {"classpath:/ldap-spring-test.xml"} )
@TestInstance( TestInstance.Lifecycle.PER_CLASS )
@Tag( "rest-native" )
@TestMethodOrder( MethodOrderer.Random.class )
@DisplayName( "Native REST tests for V2 RoleService" )
public class NativeRoleServiceTest extends AbstractNativeRestServices
{
@Override
protected String getServicePath( )
{
return "/roles";
}
@BeforeAll
void setup( ) throws Exception
{
super.setupNative( );
}
@AfterAll
void destroy( ) throws Exception
{
super.shutdownNative( );
}
private String getUserServicePath()
{
return new StringBuilder( )
.append( getContextRoot( ) )
.append( getServiceBasePath( ) )
.append( "/users" ).toString( );
}
@Test
void createTemplatedRole( )
{
String token = getAdminToken( );
try
{
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 201 ).extract( ).response( );
assertNotNull( response );
RoleInfo roleInfo = response.getBody( ).jsonPath( ).getObject( "", RoleInfo.class );
assertNotNull( response.getHeader( "Location" ) );
assertTrue( response.getHeader( "Location" ).endsWith( "/roles/" + roleInfo.getId( ) ) );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.head( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 200 );
// Repository observer is child template of repository-manager and will be created too
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.head( "template/archiva-repository-observer/repository01" )
.then( ).statusCode( 200 );
}
finally
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-observer/repository01" )
.then( ).statusCode( 200 );
}
}
@Test
void createTemplatedRoleWithNonexistentTemplate( )
{
String token = getAdminToken( );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/abcdefg/repository01" )
.then( ).statusCode( 404 );
}
@Test
void deleteTemplatedRole( )
{
String token = getAdminToken( );
try
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-manager/repository05" )
.then( ).statusCode( 201 ).extract( ).response( );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 404 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-manager/repository05" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-manager/repository05" )
.then( ).statusCode( 404 );
} finally
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-observer/repository01" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-observer/repository05" )
.then( ).statusCode( 200 );
}
}
@Test
void checkTemplatedRole() {
String token = getAdminToken( );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-observer/repository01" )
.then( ).statusCode( 201 );
try {
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.head( "template/archiva-repository-observer/repository01" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.head( "archiva-repository-observer.repository01" )
.then( ).statusCode( 200 );
} finally
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-observer/repository01" )
.then( ).statusCode( 200 );
}
}
@Nested
@DisplayName( "Test Role queries" )
@ContextConfiguration(
locations = {"classpath:/ldap-spring-test.xml"} )
@TestInstance( TestInstance.Lifecycle.PER_CLASS )
class TestRoleRetrieval
{
int roleInstances = 3;
String token;
@BeforeAll
void initRoles( )
{
this.token = getAdminToken( );
for ( int i = 0; i < roleInstances; i++ )
{
String suffix = String.format( "%03d", i );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-manager/repo" + suffix )
.then( ).statusCode( 201 ).extract( ).response( );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-observer/repo" + suffix )
.then( ).statusCode( anyOf( equalTo( 200 ), equalTo( 201 ) ) ).extract( ).response( );
}
}
@Test
void getMultipleRolesWithoutParams( )
{
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).get( ).then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
List<RoleInfo> roleData = response.body( ).jsonPath( ).getList( "data", RoleInfo.class );
assertNotNull( roleData );
assertEquals( roleInstances * 2 + 9, roleData.size( ) );
assertEquals( Integer.valueOf( 0 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
assertEquals( Integer.valueOf( DEFAULT_PAGE_LIMIT ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( roleInstances * 2 + 9 ), response.body( ).jsonPath( ).get( "pagination.total_count" ) );
}
@Test
void getMultipleRolesWithPaging( )
{
HashMap<String, String> params = new HashMap<>( );
params.put( "limit", Integer.toString( 10 ) );
params.put( "offset", Integer.toString( 1 ) );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).params( params ).get( ).then( ).statusCode( 200 ).extract( ).response( );
List<RoleInfo> userData = response.body( ).jsonPath( ).getList( "data", RoleInfo.class );
assertNotNull( userData );
response.getBody( ).jsonPath( ).prettyPrint( );
assertEquals( 10, userData.size( ) );
assertEquals( Integer.valueOf( 1 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
assertEquals( Integer.valueOf( 10 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( roleInstances * 2 + 9 ), response.body( ).jsonPath( ).get( "pagination.total_count" ) );
}
@Test
void getMultipleUsersWithPagingOrderByIdAndResource( )
{
HashMap<String, Object> params = new HashMap<>( );
params.put( "limit", Integer.toString( 8 ) );
params.put( "offset", Integer.toString( 5 ) );
params.put( "orderBy", Arrays.asList( "id", "resource" ) );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).params( params ).get( ).then( ).statusCode( 200 ).extract( ).response( );
List<RoleInfo> userData = response.body( ).jsonPath( ).getList( "data", RoleInfo.class );
assertNotNull( userData );
// admin user has toto@toto.org as email so is after aragorn
assertEquals( "repo002", userData.get( 0 ).getResource( ) );
assertEquals( "repo000", userData.get( 1 ).getResource( ) );
assertEquals( "archiva-repository-observer.repo000", userData.get( 1 ).getId( ) );
assertEquals( "archiva-system-administrator", userData.get( 4 ).getId( ) );
assertEquals( 8, userData.size( ) );
assertEquals( Integer.valueOf( 5 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
assertEquals( Integer.valueOf( 8 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( roleInstances * 2 + 9 ), response.body( ).jsonPath( ).get( "pagination.total_count" ) );
}
@Test
void getMultipleUsersWithPagingOrderByIdAndResourceReverse( )
{
HashMap<String, Object> params = new HashMap<>( );
params.put( "limit", Integer.toString( 7 ) );
params.put( "offset", Integer.toString( 1 ) );
params.put( "orderBy", Arrays.asList( "id", "resource" ) );
params.put( "order", "desc" );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).params( params ).get( ).then( ).statusCode( 200 ).extract( ).response( );
response.getBody( ).jsonPath( ).prettyPrint( );
List<RoleInfo> userData = response.body( ).jsonPath( ).getList( "data", RoleInfo.class );
assertNotNull( userData );
// admin user has toto@toto.org as email so is after aragorn
assertEquals( "system-administrator", userData.get( 0 ).getId( ) );
assertEquals( "registered-user", userData.get( 1 ).getId( ) );
assertEquals( "guest", userData.get( 2 ).getId( ) );
assertEquals( "archiva-repository-observer.repo002", userData.get( 5 ).getId( ) );
assertEquals( 7, userData.size( ) );
assertEquals( Integer.valueOf( 1 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
assertEquals( Integer.valueOf( 7 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( roleInstances * 2 + 9 ), response.body( ).jsonPath( ).get( "pagination.total_count" ) );
}
@Test
void getMultipleRolesWithPagingAndQuery( )
{
HashMap<String, String> params = new HashMap<>( );
params.put( "limit", Integer.toString( 10 ) );
params.put( "offset", Integer.toString( 0 ) );
params.put( "order", "asc" );
params.put( "q", "system" );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).params( params ).get( ).then( ).statusCode( 200 ).extract( ).response( );
List<RoleInfo> userData = response.body( ).jsonPath( ).getList( "data", RoleInfo.class );
assertNotNull( userData );
assertEquals( 2, userData.size( ) );
assertEquals( Integer.valueOf( 0 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
assertEquals( Integer.valueOf( 10 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( 2 ), response.body( ).jsonPath( ).get( "pagination.total_count" ) );
}
@AfterAll
void cleanupRoles( )
{
for ( int i = 0; i < roleInstances; i++ )
{
String suffix = String.format( "%03d", i );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).delete( "template/archiva-repository-manager/repo" + suffix ).then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).delete( "template/archiva-repository-observer/repo" + suffix ).then( ).statusCode( 200 );
}
}
}
@Test
void getRole( )
{
String token = getAdminToken( );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).get( "archiva-system-administrator" ).then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
RoleInfo roleInfo = response.getBody( ).jsonPath( ).getObject( "", RoleInfo.class );
assertNotNull( roleInfo );
assertEquals( "archiva-system-administrator", roleInfo.getId( ) );
assertEquals( "Archiva System Administrator", roleInfo.getName( ) );
}
@Test
void getNonExistingRole( )
{
String token = getAdminToken( );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).get( "abcdefg" ).then( ).statusCode( 404 );
}
@Test
void checkRole() {
String token = getAdminToken( );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).head( "archiva-system-administrator" ).then( ).statusCode( 200 ).extract( ).response( );
assertEquals(0,response.getBody( ).asByteArray().length);
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).head( "abcdefg" ).then( ).statusCode( 404 );
}
@Test
void moveRole() {
String token = getAdminToken( );
try
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 201 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).head( "template/archiva-repository-observer/repository01" ).then( ).statusCode( 200 );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).post( "template/archiva-repository-manager/repository01/moveto/repository02" ).then( ).statusCode( 201 ).extract( ).response( );
RoleInfo role = response.getBody( ).jsonPath( ).getObject( "", RoleInfo.class );
assertNotNull( role );
assertEquals( "archiva-repository-manager.repository02", role.getId( ) );
assertEquals( "repository02", role.getResource( ) );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).head( "template/archiva-repository-manager/repository01" ).then( ).statusCode( 404 );
// Child templates are copied and not moved
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).head( "template/archiva-repository-observer/repository01" ).then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).head( "template/archiva-repository-observer/repository02" ).then( ).statusCode( 200 );
} finally
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-manager/repository02" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-observer/repository01" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-observer/repository02" )
.then( ).statusCode( 200 );
}
}
@Test
void moveRoleToExistingDestination() {
String token = getAdminToken( );
try
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 201 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "template/archiva-repository-manager/repository02" )
.then( ).statusCode( 201 );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).redirects( ).follow( false )
.post( "template/archiva-repository-manager/repository01/moveto/repository02" ).then( ).statusCode( 303 )
.extract( ).response( );
System.out.println( response.getHeader( "Location" ) );
assertTrue( response.getHeader( "Location" ).endsWith( "/roles/template/archiva-repository-manager/repository02" ) );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( ).head( "template/archiva-repository-manager/repository01" ).then( ).statusCode( 200 );
} finally
{
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-manager/repository01" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-manager/repository02" )
.then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.delete( "template/archiva-repository-observer/repository02" )
.then( ).statusCode( 200 );
}
}
@Test
void assignRole() {
String token = getAdminToken( );
Map<String, Object> jsonAsMap = new HashMap<>( );
jsonAsMap.put( "user_id", "aragorn");
jsonAsMap.put( "email", "aragorn@lordoftherings.org" );
jsonAsMap.put( "full_name", "Aragorn King of Gondor " );
jsonAsMap.put( "password", "pAssw0rD" );
try
{
given( ).spec( getRequestSpec( token, getUserServicePath() ) ).contentType( JSON )
.body( jsonAsMap )
.when( )
.post( )
.then( ).statusCode( 201 );
Response response = given( ).spec( getRequestSpec( token, getUserServicePath() ) ).contentType( JSON )
.when( )
.get( "aragorn/roles" )
.then( ).statusCode( 200 ).extract( ).response( );
List<RoleInfo> roles = response.getBody( ).jsonPath( ).getList( "", RoleInfo.class );
assertFalse( roles.stream( ).filter( role -> "system-administrator".equals( role.getId( ) ) ).findAny( ).isPresent( ) );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.put( "system-administrator/assign/aragorn" )
.prettyPeek()
.then( ).statusCode( 200 );
response = given( ).spec( getRequestSpec( token, getUserServicePath() ) ).contentType( JSON )
.when( )
.get( "aragorn/roles" )
.then( ).statusCode( 200 ).extract( ).response( );
roles = response.getBody( ).jsonPath( ).getList( "", RoleInfo.class );
assertTrue( roles.stream( ).filter( role -> "system-administrator".equals( role.getId( ) ) ).findAny( ).isPresent( ) );
} finally
{
given( ).spec( getRequestSpec( token, getUserServicePath() ) ).contentType( JSON )
.when( )
.delete( "aragorn" ).getBody( );
}
}
}

View File

@ -18,10 +18,13 @@ package org.apache.archiva.redback.rest.services.v2;
* under the License.
*/
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import org.apache.archiva.redback.rest.api.model.v2.BaseRoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.Operation;
import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.RegistrationKey;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.model.v2.VerificationStatus;
import org.apache.archiva.redback.rest.services.mock.EmailMessage;
@ -44,6 +47,7 @@ import java.util.Map;
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
import static org.apache.archiva.redback.rest.api.Constants.DEFAULT_PAGE_LIMIT;
import static org.junit.jupiter.api.Assertions.*;
/**
@ -87,7 +91,7 @@ public class NativeUserServiceTest extends AbstractNativeRestServices
assertNotNull( userData );
assertEquals( 2, userData.size( ) );
assertEquals( Integer.valueOf( 0 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
assertEquals( Integer.valueOf( 1000 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( DEFAULT_PAGE_LIMIT ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( 2 ), response.body( ).jsonPath( ).get( "pagination.total_count" ) );
}
@ -134,7 +138,7 @@ public class NativeUserServiceTest extends AbstractNativeRestServices
assertEquals( "admin", userData.get( 0 ).getUserId( ) );
assertEquals( userNum + 2, userData.size( ) );
assertEquals( Integer.valueOf( 0 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
assertEquals( Integer.valueOf( 1000 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( DEFAULT_PAGE_LIMIT ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
assertEquals( Integer.valueOf( userNum + 2 ), response.body( ).jsonPath( ).get( "pagination.total_count" ) );
}
@ -1508,4 +1512,128 @@ public class NativeUserServiceTest extends AbstractNativeRestServices
.then( ).statusCode( 200 );
}
}
@Test
void getUserRoles() {
String adminToken = getAdminToken( );
Map<String, Object> userMap = new HashMap<>( );
userMap.put( "user_id", "bilbo" );
userMap.put( "email", "bilbo@lordoftherings.org" );
userMap.put( "full_name", "Bilbo Beutlin" );
userMap.put( "validated", true );
userMap.put( "password", "pAssw0rD" );
userMap.put( "confirm_password", "pAssw0rD" );
given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.body( userMap )
.when( )
.post( )
.then( ).statusCode( 201 );
try
{
Response response = given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.when( )
.get( "bilbo/roles" )
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
JsonPath jsonPath = response.getBody( ).jsonPath( );
List<RoleInfo> roleList = jsonPath.getList( "", RoleInfo.class );
assertEquals( 1, roleList.size( ) );
assertEquals( "registered-user", roleList.get( 0 ).getId( ) );
response = given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.when( )
.get( "admin/roles" )
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
jsonPath = response.getBody( ).jsonPath( );
roleList = jsonPath.getList( "", RoleInfo.class );
jsonPath.prettyPrint( );
assertEquals( 4, roleList.size( ) );
assertTrue( roleList.stream( ).filter( role -> "system-administrator".equals( role.getId( ) ) ).findAny( ).isPresent( ) );
assertTrue( roleList.stream( ).filter( role -> "archiva-global-repository-manager".equals( role.getId( ) ) ).findAny( ).isPresent( ) );
assertTrue( roleList.stream( ).filter( role -> "archiva-global-repository-observer".equals( role.getId( ) ) ).findAny( ).isPresent( ) );
assertTrue( roleList.stream( ).filter( role -> "user-administrator".equals( role.getId( ) ) ).findAny( ).isPresent( ) );
}
finally
{
given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.delete( "bilbo" )
.then( ).statusCode( 200 );
}
}
@Test
void getRoleTree() {
String adminToken = getAdminToken( );
Map<String, Object> userMap = new HashMap<>( );
userMap.put( "user_id", "bilbo" );
userMap.put( "email", "bilbo@lordoftherings.org" );
userMap.put( "full_name", "Bilbo Beutlin" );
userMap.put( "validated", true );
userMap.put( "password", "pAssw0rD" );
userMap.put( "confirm_password", "pAssw0rD" );
given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.body( userMap )
.when( )
.post( )
.then( ).statusCode( 201 );
try
{
Response response = given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.when( )
.get( "bilbo/roletree" )
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
JsonPath jsonPath = response.getBody( ).jsonPath( );
assertTrue( jsonPath.getMap( "applications" ).containsKey( "System" ) );
assertTrue( jsonPath.getMap( "applications" ).containsKey( "Archiva" ) );
List<BaseRoleInfo> roleList = jsonPath.getList( "root_roles", BaseRoleInfo.class );
assertEquals( 3, roleList.size( ) );
assertTrue( roleList.stream( ).filter( role -> role.getId( ).equals( "guest" ) ).findFirst( ).isPresent( ) );
BaseRoleInfo registered = roleList.stream( ).filter( role -> role.getId( ).equals( "registered-user" ) ).findFirst( ).get( );
assertTrue( registered.isAssigned( ) );
BaseRoleInfo sysadmin = roleList.stream( ).filter( role -> role.getId( ).equals( "system-administrator" ) ).findFirst( ).get( );
assertFalse( sysadmin.isAssigned( ) );
assertFalse( sysadmin.isChild( ) );
assertEquals( 2, sysadmin.getChildren( ).size( ) );
assertTrue( sysadmin.getChildren( ).stream( ).filter( role -> role.getId( ).equals( "user-administrator" ) ).findFirst( ).isPresent( ) );
response = given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.when( )
.get( "admin/roletree" )
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
System.out.println( response.getBody( ).prettyPrint( ) );
jsonPath = response.getBody( ).jsonPath( );
assertTrue( jsonPath.getMap( "applications" ).containsKey( "System" ) );
assertTrue( jsonPath.getMap( "applications" ).containsKey( "Archiva" ) );
roleList = jsonPath.getList( "root_roles", BaseRoleInfo.class );
assertEquals( 3, roleList.size( ) );
assertTrue( roleList.stream( ).filter( role -> role.getId( ).equals( "guest" ) ).findFirst( ).isPresent( ) );
registered = roleList.stream( ).filter( role -> role.getId( ).equals( "registered-user" ) ).findFirst( ).get( );
assertFalse( registered.isAssigned( ) );
sysadmin = roleList.stream( ).filter( role -> role.getId( ).equals( "system-administrator" ) ).findFirst( ).get( );
assertTrue( sysadmin.isAssigned( ) );
assertFalse( sysadmin.isChild( ) );
assertEquals( 2, sysadmin.getChildren( ).size( ) );
assertTrue( sysadmin.getChildren( ).stream( ).filter( role -> role.getId( ).equals( "user-administrator" ) ).findFirst( ).isPresent( ) );
}
finally
{
given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON )
.delete( "bilbo" )
.then( ).statusCode( 200 );
}
}
}

View File

@ -33,6 +33,7 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* AbstractRBACManager
@ -499,7 +500,7 @@ public abstract class AbstractRBACManager
if ( role.hasChildRoles() )
{
Map<String, ? extends Role> childRoles = getChildRoles( role );
Map<String, ? extends Role> childRoles = getChildRoleNames( role );
Iterator<? extends Role> it = childRoles.values().iterator();
while ( it.hasNext() )
{
@ -736,11 +737,11 @@ public abstract class AbstractRBACManager
throws RbacObjectInvalidException, RbacManagerException
{
saveRole( childRole );
role.addChildRoleName( childRole.getName() );
role.addChildRole( childRole );
}
@Override
public Map<String, ? extends Role> getChildRoles( Role role )
public Map<String, ? extends Role> getChildRoleNames( Role role )
throws RbacManagerException
{
Map<String, Role> childRoles = new HashMap<String, Role>();
@ -797,7 +798,64 @@ public abstract class AbstractRBACManager
}
@Override
public Map<String, ? extends Role> getParentRoles( Role role )
public Map<String, ? extends Role> getChildRoleIds( Role role )
throws RbacManagerException
{
Map<String, Role> childRoles = new HashMap<String, Role>();
boolean childRoleNamesUpdated = false;
Iterator<String> it = role.getChildRoleIds().listIterator();
final List<String> updatedChildRoleList = new ArrayList<String>( role.getChildRoleIds().size() );
while ( it.hasNext() )
{
String roleId = it.next();
try
{
Role child = getRoleById( roleId );
// archiva can change role manager but LDAP can be non writable so in such case
// some roles doesn't exists !!
if ( child != null )
{
childRoles.put( child.getId(), child );
updatedChildRoleList.add( roleId );
}
else
{
log.warn(
"error searching role with name '{}' probably some issues when migrating your role manager",
roleId );
}
}
catch ( RbacObjectNotFoundException e )
{
// Found a bad roleName! - trigger new List save
//it.remove();
childRoleNamesUpdated = true;
}
catch ( RbacManagerException e )
{
if ( !( e.getCause() instanceof RbacObjectNotFoundException ) )
{
throw e;
}
childRoleNamesUpdated = true;
}
}
if ( childRoleNamesUpdated )
{
role.setChildRoleIds( updatedChildRoleList );
saveRole( role );
}
return childRoles;
}
@Override
public Map<String, ? extends Role> getParentRoleNames( Role role )
throws RbacManagerException
{
Map<String, Role> parentRoles = new HashMap<String, Role>();
@ -822,6 +880,23 @@ public abstract class AbstractRBACManager
return parentRoles;
}
@Override
public Map<String, ? extends Role> getParentRoleIds( final Role role ) throws RbacManagerException
{
return getAllRoles( ).stream( ).filter( r -> !r.getId( ).equals( role.getId( ) ) )
.filter( r -> {
try
{
return getEffectiveRoles( r ).stream( ).map( Role::getId ).filter( cRoleId -> cRoleId.equals( role.getId( ) ) ).findAny( ).isPresent( );
}
catch ( RbacManagerException e )
{
return false;
}
}
).distinct().collect( Collectors.toMap( Role::getId, Function.identity( ) ) );
}
@Override
public Set<? extends Role> getEffectiveRoles( Role role )
throws RbacObjectNotFoundException, RbacManagerException

View File

@ -29,7 +29,7 @@ public abstract class AbstractRole
@Override
public boolean hasChildRoles()
{
return ( getChildRoleNames() != null ) && !getChildRoleNames().isEmpty();
return ( getChildRoleIds() != null ) && !getChildRoleIds().isEmpty();
}
/**
@ -57,4 +57,11 @@ public abstract class AbstractRole
return result;
}
@Override
public void addChildRole( Role child )
{
addChildRoleName( child.getName() );
addChildRoleId( child.getId() );
}
}

View File

@ -155,21 +155,39 @@ public interface RBACManager
throws RbacObjectInvalidException, RbacManagerException;
/**
* Returns all the child roles of a given role.
* Returns all the child roles of a given role as (name, role) pairs.
* @param role the parent role
* @return the list of child roles
* @throws RbacManagerException if the access to the backend datastore failed
*/
Map<String, ? extends Role> getChildRoles( Role role )
Map<String, ? extends Role> getChildRoleNames( Role role )
throws RbacManagerException;
/**
* Returns all the parent roles of a given role.
* Returns all the child roles of a given role as (role id, role) pairs.
* @param role the parent role
* @return the map of child roles as (role id, role) pairs
* @throws RbacManagerException if the access to the backend datastore failed
*/
Map<String, ? extends Role> getChildRoleIds( Role role )
throws RbacManagerException;
/**
* Returns all the parent roles of a given role as map of (name, role) elements.
* @param role the role to check for parent roles
* @return the list of parent roles that have <code>role</code> als child
* @throws RbacManagerException if the access to the backend datastore failed
*/
Map<String, ? extends Role> getParentRoles( Role role )
Map<String, ? extends Role> getParentRoleNames( Role role )
throws RbacManagerException;
/**
* Returns all the parent roles of a given role as map of (id, role) elements.
* @param role the role to check for parents roles
* @return a map of (role id, role) pairs that have <code>role</code> as child
* @throws RbacManagerException if the access to the backend datastore failed
*/
Map<String, ? extends Role> getParentRoleIds( Role role )
throws RbacManagerException;
/**

View File

@ -58,6 +58,24 @@ public interface Role
*/
List<String> getChildRoleNames();
/**
* Adds a child role and sets the list of child names and child ids.
* @param child the child role
*/
void addChildRole( Role child );
/**
* Adds a child role id
* @param id the id
*/
void addChildRoleId( String id );
/**
* Returns the child role ids
* @return the list of child role ids
*/
List<String> getChildRoleIds();
/**
* Convenience method to see if Role has Child Roles.
*
@ -114,6 +132,12 @@ public interface Role
*/
void setChildRoleNames( List<String> names );
/**
* Sets the list of child role ids
* @param ids
*/
void setChildRoleIds( List<String> ids );
/**
* Set the Description
*
@ -220,4 +244,6 @@ public interface Role
* @param resource the resource identifier. Must not be null.
*/
void setResource( String resource );
}

View File

@ -291,19 +291,33 @@ public class CachedRbacManager
}
@Override
public Map<String, ? extends Role> getChildRoles( Role role )
public Map<String, ? extends Role> getChildRoleNames( Role role )
throws RbacManagerException
{
log.debug( "NOT CACHED - .getChildRoles(Role)" );
return this.rbacImpl.getChildRoles( role );
return this.rbacImpl.getChildRoleNames( role );
}
@Override
public Map<String, ? extends Role> getParentRoles( Role role )
public Map<String, ? extends Role> getChildRoleIds( Role role ) throws RbacManagerException
{
log.debug( "NOT CACHED - .getChildRoles(Role)" );
return this.rbacImpl.getChildRoleIds( role );
}
@Override
public Map<String, ? extends Role> getParentRoleNames( Role role )
throws RbacManagerException
{
log.debug( "NOT CACHED - .getParentRoles(Role)" );
return this.rbacImpl.getParentRoles( role );
return this.rbacImpl.getParentRoleNames( role );
}
@Override
public Map<String, ? extends Role> getParentRoleIds( Role role ) throws RbacManagerException
{
log.debug( "NOT CACHED - .getParentRoles(Role)" );
return this.rbacImpl.getParentRoleIds( role );
}
@Override

View File

@ -35,7 +35,7 @@ import org.apache.archiva.redback.rbac.jpa.model.JpaPermission;
import org.apache.archiva.redback.rbac.jpa.model.JpaResource;
import org.apache.archiva.redback.rbac.jpa.model.JpaRole;
import org.apache.archiva.redback.rbac.jpa.model.JpaUserAssignment;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.archiva.redback.rbac.jpa.model.RoleId;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
@ -44,9 +44,6 @@ import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ -138,8 +135,15 @@ public class JpaRbacManager extends AbstractRBACManager {
@Transactional
@Override
public Map<String, ? extends Role> getChildRoles(Role role) throws RbacManagerException {
return super.getChildRoles(role);
public Map<String, ? extends Role> getChildRoleNames( Role role) throws RbacManagerException {
return super.getChildRoleNames(role);
}
@Transactional
@Override
public Map<String, ? extends Role> getChildRoleIds( Role role ) throws RbacManagerException
{
return super.getChildRoleIds( role );
}
@Transactional
@ -219,7 +223,7 @@ public class JpaRbacManager extends AbstractRBACManager {
throw new RbacPermanentException( "Unable to delete permanent role [" + role.getName() + "]" );
}
final EntityManager em = getEm();
JpaRole myRole = em.find(JpaRole.class, role.getName());
JpaRole myRole = em.find(JpaRole.class, new RoleId( role.getId(), role.getName()));
if (myRole == null) {
throw new RbacObjectNotFoundException("Role not found "+role.getName());
}

View File

@ -21,6 +21,7 @@ package org.apache.archiva.redback.rbac.jpa.model;
import org.apache.archiva.redback.rbac.AbstractRole;
import org.apache.archiva.redback.rbac.Permission;
import org.apache.archiva.redback.rbac.Role;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
@ -37,14 +38,16 @@ import java.util.List;
@Table(
name="SECURITY_ROLES"
)
@IdClass( RoleId.class )
public class JpaRole extends AbstractRole implements Serializable {
private static final Logger log = LoggerFactory.getLogger( JpaRole.class );
private static final long serialVersionUID = 4564608138465995665L;
@Id
@Column(name="NAME")
@Column(name="NAME", unique = true)
private String name;
@Id
@Column( name = "ID", unique = true )
private String id;
@Column(name="DESCRIPTION")
@ -75,6 +78,17 @@ public class JpaRole extends AbstractRole implements Serializable {
)
List<String> childRoleNames = new ArrayList<String>();
@ElementCollection(fetch = FetchType.EAGER)
@OrderColumn(name="INTEGER_IDX",nullable = false)
@Column(name="CHILD_IDS")
@CollectionTable(
name="SECURITY_ROLE_CHILDROLE_ID_MAP",
joinColumns = {
@JoinColumn(name="ID_OID",referencedColumnName = "ID", nullable = false)
}
)
List<String> childRoleIds = new ArrayList<String>();
@Column(name="TEMPLATE_INSTANCE",nullable = false)
private Boolean templateInstance = false;
@ -101,11 +115,23 @@ public class JpaRole extends AbstractRole implements Serializable {
this.childRoleNames.add(name);
}
@Override
public void addChildRoleId( String id )
{
this.childRoleIds.add( id );
}
@Override
public List<String> getChildRoleNames() {
return childRoleNames;
}
@Override
public List<String> getChildRoleIds( )
{
return childRoleIds;
}
@Override
public String getDescription() {
return description;
@ -142,6 +168,13 @@ public class JpaRole extends AbstractRole implements Serializable {
this.childRoleNames.addAll(names);
}
@Override
public void setChildRoleIds( List<String> childRoleIds )
{
this.childRoleIds.clear();
this.childRoleIds.addAll( childRoleIds );
}
@Override
public void setDescription(String description) {
this.description=description;
@ -245,12 +278,15 @@ public class JpaRole extends AbstractRole implements Serializable {
JpaRole jpaRole = (JpaRole) o;
return name.equals( jpaRole.name );
if ( !name.equals( jpaRole.name ) ) return false;
return id.equals( jpaRole.id );
}
@Override
public int hashCode( )
{
return name.hashCode( );
int result = name.hashCode( );
result = 31 * result + id.hashCode( );
return result;
}
}

View File

@ -0,0 +1,59 @@
package org.apache.archiva.redback.rbac.jpa.model;/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.Serializable;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class RoleId implements Serializable
{
private static final long serialVersionUID = -3358026083136193536L;
private String id;
private String name;
public RoleId( )
{
}
public RoleId( String id, String name )
{
this.id = id;
this.name = name;
}
@Override
public boolean equals( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass( ) != o.getClass( ) ) return false;
RoleId roleId = (RoleId) o;
if ( !id.equals( roleId.id ) ) return false;
return name.equals( roleId.name );
}
@Override
public int hashCode( )
{
int result = id.hashCode( );
result = 31 * result + name.hashCode( );
return result;
}
}

View File

@ -60,10 +60,8 @@ import javax.naming.directory.DirContext;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -474,17 +472,29 @@ public class LdapRbacManager
}
@Override
public Map<String, ? extends Role> getChildRoles( Role role )
public Map<String, ? extends Role> getChildRoleNames( Role role )
throws RbacManagerException
{
return this.rbacImpl.getChildRoles( role );
return this.rbacImpl.getChildRoleNames( role );
}
@Override
public Map<String, ? extends Role> getParentRoles( Role role )
public Map<String, ? extends Role> getChildRoleIds( Role role ) throws RbacManagerException
{
return this.rbacImpl.getChildRoleIds( role );
}
@Override
public Map<String, ? extends Role> getParentRoleNames( Role role )
throws RbacManagerException
{
return this.rbacImpl.getParentRoles( role );
return this.rbacImpl.getParentRoleNames( role );
}
@Override
public Map<String, ? extends Role> getParentRoleIds( Role role ) throws RbacManagerException
{
return this.rbacImpl.getParentRoleIds( role );
}
//
@ -1241,9 +1251,10 @@ public class LdapRbacManager
private boolean isTemplateInstance=false;
private String resource="";
private List<Permission> permissions = new ArrayList<Permission>();
private List<Permission> permissions = new ArrayList<>();
private List<String> childRoleNames = new ArrayList<String>();
private List<String> childRoleNames = new ArrayList<>();
private List<String> childRoleIds = new ArrayList<>( );
private RoleImpl( String name )
{
@ -1280,6 +1291,18 @@ public class LdapRbacManager
return this.childRoleNames;
}
@Override
public void addChildRoleId( String id )
{
this.childRoleIds.add( id );
}
@Override
public List<String> getChildRoleIds( )
{
return this.childRoleIds;
}
@Override
public String getDescription()
{
@ -1322,6 +1345,12 @@ public class LdapRbacManager
this.childRoleNames = names;
}
@Override
public void setChildRoleIds( List<String> ids )
{
}
@Override
public void setDescription( String description )
{

View File

@ -61,6 +61,8 @@ public class MemoryRole
*/
private List<String> childRoleNames = new ArrayList<>( 0 );
private List<String> childRoleIds = new ArrayList<>( 0 );
/**
* Field permissions
*/
@ -110,6 +112,20 @@ public class MemoryRole
return this.childRoleNames;
}
@Override
public void addChildRoleId( String id )
{
this.childRoleIds.add( id );
}
@Override
public List<String> getChildRoleIds( )
{
return this.childRoleIds;
}
@Override
public String getDescription()
{
@ -198,6 +214,12 @@ public class MemoryRole
}
}
@Override
public void setChildRoleIds( List<String> ids )
{
}
@Override
public boolean isPermanent()
{

View File

@ -21,6 +21,7 @@ package org.apache.archiva.redback.role;
import org.apache.archiva.redback.rbac.RBACManager;
import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
import org.apache.archiva.redback.rbac.Role;
import org.apache.archiva.redback.rbac.UserAssignment;
import org.apache.archiva.redback.role.model.ModelApplication;
@ -184,10 +185,10 @@ public class DefaultRoleManager
* resolving the ${resource} expression
*/
@Override
public void createTemplatedRole( String templateId, String resource )
public String createTemplatedRole( String templateId, String resource )
throws RoleManagerException
{
templateProcessor.create( blessedModel, templateId, resource );
return templateProcessor.create( blessedModel, templateId, resource );
}
/**
@ -198,13 +199,10 @@ public class DefaultRoleManager
public void removeTemplatedRole( String templateId, String resource )
throws RoleManagerException
{
ModelTemplate template = RoleModelUtils.getModelTemplate( blessedModel, templateId );
String roleName = template.getNamePrefix() + template.getDelimiter() + resource;
String roleId = templateProcessor.getRoleId( templateId, resource );
try
{
Role role = rbacManager.getRole( roleName );
Role role = rbacManager.getRoleById( roleId );
for ( UserAssignment assignment : rbacManager.getUserAssignmentsForRoles(
Arrays.asList( role.getName() ) ) )
@ -213,10 +211,12 @@ public class DefaultRoleManager
rbacManager.saveUserAssignment( assignment );
}
} catch ( RbacObjectNotFoundException e) {
throw new RoleNotFoundException( e.getMessage( ), e );
}
catch ( RbacManagerException e )
{
throw new RoleManagerException( "unable to remove role", e );
throw new RoleManagerException( "Unable to remove role", e );
}
templateProcessor.remove( blessedModel, templateId, resource );
@ -229,11 +229,11 @@ public class DefaultRoleManager
* because of the use of the name as an identifier
*/
@Override
public void moveTemplatedRole( String templateId, String oldResource, String newResource )
public String moveTemplatedRole( String templateId, String oldResource, String newResource )
throws RoleManagerException
{
// make the new role
templateProcessor.create( blessedModel, templateId, newResource );
String roleId = templateProcessor.create( blessedModel, templateId, newResource );
ModelTemplate template = RoleModelUtils.getModelTemplate( blessedModel, templateId );
@ -259,6 +259,7 @@ public class DefaultRoleManager
}
templateProcessor.remove( blessedModel, templateId, oldResource );
return roleId;
}
@Override
@ -269,7 +270,7 @@ public class DefaultRoleManager
if ( modelRole == null )
{
throw new RoleManagerException( "Unable to assign role: " + roleId + " does not exist." );
throw new RoleNotFoundException( "Unable to assign role: " + roleId + " does not exist." );
}
try

View File

@ -0,0 +1,33 @@
package org.apache.archiva.redback.role;/*
* 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 RoleExistsException extends RoleManagerException
{
public RoleExistsException( String string )
{
super( string );
}
public RoleExistsException( String string, Throwable throwable )
{
super( string, throwable );
}
}

View File

@ -53,7 +53,7 @@ public interface RoleManager
* @param resource
* @throws RoleManagerException
*/
void createTemplatedRole( String templateId, String resource )
String createTemplatedRole( String templateId, String resource )
throws RoleManagerException;
/**
@ -78,7 +78,7 @@ public interface RoleManager
* @param newResource the new resource name
* @throws RoleManagerException
*/
void moveTemplatedRole( String templateId, String oldResource, String newResource )
String moveTemplatedRole( String templateId, String oldResource, String newResource )
throws RoleManagerException;

View File

@ -0,0 +1,33 @@
package org.apache.archiva.redback.role;/*
* 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 RoleNotFoundException extends RoleManagerException
{
public RoleNotFoundException( String string )
{
super( string );
}
public RoleNotFoundException( String string, Throwable throwable )
{
super( string, throwable );
}
}

View File

@ -216,6 +216,7 @@ public class DefaultRoleModelProcessor
{
ModelRole childRoleProfile = RoleModelUtils.getModelRole( model, childRoleId );
role.addChildRoleName( childRoleProfile.getName() );
role.addChildRoleId( childRoleProfile.getId() );
}
}
@ -229,7 +230,7 @@ public class DefaultRoleModelProcessor
{
ModelRole parentModelRole = RoleModelUtils.getModelRole( model, parentRoleId );
Role parentRole = rbacManager.getRole( parentModelRole.getName() );
parentRole.addChildRoleName( role.getName() );
parentRole.addChildRole( role );
rbacManager.saveRole( parentRole );
allRoleNames.add( parentRole.getName() );
}

View File

@ -25,7 +25,9 @@ import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.Resource;
import org.apache.archiva.redback.rbac.Role;
import org.apache.archiva.redback.rbac.RBACManager;
import org.apache.archiva.redback.role.RoleExistsException;
import org.apache.archiva.redback.role.RoleManagerException;
import org.apache.archiva.redback.role.RoleNotFoundException;
import org.apache.archiva.redback.role.model.ModelApplication;
import org.apache.archiva.redback.role.model.ModelOperation;
import org.apache.archiva.redback.role.model.ModelPermission;
@ -60,8 +62,9 @@ public class DefaultRoleTemplateProcessor
@Named(value = "rbacManager#default")
private RBACManager rbacManager;
@Override
@SuppressWarnings("unchecked")
public void create( RedbackRoleModel model, String templateId, String resource )
public String create( final RedbackRoleModel model, final String templateId, final String resource )
throws RoleManagerException
{
for ( ModelApplication application : model.getApplications() )
@ -74,16 +77,16 @@ public class DefaultRoleTemplateProcessor
processResource( template, resource );
// templates are roles that have yet to be paired with a resource for creation
processTemplate( model, template, resource );
return processTemplate( model, template, resource );
return;
}
}
}
throw new RoleManagerException( "unknown template '" + templateId + "'" );
throw new RoleNotFoundException( "unknown template '" + templateId + "'" );
}
@Override
@SuppressWarnings("unchecked")
public void remove( RedbackRoleModel model, String templateId, String resource )
throws RoleManagerException
@ -106,11 +109,11 @@ public class DefaultRoleTemplateProcessor
private void removeTemplatedRole( RedbackRoleModel model, ModelTemplate template, String resource )
throws RoleManagerException
{
String roleName = template.getNamePrefix() + template.getDelimiter() + resource;
String roleId = getRoleId( template.getId( ), resource );
try
{
Role role = rbacManager.getRole( roleName );
Role role = rbacManager.getRoleById( roleId );
if ( !role.isPermanent() )
{
@ -142,12 +145,12 @@ public class DefaultRoleTemplateProcessor
}
else
{
throw new RoleManagerException( "unable to remove role, it is flagged permanent" );
throw new RoleManagerException( "Unable to remove role, it is flagged permanent" );
}
}
catch ( RbacManagerException e )
{
throw new RoleManagerException( "unable to remove templated role: " + roleName, e );
throw new RoleManagerException( "Unable to remove templated role: " + roleId, e );
}
//catch ( RoleTemplateProcessorException e )
//{
@ -173,12 +176,17 @@ public class DefaultRoleTemplateProcessor
}
}
@Override
public String getRoleId( String templateId, String resource) {
return templateId + "." + resource;
}
@SuppressWarnings("unchecked")
private void processTemplate( RedbackRoleModel model, ModelTemplate template, String resource )
private String processTemplate( RedbackRoleModel model, ModelTemplate template, String resource )
throws RoleManagerException
{
final String templateName = template.getNamePrefix() + template.getDelimiter() + resource;
final String roleId = template.getId( ) + "." + resource;
final String roleId = getRoleId( template.getId( ), resource );
List<Permission> permissions = processPermissions( model, template, resource );
@ -190,7 +198,7 @@ public class DefaultRoleTemplateProcessor
}
catch ( RbacManagerException e )
{
throw new RoleManagerException( e.getMessage(), e );
throw new RoleExistsException( e.getMessage(), e );
}
if ( !roleExists )
@ -221,6 +229,7 @@ public class DefaultRoleTemplateProcessor
{
ModelRole childRoleProfile = RoleModelUtils.getModelRole( model, childRoleId );
role.addChildRoleName( childRoleProfile.getName() );
role.addChildRoleId( childRoleProfile.getId() );
}
}
@ -246,12 +255,14 @@ public class DefaultRoleTemplateProcessor
if ( rbacManager.roleExists( childRoleName ) )
{
role.addChildRoleName( childRoleName );
role.addChildRoleId( getRoleId( childTemplateId, resource ) );
}
else
{
processTemplate( model, childModelTemplate, resource );
role.addChildRoleName( childRoleName );
role.addChildRoleId( getRoleId( childTemplateId, resource ) );
}
}
}
@ -270,7 +281,7 @@ public class DefaultRoleTemplateProcessor
{
ModelRole parentModelRole = RoleModelUtils.getModelRole( model, parentRoleId );
Role parentRole = rbacManager.getRole( parentModelRole.getName() );
parentRole.addChildRoleName( role.getName() );
parentRole.addChildRole( role );
rbacManager.saveRole( parentRole );
}
}
@ -298,7 +309,7 @@ public class DefaultRoleTemplateProcessor
{
Role parentRole = rbacManager.getRole( parentRoleName );
parentRole.addChildRoleName( role.getName() );
parentRole.addChildRole( role );
rbacManager.saveRole( parentRole );
}
else
@ -307,7 +318,7 @@ public class DefaultRoleTemplateProcessor
Role parentRole = rbacManager.getRole( parentRoleName );
parentRole.addChildRoleName( role.getName() );
parentRole.addChildRole( role );
rbacManager.saveRole( parentRole );
}
}
@ -358,6 +369,7 @@ public class DefaultRoleTemplateProcessor
throw new RoleManagerException( "error updating role '" + templateName + "'", e );
}
}
return roleId;
}
@SuppressWarnings("unchecked")

View File

@ -30,9 +30,33 @@ import org.apache.archiva.redback.role.model.RedbackRoleModel;
public interface RoleTemplateProcessor
{
void create( RedbackRoleModel model, String templateId, String resource )
/**
* Creates a role instance from a template for the given resource and returns the id of the new role.
* @param model the model
* @param templateId the template identifier
* @param resource the resource to which the role is applied
* @return the id of the role
* @throws RoleManagerException if the access to the backend datastore failed
*/
String create( RedbackRoleModel model, String templateId, String resource )
throws RoleManagerException;
/**
* Removes the role instance that belongs to the template from the datastore
* @param model the model
* @param templateId the template identifier
* @param resource the resource to which the role is applied
* @throws RoleManagerException if the access to the backend datastore failed
*/
void remove( RedbackRoleModel model, String templateId, String resource )
throws RoleManagerException;
/**
* Returns the role id that identifies the role that is a instance of the given template for the given resource.
* @param templateId the template identifier
* @param resource the resource
* @return the role identifier
*/
String getRoleId( String templateId, String resource );
}

View File

@ -169,6 +169,7 @@ public class AbstractRbacManagerPerformanceTestCase
Role devRole = getDeveloperRole();
Role devPlusRole = getSuperDeveloperRole();
devPlusRole.setChildRoleNames( Collections.singletonList( devRole.getName() ) );
devPlusRole.setChildRoleIds( Collections.singletonList( devRole.getId() ) );
devRole = manager.saveRole( devRole );
devPlusRole = manager.saveRole( devPlusRole );
@ -197,6 +198,7 @@ public class AbstractRbacManagerPerformanceTestCase
username = "janet";
devPlusRole.setChildRoleNames( Collections.singletonList( devRole.getName() ) );
devPlusRole.setChildRoleIds( Collections.singletonList( devRole.getId() ) );
devRole = manager.saveRole( devRole );
manager.saveRole( devPlusRole );

View File

@ -91,7 +91,7 @@ public abstract class AbstractRbacManagerTestCase
private Role getAdminRole()
throws RbacManagerException
{
Role role = rbacManager.createRole( "ADMIN" );
Role role = rbacManager.createRole( "admin", "ADMIN" );
role.setAssignable( false );
Permission perm = rbacManager.createPermission( "EDIT_ANY_USER", "EDIT", "User:*" );
@ -375,6 +375,7 @@ public abstract class AbstractRbacManagerTestCase
manager.saveRole( projectRole );
develRole.addChildRoleName( projectRoleName );
develRole.addChildRoleId( projectRole.getId() );
manager.saveRole( develRole );
@ -428,7 +429,7 @@ public abstract class AbstractRbacManagerTestCase
Role adminRole = getAdminRole();
adminRole.addChildRoleName( developerRole.getName() );
adminRole.addChildRole( developerRole );
adminRole = manager.saveRole( adminRole );
@ -631,6 +632,7 @@ public abstract class AbstractRbacManagerTestCase
Role devRole = getDeveloperRole();
Role devPlusRole = getSuperDeveloperRole();
devPlusRole.setChildRoleNames( Collections.singletonList( devRole.getName() ) );
devPlusRole.setChildRoleIds( Collections.singletonList( devRole.getId() ) );
manager.saveRole( devRole );
manager.saveRole( devPlusRole );

View File

@ -159,6 +159,7 @@ public class RBACDefaults
{
Role admin = manager.createRole( "System Administrator" );
admin.addChildRoleName( "User Administrator" );
admin.addChildRoleId( "user-administrator" );
admin.addPermission( manager.getPermission( "Edit Configuration" ) );
admin.addPermission( manager.getPermission( "Run Indexer" ) );
admin.addPermission( manager.getPermission( "Add Repository" ) );
@ -171,6 +172,7 @@ public class RBACDefaults
{
Role developer = manager.createRole( "Trusted Developer" );
developer.addChildRoleName( "System Administrator" );
developer.addChildRoleId( "system-administrator" );
developer.addPermission( manager.getPermission( "Run Indexer" ) );
developer.setAssignable( true );
manager.saveRole( developer );
@ -180,6 +182,7 @@ public class RBACDefaults
{
Role developer = manager.createRole( "Developer" );
developer.addChildRoleName( "Trusted Developer" );
developer.addChildRoleId( "trusted-developer" );
developer.addPermission( manager.getPermission( "Run Indexer" ) );
developer.setAssignable( true );
manager.saveRole( developer );