WIP: introduce separate database schemas #102
38
doc/rbac.md
38
doc/rbac.md
@ -29,7 +29,7 @@ skinparam linetype ortho
|
||||
package RBAC {
|
||||
|
||||
' forward declarations
|
||||
entity RbacUser
|
||||
entity RbacSubject
|
||||
|
||||
together {
|
||||
|
||||
@ -37,8 +37,8 @@ package RBAC {
|
||||
entity RbacPermission
|
||||
|
||||
|
||||
RbacUser -[hidden]> RbacRole
|
||||
RbacRole -[hidden]> RbacUser
|
||||
RbacSubject -[hidden]> RbacRole
|
||||
RbacRole -[hidden]> RbacSubject
|
||||
}
|
||||
|
||||
together {
|
||||
@ -57,11 +57,11 @@ package RBAC {
|
||||
RbacGrant o-u-> RbacReference
|
||||
|
||||
enum RbacReferenceType {
|
||||
RbacUser
|
||||
RbacSubject
|
||||
RbacRole
|
||||
RbacPermission
|
||||
}
|
||||
RbacReferenceType ..> RbacUser
|
||||
RbacReferenceType ..> RbacSubject
|
||||
RbacReferenceType ..> RbacRole
|
||||
RbacReferenceType ..> RbacPermission
|
||||
|
||||
@ -71,12 +71,12 @@ package RBAC {
|
||||
type : RbacReferenceType
|
||||
}
|
||||
RbacReference o--> RbacReferenceType
|
||||
entity RbacUser {
|
||||
entity RbacSubject {
|
||||
*uuid : uuid <<generated>>
|
||||
--
|
||||
name : varchar
|
||||
}
|
||||
RbacUser o-- RbacReference
|
||||
RbacSubject o-- RbacReference
|
||||
|
||||
entity RbacRole {
|
||||
*uuid : uuid(RbacReference)
|
||||
@ -143,20 +143,20 @@ The primary key of the *RbacReference* and its referred object is always identic
|
||||
#### RbacReferenceType
|
||||
|
||||
The enum *RbacReferenceType* describes the type of reference.
|
||||
It's only needed to make it easier to find the referred object in *RbacUser*, *RbacRole* or *RbacPermission*.
|
||||
It's only needed to make it easier to find the referred object in *RbacSubject*, *RbacRole* or *RbacPermission*.
|
||||
|
||||
#### RbacUser
|
||||
#### RbacSubject
|
||||
|
||||
An *RbacUser* is a type of RBAC-subject which references a login account outside this system, identified by a name (usually an email-address).
|
||||
An *RbacSubject* is a type of RBAC-subject which references a login account outside this system, identified by a name (usually an email-address).
|
||||
|
||||
*RbacUser*s can be assigned to multiple *RbacRole*s, through which they can get permissions to *RbacObject*s.
|
||||
*RbacSubject*s can be assigned to multiple *RbacRole*s, through which they can get permissions to *RbacObject*s.
|
||||
|
||||
The primary key of the *RbacUser* is identical to its related *RbacReference*.
|
||||
The primary key of the *RbacSubject* is identical to its related *RbacReference*.
|
||||
|
||||
#### RbacRole
|
||||
|
||||
An *RbacRole* represents a collection of directly or indirectly assigned *RbacPermission*s.
|
||||
Each *RbacRole* can be assigned to *RbacUser*s or to another *RbacRole*.
|
||||
Each *RbacRole* can be assigned to *RbacSubject*s or to another *RbacRole*.
|
||||
|
||||
Both kinds of assignments are represented via *RbacGrant*.
|
||||
|
||||
@ -184,7 +184,7 @@ Only with this rule, the foreign key in *RbacPermission* can be defined as `NOT
|
||||
|
||||
#### RbacGrant
|
||||
|
||||
The *RbacGrant* entities represent the access-rights structure from *RbacUser*s via hierarchical *RbacRoles* down to *RbacPermission*s.
|
||||
The *RbacGrant* entities represent the access-rights structure from *RbacSubject*s via hierarchical *RbacRoles* down to *RbacPermission*s.
|
||||
|
||||
The core SQL queries to determine access rights are all recursive queries on the *RbacGrant* table.
|
||||
|
||||
@ -284,7 +284,7 @@ hide circle
|
||||
' use right-angled line routing
|
||||
' skinparam linetype ortho
|
||||
|
||||
package RbacUsers {
|
||||
package RbacSubjects {
|
||||
object UserMike
|
||||
object UserSuse
|
||||
object UserPaul
|
||||
@ -296,7 +296,7 @@ package RbacRoles {
|
||||
object RoleCustXyz_Admin
|
||||
object RolePackXyz00_Owner
|
||||
}
|
||||
RbacUsers -[hidden]> RbacRoles
|
||||
RbacSubjects -[hidden]> RbacRoles
|
||||
|
||||
package RbacPermissions {
|
||||
object PermCustXyz_SELECT
|
||||
@ -365,7 +365,7 @@ This way, each user can only select the data they have 'SELECT'-permission for,
|
||||
### Current User
|
||||
|
||||
The current use is taken from the session variable `hsadminng.currentSubject` which contains the name of the user as stored in the
|
||||
*RbacUser*s table. Example:
|
||||
*RbacSubject*s table. Example:
|
||||
|
||||
SET LOCAL hsadminng.currentSubject = 'mike@hostsharing.net';
|
||||
|
||||
@ -671,9 +671,9 @@ Access Control for business objects checked according to the assigned roles.
|
||||
But we decided not to create such roles and permissions for the RBAC-Objects itself.
|
||||
It would have overcomplicated the system and the necessary information can easily be added to the RBAC-Objects itself, mostly the `RbacGrant`s.
|
||||
|
||||
### RbacUser
|
||||
### RbacSubject
|
||||
|
||||
Users can self-register, thus to create a new RbacUser entity, no login is required.
|
||||
Users can self-register, thus to create a new RbacSubject entity, no login is required.
|
||||
But such a user has no access-rights except viewing itself.
|
||||
|
||||
Users can view themselves.
|
||||
|
@ -9,21 +9,21 @@ select isGranted(findRoleId('test_package#aaa00:OWNER'), findRoleId('administrat
|
||||
-- call grantRoleToRole(findRoleId('administrators'), findRoleId('test_package#aaa00:OWNER'));
|
||||
|
||||
select count(*)
|
||||
FROM queryAllPermissionsOfSubjectIdForObjectUuids(findRbacUser('superuser-fran@hostsharing.net'),
|
||||
FROM queryAllPermissionsOfSubjectIdForObjectUuids(findRbacSubject('superuser-fran@hostsharing.net'),
|
||||
ARRAY(select uuid from customer where reference < 1100000));
|
||||
select count(*)
|
||||
FROM queryAllPermissionsOfSubjectId(findRbacUser('superuser-fran@hostsharing.net'));
|
||||
FROM queryAllPermissionsOfSubjectId(findRbacSubject('superuser-fran@hostsharing.net'));
|
||||
select *
|
||||
FROM queryAllPermissionsOfSubjectId(findRbacUser('alex@example.com'));
|
||||
FROM queryAllPermissionsOfSubjectId(findRbacSubject('alex@example.com'));
|
||||
select *
|
||||
FROM queryAllPermissionsOfSubjectId(findRbacUser('rosa@example.com'));
|
||||
FROM queryAllPermissionsOfSubjectId(findRbacSubject('rosa@example.com'));
|
||||
|
||||
select *
|
||||
FROM queryAllRbacUsersWithPermissionsFor(findEffectivePermissionId('customer',
|
||||
FROM queryAllRbacSubjectsWithPermissionsFor(findEffectivePermissionId('customer',
|
||||
(SELECT uuid FROM RbacObject WHERE objectTable = 'customer' LIMIT 1),
|
||||
'add-package'));
|
||||
select *
|
||||
FROM queryAllRbacUsersWithPermissionsFor(findEffectivePermissionId('package',
|
||||
FROM queryAllRbacSubjectsWithPermissionsFor(findEffectivePermissionId('package',
|
||||
(SELECT uuid FROM RbacObject WHERE objectTable = 'package' LIMIT 1),
|
||||
'DELETE'));
|
||||
|
||||
@ -33,7 +33,7 @@ $$
|
||||
userId uuid;
|
||||
result bool;
|
||||
BEGIN
|
||||
userId = findRbacUser('superuser-alex@hostsharing.net');
|
||||
userId = findRbacSubject('superuser-alex@hostsharing.net');
|
||||
result = (SELECT * FROM isPermissionGrantedToSubject(findPermissionId('package', 94928, 'add-package'), userId));
|
||||
IF (result) THEN
|
||||
RAISE EXCEPTION 'expected permission NOT to be granted, but it is';
|
||||
|
@ -38,7 +38,7 @@ CREATE OR REPLACE RULE "_RETURN" AS
|
||||
SELECT * FROM customer WHERE isPermissionGrantedToSubject(findEffectivePermissionId('test_customer', id, 'SELECT'), rbac.currentSubjectUuid());
|
||||
SELECT * from cust_view LIMIT 10;
|
||||
|
||||
select queryAllPermissionsOfSubjectId(findRbacUser('superuser-alex@hostsharing.net'));
|
||||
select queryAllPermissionsOfSubjectId(findRbacSubject('superuser-alex@hostsharing.net'));
|
||||
|
||||
-- access control via view-rule with join to recursive permissions - really fast (38ms for 1 million rows)
|
||||
SET SESSION SESSION AUTHORIZATION DEFAULT;
|
||||
@ -80,10 +80,10 @@ SELECT * from cust_view where reference=1144150;
|
||||
select rr.uuid, rr.type from RbacGrants g
|
||||
join RbacReference RR on g.ascendantUuid = RR.uuid
|
||||
where g.descendantUuid in (
|
||||
select uuid from queryAllPermissionsOfSubjectId(findRbacUser('alex@example.com'))
|
||||
select uuid from queryAllPermissionsOfSubjectId(findRbacSubject('alex@example.com'))
|
||||
where objectTable='test_customer');
|
||||
|
||||
call grantRoleToUser(findRoleId('test_customer#aaa:ADMIN'), findRbacUser('aaaaouq@example.com'));
|
||||
call grantRoleToUser(findRoleId('test_customer#aaa:ADMIN'), findRbacSubject('aaaaouq@example.com'));
|
||||
|
||||
select queryAllPermissionsOfSubjectId(findRbacUser('aaaaouq@example.com'));
|
||||
select queryAllPermissionsOfSubjectId(findRbacSubject('aaaaouq@example.com'));
|
||||
|
||||
|
@ -22,7 +22,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.DELETE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.GUEST;
|
||||
|
@ -14,7 +14,7 @@ import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
||||
|
||||
|
@ -11,7 +11,7 @@ import java.io.IOException;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
|
||||
|
@ -45,7 +45,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.DELETE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
|
||||
|
@ -16,7 +16,7 @@ import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
||||
|
@ -24,7 +24,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.DELETE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
|
||||
|
@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingD
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
|
@ -27,7 +27,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingD
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.ROLE_TO_ROLE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.Part.AUTO_FETCH;
|
||||
import static org.apache.commons.collections4.SetUtils.hashSet;
|
||||
import static org.apache.commons.lang3.StringUtils.uncapitalize;
|
||||
@ -41,7 +41,7 @@ public class RbacView {
|
||||
|
||||
private final EntityAlias rootEntityAlias;
|
||||
|
||||
private final Set<RbacUserReference> userDefs = new LinkedHashSet<>();
|
||||
private final Set<RbacSubjectReference> userDefs = new LinkedHashSet<>();
|
||||
private final Set<RbacRoleDefinition> roleDefs = new LinkedHashSet<>();
|
||||
private final Set<RbacPermissionDefinition> permDefs = new LinkedHashSet<>();
|
||||
private final Map<String, EntityAlias> entityAliases = new HashMap<>() {
|
||||
@ -97,7 +97,7 @@ public class RbacView {
|
||||
RbacView(final String alias, final Class<? extends BaseEntity> entityClass) {
|
||||
rootEntityAlias = new EntityAlias(alias, entityClass);
|
||||
entityAliases.put(alias, rootEntityAlias);
|
||||
new RbacUserReference(CREATOR);
|
||||
new RbacSubjectReference(CREATOR);
|
||||
entityAliases.put("global", new EntityAlias("global"));
|
||||
}
|
||||
|
||||
@ -467,7 +467,7 @@ public class RbacView {
|
||||
return new RbacExampleRole(entityAlias, role);
|
||||
}
|
||||
|
||||
private RbacGrantDefinition grantRoleToSubject(final RbacRoleDefinition roleDefinition, final RbacUserReference user) {
|
||||
private RbacGrantDefinition grantRoleToSubject(final RbacRoleDefinition roleDefinition, final RbacSubjectReference user) {
|
||||
return findOrCreateGrantDef(roleDefinition, user).toCreate();
|
||||
}
|
||||
|
||||
@ -564,7 +564,7 @@ public class RbacView {
|
||||
@EqualsAndHashCode
|
||||
public class RbacGrantDefinition {
|
||||
|
||||
private final RbacUserReference userDef;
|
||||
private final RbacSubjectReference userDef;
|
||||
private final RbacRoleDefinition superRoleDef;
|
||||
private final RbacRoleDefinition subRoleDef;
|
||||
private final RbacPermissionDefinition permDef;
|
||||
@ -605,7 +605,7 @@ public class RbacView {
|
||||
register(this);
|
||||
}
|
||||
|
||||
public RbacGrantDefinition(final RbacRoleDefinition roleDef, final RbacUserReference userDef) {
|
||||
public RbacGrantDefinition(final RbacRoleDefinition roleDef, final RbacSubjectReference userDef) {
|
||||
this.userDef = userDef;
|
||||
this.subRoleDef = roleDef;
|
||||
this.superRoleDef = null;
|
||||
@ -770,7 +770,7 @@ public class RbacView {
|
||||
* @return
|
||||
* The grant definition for further chained calls.
|
||||
*/
|
||||
public RbacGrantDefinition owningUser(final RbacUserReference.UserRole userRole) {
|
||||
public RbacGrantDefinition owningUser(final RbacSubjectReference.UserRole userRole) {
|
||||
return grantRoleToSubject(this, findUserRef(userRole));
|
||||
}
|
||||
|
||||
@ -833,12 +833,12 @@ public class RbacView {
|
||||
}
|
||||
}
|
||||
|
||||
public RbacUserReference findUserRef(final RbacUserReference.UserRole userRole) {
|
||||
public RbacSubjectReference findUserRef(final RbacSubjectReference.UserRole userRole) {
|
||||
return userDefs.stream().filter(u -> u.role == userRole).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
@EqualsAndHashCode
|
||||
public class RbacUserReference {
|
||||
public class RbacSubjectReference {
|
||||
|
||||
public enum UserRole {
|
||||
GLOBAL_ADMIN,
|
||||
@ -847,7 +847,7 @@ public class RbacView {
|
||||
|
||||
final UserRole role;
|
||||
|
||||
public RbacUserReference(final UserRole creator) {
|
||||
public RbacSubjectReference(final UserRole creator) {
|
||||
this.role = creator;
|
||||
userDefs.add(this);
|
||||
}
|
||||
@ -885,7 +885,7 @@ public class RbacView {
|
||||
.orElseGet(() -> new RbacPermissionDefinition(entityAlias, perm, tableName, true)); // TODO: true => toCreate
|
||||
}
|
||||
|
||||
private RbacGrantDefinition findOrCreateGrantDef(final RbacRoleDefinition roleDefinition, final RbacUserReference user) {
|
||||
private RbacGrantDefinition findOrCreateGrantDef(final RbacRoleDefinition roleDefinition, final RbacSubjectReference user) {
|
||||
return grantDefs.stream()
|
||||
.filter(g -> g.subRoleDef == roleDefinition && g.userDef == user)
|
||||
.findFirst()
|
||||
|
@ -578,7 +578,7 @@ class RolesGrantsAndPermissionsGenerator {
|
||||
plPgSql.writeLn();
|
||||
}
|
||||
|
||||
private String toPlPgSqlReference(final RbacView.RbacUserReference userRef) {
|
||||
private String toPlPgSqlReference(final RbacView.RbacSubjectReference userRef) {
|
||||
return switch (userRef.role) {
|
||||
case CREATOR -> "currentSubjectUuid()";
|
||||
default -> throw new IllegalArgumentException("unknown user role: " + userRef);
|
||||
|
@ -50,7 +50,7 @@ public class RbacGrantController implements RbacGrantsApi {
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseEntity<List<RbacGrantResource>> listUserGrants(
|
||||
public ResponseEntity<List<RbacGrantResource>> listSubjectGrants(
|
||||
final String currentSubject,
|
||||
final String assumedRoles) {
|
||||
|
||||
@ -97,7 +97,7 @@ public class RbacGrantController implements RbacGrantsApi {
|
||||
|
||||
// TODO.feat: implement an endpoint to create a Mermaid flowchart with all grants of a given user
|
||||
// @GetMapping(
|
||||
// path = "/api/rbac/users/{subjectUuid}/grants",
|
||||
// path = "/api/rbac/subjects/{subjectUuid}/grants",
|
||||
// produces = {"text/vnd.mermaid"})
|
||||
// @Transactional(readOnly = true)
|
||||
// public ResponseEntity<String> allGrantsOfUserAsMermaid(
|
||||
|
@ -33,7 +33,7 @@ public class RbacGrantEntity {
|
||||
private UUID grantedRoleUuid;
|
||||
|
||||
@Column(name = "username", updatable = false, insertable = false)
|
||||
private String granteeUserName;
|
||||
private String granteeSubjectName;
|
||||
|
||||
@Id
|
||||
@Column(name = "subjectuuid")
|
||||
@ -60,7 +60,7 @@ public class RbacGrantEntity {
|
||||
|
||||
public String toDisplay() {
|
||||
return "{ grant role:" + grantedRoleIdName +
|
||||
" to user:" + granteeUserName +
|
||||
" to user:" + granteeSubjectName +
|
||||
" by role:" + grantedByRoleIdName +
|
||||
(assumed ? " and assume" : "") +
|
||||
" }";
|
||||
|
@ -1,46 +0,0 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface RbacUserRepository extends Repository<RbacUserEntity, UUID> {
|
||||
|
||||
@Query("""
|
||||
select u from RbacUserEntity u
|
||||
where :userName is null or u.name like concat(cast(:userName as text), '%')
|
||||
order by u.name
|
||||
""")
|
||||
List<RbacUserEntity> findByOptionalNameLike(String userName);
|
||||
|
||||
// bypasses the restricted view, to be able to grant rights to arbitrary user
|
||||
@Query(value = "select * from rbac.subject where name=:userName", nativeQuery = true)
|
||||
RbacUserEntity findByName(String userName);
|
||||
|
||||
RbacUserEntity findByUuid(UUID uuid);
|
||||
|
||||
@Query(value = "select * from grantedPermissions(:subjectUuid)", nativeQuery = true)
|
||||
List<RbacUserPermission> findPermissionsOfUserByUuid(UUID subjectUuid);
|
||||
|
||||
/*
|
||||
Can't use save/saveAndFlush from SpringData because the uuid is not generated on the entity level,
|
||||
but explicitly, and then SpringData check's if it exists using an SQL SELECT.
|
||||
And SQL SELECT needs a currentSubject which we don't yet have in the case of self registration.
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = "insert into RBacUser_RV (uuid, name) values( :#{#newUser.uuid}, :#{#newUser.name})", nativeQuery = true)
|
||||
void insert(final RbacUserEntity newUser);
|
||||
|
||||
default RbacUserEntity create(final RbacUserEntity rbacUserEntity) {
|
||||
if (rbacUserEntity.getUuid() == null) {
|
||||
rbacUserEntity.setUuid(UUID.randomUUID());
|
||||
}
|
||||
insert(rbacUserEntity);
|
||||
return rbacUserEntity;
|
||||
}
|
||||
|
||||
void deleteByUuid(UUID subjectUuid);
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.mapper.Mapper;
|
||||
import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacUsersApi;
|
||||
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacUserPermissionResource;
|
||||
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacUserResource;
|
||||
import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacSubjectsApi;
|
||||
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacSubjectPermissionResource;
|
||||
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacSubjectResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -15,7 +15,7 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
public class RbacUserController implements RbacUsersApi {
|
||||
public class RbacSubjectController implements RbacSubjectsApi {
|
||||
|
||||
@Autowired
|
||||
private Context context;
|
||||
@ -24,73 +24,73 @@ public class RbacUserController implements RbacUsersApi {
|
||||
private Mapper mapper;
|
||||
|
||||
@Autowired
|
||||
private RbacUserRepository rbacUserRepository;
|
||||
private RbacSubjectRepository rbacSubjectRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseEntity<RbacUserResource> createUser(
|
||||
final RbacUserResource body
|
||||
public ResponseEntity<RbacSubjectResource> createSubject(
|
||||
final RbacSubjectResource body
|
||||
) {
|
||||
context.define(null);
|
||||
|
||||
if (body.getUuid() == null) {
|
||||
body.setUuid(UUID.randomUUID());
|
||||
}
|
||||
final var saved = mapper.map(body, RbacUserEntity.class);
|
||||
rbacUserRepository.create(saved);
|
||||
final var saved = mapper.map(body, RbacSubjectEntity.class);
|
||||
rbacSubjectRepository.create(saved);
|
||||
final var uri =
|
||||
MvcUriComponentsBuilder.fromController(getClass())
|
||||
.path("/api/rbac.yaml/users/{id}")
|
||||
.buildAndExpand(saved.getUuid())
|
||||
.toUri();
|
||||
return ResponseEntity.created(uri).body(mapper.map(saved, RbacUserResource.class));
|
||||
return ResponseEntity.created(uri).body(mapper.map(saved, RbacSubjectResource.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseEntity<Void> deleteUserByUuid(
|
||||
public ResponseEntity<Void> deleteSubjectByUuid(
|
||||
final String currentSubject,
|
||||
final String assumedRoles,
|
||||
final UUID subjectUuid
|
||||
) {
|
||||
context.define(currentSubject, assumedRoles);
|
||||
|
||||
rbacUserRepository.deleteByUuid(subjectUuid);
|
||||
rbacSubjectRepository.deleteByUuid(subjectUuid);
|
||||
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseEntity<RbacUserResource> getUserById(
|
||||
public ResponseEntity<RbacSubjectResource> getSubjectById(
|
||||
final String currentSubject,
|
||||
final String assumedRoles,
|
||||
final UUID subjectUuid) {
|
||||
|
||||
context.define(currentSubject, assumedRoles);
|
||||
|
||||
final var result = rbacUserRepository.findByUuid(subjectUuid);
|
||||
final var result = rbacSubjectRepository.findByUuid(subjectUuid);
|
||||
if (result == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok(mapper.map(result, RbacUserResource.class));
|
||||
return ResponseEntity.ok(mapper.map(result, RbacSubjectResource.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseEntity<List<RbacUserResource>> listUsers(
|
||||
public ResponseEntity<List<RbacSubjectResource>> listSubjects(
|
||||
final String currentSubject,
|
||||
final String assumedRoles,
|
||||
final String userName
|
||||
) {
|
||||
context.define(currentSubject, assumedRoles);
|
||||
|
||||
return ResponseEntity.ok(mapper.mapList(rbacUserRepository.findByOptionalNameLike(userName), RbacUserResource.class));
|
||||
return ResponseEntity.ok(mapper.mapList(rbacSubjectRepository.findByOptionalNameLike(userName), RbacSubjectResource.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseEntity<List<RbacUserPermissionResource>> listUserPermissions(
|
||||
public ResponseEntity<List<RbacSubjectPermissionResource>> listSubjectPermissions(
|
||||
final String currentSubject,
|
||||
final String assumedRoles,
|
||||
final UUID subjectUuid
|
||||
@ -98,7 +98,7 @@ public class RbacUserController implements RbacUsersApi {
|
||||
context.define(currentSubject, assumedRoles);
|
||||
|
||||
return ResponseEntity.ok(mapper.mapList(
|
||||
rbacUserRepository.findPermissionsOfUserByUuid(subjectUuid),
|
||||
RbacUserPermissionResource.class));
|
||||
rbacSubjectRepository.findPermissionsOfUserByUuid(subjectUuid),
|
||||
RbacSubjectPermissionResource.class));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import lombok.*;
|
||||
import org.springframework.data.annotation.Immutable;
|
||||
@ -13,14 +13,14 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "rbacuser_rv")
|
||||
@Table(schema = "rbac", name = "subject_rv")
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Immutable
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RbacUserEntity {
|
||||
public class RbacSubjectEntity {
|
||||
|
||||
private static final int MAX_VALIDITY_DAYS = 21;
|
||||
private static DateTimeFormatter DATE_FORMAT_WITH_FULLHOUR = DateTimeFormatter.ofPattern("MM-dd-yyyy HH");
|
@ -1,8 +1,8 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface RbacUserPermission {
|
||||
public interface RbacSubjectPermission {
|
||||
|
||||
UUID getRoleUuid();
|
||||
String getRoleName();
|
@ -0,0 +1,46 @@
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface RbacSubjectRepository extends Repository<RbacSubjectEntity, UUID> {
|
||||
|
||||
@Query("""
|
||||
select u from RbacSubjectEntity u
|
||||
where :userName is null or u.name like concat(cast(:userName as text), '%')
|
||||
order by u.name
|
||||
""")
|
||||
List<RbacSubjectEntity> findByOptionalNameLike(String userName);
|
||||
|
||||
// bypasses the restricted view, to be able to grant rights to arbitrary user
|
||||
@Query(value = "select * from rbac.subject where name=:userName", nativeQuery = true)
|
||||
RbacSubjectEntity findByName(String userName);
|
||||
|
||||
RbacSubjectEntity findByUuid(UUID uuid);
|
||||
|
||||
@Query(value = "select * from rbac.grantedPermissions(:subjectUuid)", nativeQuery = true)
|
||||
List<RbacSubjectPermission> findPermissionsOfUserByUuid(UUID subjectUuid);
|
||||
|
||||
/*
|
||||
Can't use save/saveAndFlush from SpringData because the uuid is not generated on the entity level,
|
||||
but explicitly, and then SpringData check's if it exists using an SQL SELECT.
|
||||
And SQL SELECT needs a currentSubject which we don't yet have in the case of self registration.
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = "insert into rbac.subject_rv (uuid, name) values( :#{#newUser.uuid}, :#{#newUser.name})", nativeQuery = true)
|
||||
void insert(final RbacSubjectEntity newUser);
|
||||
|
||||
default RbacSubjectEntity create(final RbacSubjectEntity rbacSubjectEntity) {
|
||||
if (rbacSubjectEntity.getUuid() == null) {
|
||||
rbacSubjectEntity.setUuid(UUID.randomUUID());
|
||||
}
|
||||
insert(rbacSubjectEntity);
|
||||
return rbacSubjectEntity;
|
||||
}
|
||||
|
||||
void deleteByUuid(UUID subjectUuid);
|
||||
}
|
@ -15,7 +15,7 @@ import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacSubjectReference.UserRole.CREATOR;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
|
||||
|
@ -9,7 +9,7 @@ components:
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Identifying name of the currently logged in user.
|
||||
description: Identifying name of the current subject (e.g. user).
|
||||
|
||||
assumedRoles:
|
||||
name: assumed-roles
|
||||
@ -17,4 +17,4 @@ components:
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Semicolon-separated list of roles to assume. The current user needs to have the right to assume these roles.
|
||||
description: Semicolon-separated list of roles to assume. The current subject needs to have the right to assume these roles.
|
||||
|
@ -8,13 +8,13 @@ components:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Unauthorized:
|
||||
description: The current user is unknown or not authorized.
|
||||
description: The current subject is unknown or not authorized.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Forbidden:
|
||||
description: The current user or none of the assumed or roles is granted access to the resource.
|
||||
description: The current subject or none of the assumed or roles is granted access to the resource.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
@ -9,7 +9,7 @@ components:
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Identifying name of the currently logged in user.
|
||||
description: Identifying name of the currently logged in subject.
|
||||
|
||||
assumedRoles:
|
||||
name: assumed-roles
|
||||
@ -17,4 +17,4 @@ components:
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Semicolon-separated list of roles to assume. The current user needs to have the right to assume these roles.
|
||||
description: Semicolon-separated list of roles to assume. The current subject needs to have the right to assume these roles.
|
||||
|
@ -8,13 +8,13 @@ components:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Unauthorized:
|
||||
description: The current user is unknown or not authorized.
|
||||
description: The current subject is unknown or not authorized.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Forbidden:
|
||||
description: The current user or none of the assumed or roles is granted access to the resource.
|
||||
description: The current subject or none of the assumed or roles is granted access to the resource.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of all booking items for a specified project.
|
||||
description: Returns the list of all booking items for a specified project which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of all booking items for a specified project which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-booking-items
|
||||
operationId: listBookingItemsByProjectUuid
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of all booking projects for a specified debitor.
|
||||
description: Returns the list of all booking projects for a specified debitor which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of all booking projects for a specified debitor which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-booking-projects
|
||||
operationId: listBookingProjectsByDebitorUuid
|
||||
|
@ -9,7 +9,7 @@ components:
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Identifying name of the currently logged in user.
|
||||
description: Identifying name of the currently logged in subject.
|
||||
|
||||
assumedRoles:
|
||||
name: assumed-roles
|
||||
@ -17,4 +17,4 @@ components:
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Semicolon-separated list of roles to assume. The current user needs to have the right to assume these roles.
|
||||
description: Semicolon-separated list of roles to assume. The current subject needs to have the right to assume these roles.
|
||||
|
@ -8,13 +8,13 @@ components:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Unauthorized:
|
||||
description: The current user is unknown or not authorized.
|
||||
description: The current subject is unknown or not authorized.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
Forbidden:
|
||||
description: The current user or none of the assumed or roles is granted access to the resource.
|
||||
description: The current subject or none of the assumed or roles is granted access to the resource.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a filtered list of all hosting assets.
|
||||
description: Returns the list of all hosting assets which match the given filters and are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of all hosting assets which match the given filters and are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-hosting-assets
|
||||
operationId: listAssets
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) bankaccounts.
|
||||
description: Returns the list of (optionally filtered) bankaccounts which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) bankaccounts which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-bank-accounts
|
||||
operationId: listBankAccounts
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) contacts.
|
||||
description: Returns the list of (optionally filtered) contacts which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) contacts which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-contacts
|
||||
operationId: listContacts
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) cooperative asset transactions.
|
||||
description: Returns the list of (optionally filtered) cooperative asset transactions which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) cooperative asset transactions which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-coopAssets
|
||||
operationId: listCoopAssets
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) cooperative share transactions.
|
||||
description: Returns the list of (optionally filtered) cooperative share transactions which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) cooperative share transactions which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-coopShares
|
||||
operationId: listCoopShares
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) debitors.
|
||||
description: Returns the list of (optionally filtered) debitors which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) debitors which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-debitors
|
||||
operationId: listDebitors
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) memberships.
|
||||
description: Returns the list of memberships which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of memberships which are visible to the current subject or any of it's assumed roles.
|
||||
The list can optionally be filtered by either the `partnerUuid` or the `memberNumber` - not both at the same time.
|
||||
tags:
|
||||
- hs-office-memberships
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) business partners.
|
||||
description: Returns the list of (optionally filtered) business partners which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) business partners which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-partners
|
||||
operationId: listPartners
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) persons.
|
||||
description: Returns the list of (optionally filtered) persons which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) persons which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-persons
|
||||
operationId: listPersons
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) person relations for a given person.
|
||||
description: Returns the list of (optionally filtered) person relations of a given person and which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) person relations of a given person and which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-relations
|
||||
operationId: listRelations
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) SEPA Mandates.
|
||||
description: Returns the list of (optionally filtered) SEPA Mandates which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) SEPA Mandates which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-sepaMandates
|
||||
operationId: listSepaMandatesByIBAN
|
||||
|
@ -18,7 +18,7 @@ components:
|
||||
grantedRoleUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
granteeUserName:
|
||||
granteeSubjectName:
|
||||
type: string
|
||||
granteeSubjectUuid:
|
||||
type: string
|
||||
|
@ -18,7 +18,7 @@ get:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the user to whom the role was granted.
|
||||
description: UUID of the subject to who the role was granted.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@ -53,7 +53,7 @@ delete:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the user to whom the role was granted.
|
||||
description: UUID of the subject to which the role was granted.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
|
@ -1,7 +1,7 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-grants
|
||||
operationId: listUserGrants
|
||||
operationId: listSubjectGrants
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
|
@ -3,7 +3,7 @@ components:
|
||||
|
||||
schemas:
|
||||
|
||||
RbacUser:
|
||||
RbacSubject:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
@ -11,7 +11,7 @@ components:
|
||||
format: uuid
|
||||
name:
|
||||
type: string
|
||||
RbacUserPermission:
|
||||
RbacSubjectPermission:
|
||||
type: object
|
||||
properties:
|
||||
objectUuid:
|
@ -1,8 +1,8 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: 'List all visible permissions granted to the given user; reduced '
|
||||
operationId: listUserPermissions
|
||||
- rbac-subjects
|
||||
description: 'List all visible permissions granted to the given subject; reduced '
|
||||
operationId: listSubjectPermissions
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
@ -20,7 +20,7 @@ get:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUserPermission'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubjectPermission'
|
||||
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
@ -1,8 +1,8 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: 'Fetch a single user by its id, if visible for the current subject.'
|
||||
operationId: getUserById
|
||||
- rbac-subjects
|
||||
description: 'Fetch a single subject by its id, if visible for the current subject.'
|
||||
operationId: getSubjectById
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
@ -18,7 +18,7 @@ get:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
|
||||
"401":
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
@ -28,8 +28,8 @@ get:
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- rbac-users
|
||||
operationId: deleteUserByUuid
|
||||
- rbac-subjects
|
||||
operationId: deleteSubjectByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
@ -39,7 +39,7 @@ delete:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the user to delete.
|
||||
description: UUID of the subject to delete.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
@ -1,8 +1,8 @@
|
||||
get:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: List accessible RBAC users with optional filter by name.
|
||||
operationId: listUsers
|
||||
- rbac-subjects
|
||||
description: List accessible RBAC subjects with optional filter by name.
|
||||
operationId: listSubjects
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
@ -19,7 +19,7 @@ get:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
'401':
|
||||
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||
'403':
|
||||
@ -27,22 +27,22 @@ get:
|
||||
|
||||
post:
|
||||
tags:
|
||||
- rbac-users
|
||||
description: Create a new RBAC user.
|
||||
operationId: createUser
|
||||
- rbac-subjects
|
||||
description: Create a new RBAC subject (e.g. user).
|
||||
operationId: createSubject
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: 'rbac-user-schemas.yaml#/components/schemas/RbacUser'
|
||||
$ref: 'rbac-subject-schemas.yaml#/components/schemas/RbacSubject'
|
||||
'409':
|
||||
$ref: 'error-responses.yaml#/components/responses/Conflict'
|
||||
|
@ -8,14 +8,14 @@ servers:
|
||||
|
||||
paths:
|
||||
|
||||
/api/rbac/users:
|
||||
$ref: 'rbac-users.yaml'
|
||||
/api/rbac/subjects:
|
||||
$ref: 'rbac-subjects.yaml'
|
||||
|
||||
/api/rbac/users/{subjectUuid}/permissions:
|
||||
$ref: 'rbac-users-with-id-permissions.yaml'
|
||||
/api/rbac/subjects/{subjectUuid}/permissions:
|
||||
$ref: 'rbac-subjects-with-id-permissions.yaml'
|
||||
|
||||
/api/rbac/users/{subjectUuid}:
|
||||
$ref: 'rbac-users-with-uuid.yaml'
|
||||
/api/rbac/subjects/{subjectUuid}:
|
||||
$ref: 'rbac-subjects-with-uuid.yaml'
|
||||
|
||||
/api/rbac/roles:
|
||||
$ref: 'rbac-roles.yaml'
|
||||
|
@ -1,6 +1,6 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) customers.
|
||||
description: Returns the list of (optionally filtered) customers which are visible to the current user or any of it's assumed roles.
|
||||
description: Returns the list of (optionally filtered) customers which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- testCustomers
|
||||
operationId: listCustomers
|
||||
|
@ -204,8 +204,8 @@ execute function rbac.delete_grant_tf();
|
||||
Creates a view to the users table with additional columns
|
||||
for easier human readability.
|
||||
*/
|
||||
drop view if exists RbacUser_ev;
|
||||
create or replace view RbacUser_ev as
|
||||
drop view if exists rbac.subject_ev;
|
||||
create or replace view rbac.subject_ev as
|
||||
select distinct *
|
||||
-- @formatter:off
|
||||
from (
|
||||
@ -229,8 +229,8 @@ select distinct *
|
||||
Creates a view to the users table with row-level limitation
|
||||
based on the grants of the current user or assumed roles.
|
||||
*/
|
||||
drop view if exists RbacUser_rv;
|
||||
create or replace view RbacUser_rv as
|
||||
drop view if exists rbac.subject_rv;
|
||||
create or replace view rbac.subject_rv as
|
||||
select distinct *
|
||||
-- @formatter:off
|
||||
from (
|
||||
@ -247,7 +247,7 @@ create or replace view RbacUser_rv as
|
||||
) as unordered
|
||||
-- @formatter:on
|
||||
order by unordered.name;
|
||||
grant all privileges on RbacUser_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
grant all privileges on rbac.subject_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
@ -255,9 +255,9 @@ grant all privileges on RbacUser_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Instead of insert trigger function for RbacUser_rv.
|
||||
Instead of insert trigger function for rbac.subject_rv.
|
||||
*/
|
||||
create or replace function insertRbacUser()
|
||||
create or replace function rbac.insert_subject_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
declare
|
||||
@ -277,13 +277,13 @@ end;
|
||||
$$;
|
||||
|
||||
/*
|
||||
Creates an instead of insert trigger for the RbacUser_rv view.
|
||||
Creates an instead of insert trigger for the rbac.subject_rv view.
|
||||
*/
|
||||
create trigger insertRbacUser_Trigger
|
||||
create trigger insert_subject_tg
|
||||
instead of insert
|
||||
on RbacUser_rv
|
||||
on rbac.subject_rv
|
||||
for each row
|
||||
execute function insertRbacUser();
|
||||
execute function rbac.insert_subject_tf();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
@ -291,11 +291,11 @@ execute function insertRbacUser();
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Instead of delete trigger function for RbacUser_RV.
|
||||
Instead of delete trigger function for rbac.subject_rv.
|
||||
|
||||
Checks if the current subject (user / assumed role) has the permission to delete the user.
|
||||
*/
|
||||
create or replace function deleteRbacUser()
|
||||
create or replace function delete_subject_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
@ -307,13 +307,13 @@ begin
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
Creates an instead of delete trigger for the RbacUser_rv view.
|
||||
Creates an instead of delete trigger for the rbac.subject_rv view.
|
||||
*/
|
||||
create trigger deleteRbacUser_Trigger
|
||||
create trigger delete_subject_tg
|
||||
instead of delete
|
||||
on RbacUser_rv
|
||||
on rbac.subject_rv
|
||||
for each row
|
||||
execute function deleteRbacUser();
|
||||
execute function delete_subject_tf();
|
||||
--/
|
||||
|
||||
-- ============================================================================
|
||||
@ -324,8 +324,8 @@ execute function deleteRbacUser();
|
||||
based on the grants of the current user or assumed roles.
|
||||
*/
|
||||
-- @formatter:off
|
||||
drop view if exists RbacOwnGrantedPermissions_rv;
|
||||
create or replace view RbacOwnGrantedPermissions_rv as
|
||||
drop view if exists rbac.own_granted_permissions_rv;
|
||||
create or replace view rbac.own_granted_permissions_rv as
|
||||
select r.uuid as roleuuid, p.uuid as permissionUuid,
|
||||
(r.objecttable || ':' || r.objectidname || ':' || r.roletype) as roleName, p.op,
|
||||
o.objecttable, r.objectidname, o.uuid as objectuuid
|
||||
@ -333,7 +333,7 @@ select r.uuid as roleuuid, p.uuid as permissionUuid,
|
||||
join rbacgrants g on g.ascendantuuid = r.uuid
|
||||
join rbacpermission p on p.uuid = g.descendantuuid
|
||||
join rbac.object o on o.uuid = p.objectuuid;
|
||||
grant all privileges on RbacOwnGrantedPermissions_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
grant all privileges on rbac.own_granted_permissions_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
||||
-- @formatter:om
|
||||
|
||||
-- ============================================================================
|
||||
@ -343,7 +343,7 @@ grant all privileges on RbacOwnGrantedPermissions_rv to ${HSADMINNG_POSTGRES_RES
|
||||
Returns all permissions granted to the given user,
|
||||
which are also visible to the current user or assumed roles.
|
||||
*/
|
||||
create or replace function grantedPermissionsRaw(targetSubjectUuid uuid)
|
||||
create or replace function rbac.grantedPermissionsRaw(targetSubjectUuid uuid)
|
||||
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
|
||||
returns null on null input
|
||||
language plpgsql as $$
|
||||
@ -379,14 +379,14 @@ begin
|
||||
-- @formatter:on
|
||||
end; $$;
|
||||
|
||||
create or replace function grantedPermissions(targetSubjectUuid uuid)
|
||||
create or replace function rbac.grantedPermissions(targetSubjectUuid uuid)
|
||||
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
|
||||
returns null on null input
|
||||
language sql as $$
|
||||
select * from grantedPermissionsRaw(targetSubjectUuid)
|
||||
select * from rbac.grantedPermissionsRaw(targetSubjectUuid)
|
||||
union all
|
||||
select roleUuid, roleName, permissionUuid, 'SELECT'::RbacOp, opTableName, objectTable, objectIdName, objectUuid
|
||||
from grantedPermissionsRaw(targetSubjectUuid)
|
||||
from rbac.grantedPermissionsRaw(targetSubjectUuid)
|
||||
where op <> 'SELECT'::RbacOp;
|
||||
$$;
|
||||
--//
|
||||
|
@ -68,7 +68,7 @@ public class ArchitectureTest {
|
||||
"..mapper",
|
||||
"..ping",
|
||||
"..rbac",
|
||||
"..rbac.rbacuser",
|
||||
"..rbac.rbacSubject",
|
||||
"..rbac.rbacgrant",
|
||||
"..rbac.rbacrole",
|
||||
"..rbac.rbacobject",
|
||||
|
@ -298,7 +298,7 @@ public class CsvDataImport extends ContextBasedTest {
|
||||
protected void deleteFromCommonTables() {
|
||||
jpaAttempt.transacted(() -> {
|
||||
context(rbacSuperuser);
|
||||
em.createNativeQuery("delete from rbacuser_rv where name not like 'superuser-%'").executeUpdate();
|
||||
em.createNativeQuery("delete from rbac.subject_rv where name not like 'superuser-%'").executeUpdate();
|
||||
em.createNativeQuery("delete from basis.tx_journal where true").executeUpdate();
|
||||
em.createNativeQuery("delete from basis.tx_context where true").executeUpdate();
|
||||
}).assertSuccessful();
|
||||
|
@ -7,8 +7,8 @@ import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||
import net.hostsharing.hsadminng.rbac.context.ContextBasedTest;
|
||||
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity;
|
||||
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
|
||||
import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserEntity;
|
||||
import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserRepository;
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectEntity;
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectRepository;
|
||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
@ -43,7 +43,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
EntityManager em;
|
||||
|
||||
@Autowired
|
||||
RbacUserRepository rbacUserRepository;
|
||||
RbacSubjectRepository rbacSubjectRepository;
|
||||
|
||||
@Autowired
|
||||
RbacRoleRepository rbacRoleRepository;
|
||||
@ -73,7 +73,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
// TODO: should there be a grantedByRole or just a grantedByTrigger?
|
||||
hasEntry("grantedByRoleIdName", "test_customer#xxx:OWNER"),
|
||||
hasEntry("grantedRoleIdName", "test_customer#xxx:ADMIN"),
|
||||
hasEntry("granteeUserName", "customer-admin@xxx.example.com")
|
||||
hasEntry("granteeSubjectName", "customer-admin@xxx.example.com")
|
||||
)
|
||||
))
|
||||
.body("", hasItem(
|
||||
@ -81,28 +81,28 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
// TODO: should there be a grantedByRole or just a grantedByTrigger?
|
||||
hasEntry("grantedByRoleIdName", "test_customer#yyy:OWNER"),
|
||||
hasEntry("grantedRoleIdName", "test_customer#yyy:ADMIN"),
|
||||
hasEntry("granteeUserName", "customer-admin@yyy.example.com")
|
||||
hasEntry("granteeSubjectName", "customer-admin@yyy.example.com")
|
||||
)
|
||||
))
|
||||
.body("", hasItem(
|
||||
allOf(
|
||||
hasEntry("grantedByRoleIdName", "global#global:ADMIN"),
|
||||
hasEntry("grantedRoleIdName", "global#global:ADMIN"),
|
||||
hasEntry("granteeUserName", "superuser-fran@hostsharing.net")
|
||||
hasEntry("granteeSubjectName", "superuser-fran@hostsharing.net")
|
||||
)
|
||||
))
|
||||
.body("", hasItem(
|
||||
allOf(
|
||||
hasEntry("grantedByRoleIdName", "test_customer#xxx:ADMIN"),
|
||||
hasEntry("grantedRoleIdName", "test_package#xxx00:ADMIN"),
|
||||
hasEntry("granteeUserName", "pac-admin-xxx00@xxx.example.com")
|
||||
hasEntry("granteeSubjectName", "pac-admin-xxx00@xxx.example.com")
|
||||
)
|
||||
))
|
||||
.body("", hasItem(
|
||||
allOf(
|
||||
hasEntry("grantedByRoleIdName", "test_customer#zzz:ADMIN"),
|
||||
hasEntry("grantedRoleIdName", "test_package#zzz02:ADMIN"),
|
||||
hasEntry("granteeUserName", "pac-admin-zzz02@zzz.example.com")
|
||||
hasEntry("granteeSubjectName", "pac-admin-zzz02@zzz.example.com")
|
||||
)
|
||||
))
|
||||
.body("size()", greaterThanOrEqualTo(14));
|
||||
@ -125,7 +125,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
allOf(
|
||||
hasEntry("grantedByRoleIdName", "test_customer#yyy:ADMIN"),
|
||||
hasEntry("grantedRoleIdName", "test_package#yyy00:ADMIN"),
|
||||
hasEntry("granteeUserName", "pac-admin-yyy00@yyy.example.com")
|
||||
hasEntry("granteeSubjectName", "pac-admin-yyy00@yyy.example.com")
|
||||
)
|
||||
))
|
||||
.body("size()", is(1));
|
||||
@ -147,12 +147,12 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
allOf(
|
||||
hasEntry("grantedByRoleIdName", "test_customer#yyy:ADMIN"),
|
||||
hasEntry("grantedRoleIdName", "test_package#yyy00:ADMIN"),
|
||||
hasEntry("granteeUserName", "pac-admin-yyy00@yyy.example.com")
|
||||
hasEntry("granteeSubjectName", "pac-admin-yyy00@yyy.example.com")
|
||||
)
|
||||
))
|
||||
.body("[0].grantedByRoleIdName", is("test_customer#yyy:ADMIN"))
|
||||
.body("[0].grantedRoleIdName", is("test_package#yyy00:ADMIN"))
|
||||
.body("[0].granteeUserName", is("pac-admin-yyy00@yyy.example.com"));
|
||||
.body("[0].granteeSubjectName", is("pac-admin-yyy00@yyy.example.com"));
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
||||
@ -164,7 +164,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
void customerAdmin_withAssumedPacketAdminRole_canReadPacketAdminsGrantById() {
|
||||
// given
|
||||
final var givencurrentSubjectAsPackageAdmin = new Subject("customer-admin@xxx.example.com");
|
||||
final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGranteeUser = findRbacSubjectByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN");
|
||||
|
||||
// when
|
||||
@ -176,14 +176,14 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
.statusCode(200)
|
||||
.body("grantedByRoleIdName", is("test_customer#xxx:ADMIN"))
|
||||
.body("grantedRoleIdName", is("test_package#xxx00:ADMIN"))
|
||||
.body("granteeUserName", is("pac-admin-xxx00@xxx.example.com"));
|
||||
.body("granteeSubjectName", is("pac-admin-xxx00@xxx.example.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void packageAdmin_withoutAssumedRole_canReadItsOwnGrantById() {
|
||||
// given
|
||||
final var givencurrentSubjectAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGranteeUser = findRbacSubjectByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN");
|
||||
|
||||
// when
|
||||
@ -195,7 +195,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
.statusCode(200)
|
||||
.body("grantedByRoleIdName", is("test_customer#xxx:ADMIN"))
|
||||
.body("grantedRoleIdName", is("test_package#xxx00:ADMIN"))
|
||||
.body("granteeUserName", is("pac-admin-xxx00@xxx.example.com"));
|
||||
.body("granteeSubjectName", is("pac-admin-xxx00@xxx.example.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -204,7 +204,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
final var givencurrentSubjectAsPackageAdmin = new Subject(
|
||||
"pac-admin-xxx00@xxx.example.com",
|
||||
"test_package#xxx00:ADMIN");
|
||||
final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGranteeUser = findRbacSubjectByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN");
|
||||
|
||||
// when
|
||||
@ -216,7 +216,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
.statusCode(200)
|
||||
.body("grantedByRoleIdName", is("test_customer#xxx:ADMIN"))
|
||||
.body("grantedRoleIdName", is("test_package#xxx00:ADMIN"))
|
||||
.body("granteeUserName", is("pac-admin-xxx00@xxx.example.com"));
|
||||
.body("granteeSubjectName", is("pac-admin-xxx00@xxx.example.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -226,7 +226,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
final var givencurrentSubjectAsPackageAdmin = new Subject(
|
||||
"pac-admin-xxx00@xxx.example.com",
|
||||
"test_package#xxx00:TENANT");
|
||||
final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGranteeUser = findRbacSubjectByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN");
|
||||
final var grant = givencurrentSubjectAsPackageAdmin.getGrantById()
|
||||
.forGrantedRole(givenGrantedRole).toGranteeUser(givenGranteeUser);
|
||||
@ -244,7 +244,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
void packageAdmin_canGrantOwnPackageAdminRole_toArbitraryUser() {
|
||||
|
||||
// given
|
||||
final var givenNewUser = createRBacUser();
|
||||
final var givenNewUser = createRbacSubject();
|
||||
final var givenRoleToGrant = "test_package#xxx00:ADMIN";
|
||||
final var givencurrentSubjectAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com", givenRoleToGrant);
|
||||
final var givenOwnPackageAdminRole =
|
||||
@ -261,7 +261,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
.body("grantedByRoleIdName", is("test_package#xxx00:ADMIN"))
|
||||
.body("assumed", is(true))
|
||||
.body("grantedRoleIdName", is("test_package#xxx00:ADMIN"))
|
||||
.body("granteeUserName", is(givenNewUser.getName()));
|
||||
.body("granteeSubjectName", is(givenNewUser.getName()));
|
||||
assertThat(findAllGrantsOf(givencurrentSubjectAsPackageAdmin))
|
||||
.extracting(RbacGrantEntity::toDisplay)
|
||||
.contains("{ grant role:" + givenOwnPackageAdminRole.getRoleName() +
|
||||
@ -273,7 +273,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
void packageAdmin_canNotGrantAlienPackageAdminRole_toArbitraryUser() {
|
||||
|
||||
// given
|
||||
final var givenNewUser = createRBacUser();
|
||||
final var givenNewUser = createRbacSubject();
|
||||
final var givenRoleToGrant = "test_package#xxx00:ADMIN";
|
||||
final var givencurrentSubjectAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com", givenRoleToGrant);
|
||||
final var givenAlienPackageAdminRole = getRbacRoleByName("test_package#yyy00:ADMIN");
|
||||
@ -289,7 +289,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
.body("message", containsString("Access to granted role"))
|
||||
.body("message", containsString("forbidden for test_package#xxx00:ADMIN"));
|
||||
assertThat(findAllGrantsOf(givencurrentSubjectAsPackageAdmin))
|
||||
.extracting(RbacGrantEntity::getGranteeUserName)
|
||||
.extracting(RbacGrantEntity::getGranteeSubjectName)
|
||||
.doesNotContain(givenNewUser.getName());
|
||||
}
|
||||
}
|
||||
@ -302,7 +302,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
void packageAdmin_canRevokePackageAdminRole_grantedByPackageAdmin_fromArbitraryUser() {
|
||||
|
||||
// given
|
||||
final var givenArbitraryUser = createRBacUser();
|
||||
final var givenArbitraryUser = createRbacSubject();
|
||||
final var givenRoleToGrant = "test_package#xxx00:ADMIN";
|
||||
final var givenCurrentSubjectAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com", givenRoleToGrant);
|
||||
final var givenOwnPackageAdminRole = getRbacRoleByName("test_package#xxx00:ADMIN");
|
||||
@ -326,7 +326,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
// then
|
||||
revokeResponse.assertThat().statusCode(204);
|
||||
assertThat(findAllGrantsOf(givenCurrentSubjectAsPackageAdmin))
|
||||
.extracting(RbacGrantEntity::getGranteeUserName)
|
||||
.extracting(RbacGrantEntity::getGranteeSubjectName)
|
||||
.doesNotContain(givenArbitraryUser.getName());
|
||||
}
|
||||
}
|
||||
@ -366,7 +366,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
private Subject grantingSubject = Subject.this;
|
||||
private final RbacRoleEntity grantedRole;
|
||||
private boolean assumed;
|
||||
private RbacUserEntity granteeUser;
|
||||
private RbacSubjectEntity granteeUser;
|
||||
|
||||
public GrantFixture(final RbacRoleEntity roleToGrant) {
|
||||
this.grantedRole = roleToGrant;
|
||||
@ -377,7 +377,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
ValidatableResponse toUser(final RbacUserEntity granteeUser) {
|
||||
ValidatableResponse toUser(final RbacSubjectEntity granteeUser) {
|
||||
this.granteeUser = granteeUser;
|
||||
|
||||
return RestAssured // @formatter:ff
|
||||
@ -407,13 +407,13 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
private Subject currentSubject = Subject.this;
|
||||
private final RbacRoleEntity grantedRole;
|
||||
private boolean assumed;
|
||||
private RbacUserEntity granteeUser;
|
||||
private RbacSubjectEntity granteeUser;
|
||||
|
||||
public RevokeFixture(final RbacRoleEntity roleToGrant) {
|
||||
this.grantedRole = roleToGrant;
|
||||
}
|
||||
|
||||
ValidatableResponse fromUser(final RbacUserEntity granteeUser) {
|
||||
ValidatableResponse fromUser(final RbacSubjectEntity granteeUser) {
|
||||
this.granteeUser = granteeUser;
|
||||
|
||||
return RestAssured // @formatter:ff
|
||||
@ -450,7 +450,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
ValidatableResponse toGranteeUser(final RbacUserEntity granteeUser) {
|
||||
ValidatableResponse toGranteeUser(final RbacSubjectEntity granteeUser) {
|
||||
|
||||
return RestAssured // @formatter:ff
|
||||
.given()
|
||||
@ -480,18 +480,18 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
}).returnedValue();
|
||||
}
|
||||
|
||||
RbacUserEntity createRBacUser() {
|
||||
RbacSubjectEntity createRbacSubject() {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
final String newUserName = "test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com";
|
||||
context(null);
|
||||
return rbacUserRepository.create(new RbacUserEntity(UUID.randomUUID(), newUserName));
|
||||
return rbacSubjectRepository.create(new RbacSubjectEntity(UUID.randomUUID(), newUserName));
|
||||
}).returnedValue();
|
||||
}
|
||||
|
||||
RbacUserEntity findRbacUserByName(final String userName) {
|
||||
RbacSubjectEntity findRbacSubjectByName(final String userName) {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
context("superuser-alex@hostsharing.net", null);
|
||||
return rbacUserRepository.findByName(userName);
|
||||
return rbacSubjectRepository.findByName(userName);
|
||||
}).assertNotNull().returnedValue();
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ package net.hostsharing.hsadminng.rbac.rbacgrant;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.rbac.context.ContextBasedTest;
|
||||
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
|
||||
import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserEntity;
|
||||
import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserRepository;
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectEntity;
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectRepository;
|
||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -42,7 +42,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
RawRbacGrantRepository rawRbacGrantRepository;
|
||||
|
||||
@Autowired
|
||||
RbacUserRepository rbacUserRepository;
|
||||
RbacSubjectRepository rbacSubjectRepository;
|
||||
|
||||
@Autowired
|
||||
RbacRoleRepository rbacRoleRepository;
|
||||
@ -109,7 +109,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
public void customerAdmin_canGrantOwnPackageAdminRole_toArbitraryUser() {
|
||||
// given
|
||||
context("customer-admin@xxx.example.com", "test_customer#xxx:ADMIN");
|
||||
final var givenArbitrarySubjectUuid = rbacUserRepository.findByName("pac-admin-zzz00@zzz.example.com").getUuid();
|
||||
final var givenArbitrarySubjectUuid = rbacSubjectRepository.findByName("pac-admin-zzz00@zzz.example.com").getUuid();
|
||||
final var givenOwnPackageRoleUuid = rbacRoleRepository.findByRoleName("test_package#xxx00:ADMIN").getUuid();
|
||||
|
||||
// when
|
||||
@ -133,7 +133,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public void packageAdmin_canNotGrantPackageOwnerRole() {
|
||||
// given
|
||||
record Given(RbacUserEntity arbitraryUser, UUID packageOwnerRoleUuid) {}
|
||||
record Given(RbacSubjectEntity arbitraryUser, UUID packageOwnerRoleUuid) {}
|
||||
final var given = jpaAttempt.transacted(() -> {
|
||||
// to find the uuids of we need to have access rights to these
|
||||
context("customer-admin@xxx.example.com", null);
|
||||
@ -188,7 +188,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("customer-admin@xxx.example.com", "test_customer#xxx:ADMIN");
|
||||
assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull();
|
||||
assertThat(rbacGrantRepository.findAll())
|
||||
.extracting(RbacGrantEntity::getGranteeUserName)
|
||||
.extracting(RbacGrantEntity::getGranteeSubjectName)
|
||||
.doesNotContain("pac-admin-zzz00@zzz.example.com");
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull();
|
||||
context("customer-admin@xxx.example.com", "test_customer#xxx:ADMIN");
|
||||
assertThat(rbacGrantRepository.findAll())
|
||||
.extracting(RbacGrantEntity::getGranteeUserName)
|
||||
.extracting(RbacGrantEntity::getGranteeSubjectName)
|
||||
.doesNotContain("pac-admin-zzz00@zzz.example.com");
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
|
||||
private RbacGrantEntity create(GrantBuilder with) {
|
||||
context(with.byUserName, with.assumedRole);
|
||||
final var givenArbitrarySubjectUuid = rbacUserRepository.findByName(with.granteeUserName).getUuid();
|
||||
final var givenArbitrarySubjectUuid = rbacSubjectRepository.findByName(with.granteeSubjectName).getUuid();
|
||||
final var givenOwnPackageRoleUuid = rbacRoleRepository.findByRoleName(with.grantedRole).getUuid();
|
||||
|
||||
final var grant = RbacGrantEntity.builder()
|
||||
@ -251,7 +251,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
assertThat(rawRbacGrantRepository.findAll())
|
||||
.extracting(RawRbacGrantEntity::toDisplay)
|
||||
.contains("{ grant role:%s to user:%s by %s and assume }".formatted(
|
||||
with.grantedRole, with.granteeUserName, with.assumedRole
|
||||
with.grantedRole, with.granteeSubjectName, with.assumedRole
|
||||
));
|
||||
|
||||
return grant;
|
||||
@ -266,7 +266,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
String byUserName;
|
||||
String assumedRole = "";
|
||||
String grantedRole;
|
||||
String granteeUserName;
|
||||
String granteeSubjectName;
|
||||
|
||||
GrantBuilder byUser(final String userName) {
|
||||
byUserName = userName;
|
||||
@ -284,28 +284,28 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
|
||||
}
|
||||
|
||||
GrantBuilder toUser(final String toUser) {
|
||||
this.granteeUserName = toUser;
|
||||
this.granteeSubjectName = toUser;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RbacUserEntity createNewUserTransacted() {
|
||||
private RbacSubjectEntity createNewUserTransacted() {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
final var newUserName = "test-user-" + System.currentTimeMillis() + "@example.com";
|
||||
context(null);
|
||||
return rbacUserRepository.create(new RbacUserEntity(null, newUserName));
|
||||
return rbacSubjectRepository.create(new RbacSubjectEntity(null, newUserName));
|
||||
}).assumeSuccessful().returnedValue();
|
||||
}
|
||||
|
||||
private RbacUserEntity createNewUser() {
|
||||
return rbacUserRepository.create(
|
||||
new RbacUserEntity(null, "test-user-" + System.currentTimeMillis() + "@example.com"));
|
||||
private RbacSubjectEntity createNewUser() {
|
||||
return rbacSubjectRepository.create(
|
||||
new RbacSubjectEntity(null, "test-user-" + System.currentTimeMillis() + "@example.com"));
|
||||
}
|
||||
|
||||
void exactlyTheseRbacGrantsAreReturned(final List<RbacGrantEntity> actualResult, final String... expectedGrant) {
|
||||
assertThat(actualResult)
|
||||
.filteredOn(g -> !g.getGranteeUserName().startsWith("test-user-")) // ignore test-users created by other tests
|
||||
.filteredOn(g -> !g.getGranteeSubjectName().startsWith("test-user-")) // ignore test-users created by other tests
|
||||
.extracting(RbacGrantEntity::toDisplay)
|
||||
.containsExactlyInAnyOrder(expectedGrant);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.rbac.rbacrole;
|
||||
import io.restassured.RestAssured;
|
||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserRepository;
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
@ -24,7 +24,7 @@ class RbacRoleControllerAcceptanceTest {
|
||||
Context context;
|
||||
|
||||
@Autowired
|
||||
RbacUserRepository rbacUserRepository;
|
||||
RbacSubjectRepository rbacSubjectRepository;
|
||||
|
||||
@Autowired
|
||||
RbacRoleRepository rbacRoleRepository;
|
||||
|
@ -1,14 +0,0 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
|
||||
|
||||
import static java.util.UUID.randomUUID;
|
||||
|
||||
public class TestRbacUser {
|
||||
|
||||
static final RbacUserEntity userxxx = rbacRole("customer-admin@xxx.example.com");
|
||||
static final RbacUserEntity userBbb = rbacRole("customer-admin@bbb.example.com");
|
||||
|
||||
static public RbacUserEntity rbacRole(final String userName) {
|
||||
return new RbacUserEntity(randomUUID(), userName);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
@ -22,7 +22,7 @@ import static org.hamcrest.Matchers.*;
|
||||
classes = { HsadminNgApplication.class, JpaAttempt.class }
|
||||
)
|
||||
@Transactional
|
||||
class RbacUserControllerAcceptanceTest {
|
||||
class RbacSubjectControllerAcceptanceTest {
|
||||
|
||||
@LocalServerPort
|
||||
private Integer port;
|
||||
@ -34,10 +34,10 @@ class RbacUserControllerAcceptanceTest {
|
||||
Context context;
|
||||
|
||||
@Autowired
|
||||
RbacUserRepository rbacUserRepository;
|
||||
RbacSubjectRepository rbacSubjectRepository;
|
||||
|
||||
@Nested
|
||||
class CreateRbacUser {
|
||||
class CreateRbacSubject {
|
||||
|
||||
@Test
|
||||
void anybody_canCreateANewUser() {
|
||||
@ -53,7 +53,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
""")
|
||||
.port(port)
|
||||
.when()
|
||||
.post("http://localhost/api/rbac/users")
|
||||
.post("http://localhost/api/rbac/subjects")
|
||||
.then().assertThat()
|
||||
.statusCode(201)
|
||||
.contentType(ContentType.JSON)
|
||||
@ -66,17 +66,17 @@ class RbacUserControllerAcceptanceTest {
|
||||
final var newSubjectUuid = UUID.fromString(
|
||||
location.substring(location.lastIndexOf('/') + 1));
|
||||
context.define("new-user@example.com");
|
||||
assertThat(rbacUserRepository.findByUuid(newSubjectUuid))
|
||||
.extracting(RbacUserEntity::getName).isEqualTo("new-user@example.com");
|
||||
assertThat(rbacSubjectRepository.findByUuid(newSubjectUuid))
|
||||
.extracting(RbacSubjectEntity::getName).isEqualTo("new-user@example.com");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class GetRbacUser {
|
||||
class GetRbacSubject {
|
||||
|
||||
@Test
|
||||
void globalAdmin_withoutAssumedRole_canGetArbitraryUser() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-xxx00@xxx.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -84,7 +84,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid())
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid())
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -94,7 +94,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
|
||||
@Test
|
||||
void globalAdmin_withAssumedCustomerAdminRole_canGetUserWithinInItsRealm() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-yyy00@yyy.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-yyy00@yyy.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -103,7 +103,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("assumed-roles", "test_customer#yyy:ADMIN")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid())
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid())
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -113,7 +113,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
|
||||
@Test
|
||||
void customerAdmin_withoutAssumedRole_canGetUserWithinInItsRealm() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-yyy00@yyy.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-yyy00@yyy.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -121,7 +121,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "customer-admin@yyy.example.com")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid())
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid())
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -131,7 +131,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
|
||||
@Test
|
||||
void customerAdmin_withoutAssumedRole_canNotGetUserOutsideOfItsRealm() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-yyy00@yyy.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-yyy00@yyy.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -139,7 +139,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "customer-admin@xxx.example.com")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid())
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid())
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(404);
|
||||
// @formatter:on
|
||||
@ -147,7 +147,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ListRbacUsers {
|
||||
class ListRbacSubjects {
|
||||
|
||||
@Test
|
||||
void globalAdmin_withoutAssumedRole_canViewAllUsers() {
|
||||
@ -158,7 +158,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users")
|
||||
.get("http://localhost/api/rbac/subjects")
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -183,7 +183,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users?name=pac-admin-zzz0")
|
||||
.get("http://localhost/api/rbac/subjects?name=pac-admin-zzz0")
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -204,7 +204,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("assumed-roles", "test_customer#yyy:ADMIN")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users")
|
||||
.get("http://localhost/api/rbac/subjects")
|
||||
.then().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -225,7 +225,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "customer-admin@yyy.example.com")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users")
|
||||
.get("http://localhost/api/rbac/subjects")
|
||||
.then().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -246,7 +246,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "pac-admin-xxx01@xxx.example.com")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users")
|
||||
.get("http://localhost/api/rbac/subjects")
|
||||
.then().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -257,11 +257,11 @@ class RbacUserControllerAcceptanceTest {
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ListRbacUserPermissions {
|
||||
class ListRbacSubjectPermissions {
|
||||
|
||||
@Test
|
||||
void globalAdmin_withoutAssumedRole_canViewArbitraryUsersPermissions() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-yyy00@yyy.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-yyy00@yyy.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -269,7 +269,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid() + "/permissions")
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid() + "/permissions")
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -290,7 +290,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
|
||||
@Test
|
||||
void globalAdmin_withAssumedCustomerAdminRole_canViewArbitraryUsersPermissions() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-yyy00@yyy.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-yyy00@yyy.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -299,7 +299,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("assumed-roles", "test_customer#yyy:ADMIN")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid() + "/permissions")
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid() + "/permissions")
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -320,7 +320,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
|
||||
@Test
|
||||
void packageAdmin_withoutAssumedRole_canViewPermissionsOfUsersInItsRealm() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-yyy00@yyy.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-yyy00@yyy.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -328,7 +328,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "pac-admin-yyy00@yyy.example.com")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid() + "/permissions")
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid() + "/permissions")
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -349,7 +349,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
|
||||
@Test
|
||||
void packageAdmin_canViewPermissionsOfUsersOutsideOfItsRealm() {
|
||||
final var givenUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com");
|
||||
final var givenUser = findRbacSubjectByName("pac-admin-xxx00@xxx.example.com");
|
||||
|
||||
// @formatter:off
|
||||
RestAssured
|
||||
@ -357,7 +357,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "pac-admin-yyy00@yyy.example.com")
|
||||
.port(port)
|
||||
.when()
|
||||
.get("http://localhost/api/rbac/users/" + givenUser.getUuid() + "/permissions")
|
||||
.get("http://localhost/api/rbac/subjects/" + givenUser.getUuid() + "/permissions")
|
||||
.then().log().body().assertThat()
|
||||
.statusCode(200)
|
||||
.contentType("application/json")
|
||||
@ -367,7 +367,7 @@ class RbacUserControllerAcceptanceTest {
|
||||
}
|
||||
|
||||
@Nested
|
||||
class DeleteRbacUser {
|
||||
class DeleteRbacSubject {
|
||||
|
||||
@Test
|
||||
void anybody_canDeleteTheirOwnUser() {
|
||||
@ -381,13 +381,13 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", givenUser.getName())
|
||||
.port(port)
|
||||
.when()
|
||||
.delete("http://localhost/api/rbac/users/" + givenUser.getUuid())
|
||||
.delete("http://localhost/api/rbac/subjects/" + givenUser.getUuid())
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(204);
|
||||
// @formatter:on
|
||||
|
||||
// finally, the user is actually deleted
|
||||
assertThat(rbacUserRepository.findByName(givenUser.getName())).isNull();
|
||||
assertThat(rbacSubjectRepository.findByName(givenUser.getName())).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -402,14 +402,14 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "customer-admin@xxx.example.com")
|
||||
.port(port)
|
||||
.when()
|
||||
.delete("http://localhost/api/rbac/users/" + givenUser.getUuid())
|
||||
.delete("http://localhost/api/rbac/subjects/" + givenUser.getUuid())
|
||||
.then().log().all().assertThat()
|
||||
// that user cannot even see other users, thus the system won't even try to delete
|
||||
.statusCode(204);
|
||||
// @formatter:on
|
||||
|
||||
// finally, the user is still there
|
||||
assertThat(rbacUserRepository.findByName(givenUser.getName())).isNotNull();
|
||||
assertThat(rbacSubjectRepository.findByName(givenUser.getName())).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -424,30 +424,30 @@ class RbacUserControllerAcceptanceTest {
|
||||
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||
.port(port)
|
||||
.when()
|
||||
.delete("http://localhost/api/rbac/users/" + givenUser.getUuid())
|
||||
.delete("http://localhost/api/rbac/subjects/" + givenUser.getUuid())
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(204);
|
||||
// @formatter:on
|
||||
|
||||
// finally, the user is actually deleted
|
||||
assertThat(rbacUserRepository.findByName(givenUser.getName())).isNull();
|
||||
assertThat(rbacSubjectRepository.findByName(givenUser.getName())).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
RbacUserEntity findRbacUserByName(final String userName) {
|
||||
RbacSubjectEntity findRbacSubjectByName(final String userName) {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
return rbacUserRepository.findByName(userName);
|
||||
return rbacSubjectRepository.findByName(userName);
|
||||
}).returnedValue();
|
||||
}
|
||||
|
||||
RbacUserEntity givenANewUser() {
|
||||
RbacSubjectEntity givenANewUser() {
|
||||
final var givenUserName = "test-user-" + System.currentTimeMillis() + "@example.com";
|
||||
final var givenUser = jpaAttempt.transacted(() -> {
|
||||
context.define(null);
|
||||
return rbacUserRepository.create(new RbacUserEntity(UUID.randomUUID(), givenUserName));
|
||||
return rbacSubjectRepository.create(new RbacSubjectEntity(UUID.randomUUID(), givenUserName));
|
||||
}).assumeSuccessful().returnedValue();
|
||||
assertThat(rbacUserRepository.findByName(givenUser.getName())).isNotNull();
|
||||
assertThat(rbacSubjectRepository.findByName(givenUser.getName())).isNotNull();
|
||||
return givenUser;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.mapper.Mapper;
|
||||
@ -30,10 +30,10 @@ import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@WebMvcTest(RbacUserController.class)
|
||||
@WebMvcTest(RbacSubjectController.class)
|
||||
@Import(Mapper.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
class RbacUserControllerRestTest {
|
||||
class RbacSubjectControllerRestTest {
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
@ -42,7 +42,7 @@ class RbacUserControllerRestTest {
|
||||
Context contextMock;
|
||||
|
||||
@MockBean
|
||||
RbacUserRepository rbacUserRepository;
|
||||
RbacSubjectRepository rbacSubjectRepository;
|
||||
|
||||
@Mock
|
||||
EntityManager em;
|
||||
@ -59,13 +59,13 @@ class RbacUserControllerRestTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void createUserUsesGivenUuid() throws Exception {
|
||||
void createSubjectUsesGivenUuid() throws Exception {
|
||||
// given
|
||||
final var givenUuid = UUID.randomUUID();
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.post("/api/rbac/users")
|
||||
.post("/api/rbac/subjects")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
@ -79,14 +79,14 @@ class RbacUserControllerRestTest {
|
||||
.andExpect(jsonPath("uuid", is(givenUuid.toString())));
|
||||
|
||||
// then
|
||||
verify(rbacUserRepository).create(argThat(entity -> entity.getUuid().equals(givenUuid)));
|
||||
verify(rbacSubjectRepository).create(argThat(entity -> entity.getUuid().equals(givenUuid)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createUserGeneratesRandomUuidIfNotGiven() throws Exception {
|
||||
void createSubjectGeneratesRandomUuidIfNotGiven() throws Exception {
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
.post("/api/rbac/users")
|
||||
.post("/api/rbac/subjects")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
@ -96,6 +96,6 @@ class RbacUserControllerRestTest {
|
||||
.andExpect(jsonPath("uuid", isUuidValid()));
|
||||
|
||||
// then
|
||||
verify(rbacUserRepository).create(argThat(entity -> entity.getUuid() != null));
|
||||
verify(rbacSubjectRepository).create(argThat(entity -> entity.getUuid() != null));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -9,9 +9,9 @@ import java.util.UUID;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class RbacUserEntityUnitTest {
|
||||
class RbacSubjectEntityUnitTest {
|
||||
|
||||
RbacUserEntity givenUser = new RbacUserEntity(UUID.randomUUID(), "test@example.org");
|
||||
RbacSubjectEntity givenUser = new RbacSubjectEntity(UUID.randomUUID(), "test@example.org");
|
||||
|
||||
@Test
|
||||
void generatedAccessCodeMatchesDefinedPattern() {
|
@ -1,4 +1,4 @@
|
||||
package net.hostsharing.hsadminng.rbac.rbacuser;
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.rbac.context.ContextBasedTest;
|
||||
@ -26,10 +26,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
@Import( { Context.class, JpaAttempt.class })
|
||||
class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
class RbacSubjectRepositoryIntegrationTest extends ContextBasedTest {
|
||||
|
||||
@Autowired
|
||||
RbacUserRepository rbacUserRepository;
|
||||
RbacSubjectRepository rbacSubjectRepository;
|
||||
|
||||
@Autowired
|
||||
JpaAttempt jpaAttempt;
|
||||
@ -41,7 +41,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
HttpServletRequest request;
|
||||
|
||||
@Nested
|
||||
class CreateUser {
|
||||
class CreateSubject {
|
||||
|
||||
@Test
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
@ -54,35 +54,35 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
// when:
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
context(null);
|
||||
return rbacUserRepository.create(new RbacUserEntity(givenUuid, newUserName));
|
||||
return rbacSubjectRepository.create(new RbacSubjectEntity(givenUuid, newUserName));
|
||||
});
|
||||
|
||||
// then:
|
||||
assertThat(result.wasSuccessful()).isTrue();
|
||||
assertThat(result.returnedValue()).isNotNull()
|
||||
.extracting(RbacUserEntity::getUuid).isEqualTo(givenUuid);
|
||||
assertThat(rbacUserRepository.findByName(result.returnedValue().getName())).isNotNull();
|
||||
.extracting(RbacSubjectEntity::getUuid).isEqualTo(givenUuid);
|
||||
assertThat(rbacSubjectRepository.findByName(result.returnedValue().getName())).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class DeleteUser {
|
||||
class DeleteSubject {
|
||||
|
||||
@Test
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public void anyoneCanDeleteTheirOwnUser() {
|
||||
// given
|
||||
final RbacUserEntity givenUser = givenANewUser();
|
||||
final RbacSubjectEntity givenUser = givenANewSubject();
|
||||
|
||||
// when
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
context(givenUser.getName());
|
||||
rbacUserRepository.deleteByUuid(givenUser.getUuid());
|
||||
rbacSubjectRepository.deleteByUuid(givenUser.getUuid());
|
||||
});
|
||||
|
||||
// then the user is deleted
|
||||
result.assertSuccessful();
|
||||
assertThat(rbacUserRepository.findByName(givenUser.getName())).isNull();
|
||||
assertThat(rbacSubjectRepository.findByName(givenUser.getName())).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,27 +102,27 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
);
|
||||
|
||||
@Test
|
||||
public void globalAdmin_withoutAssumedRole_canViewAllRbacUsers() {
|
||||
public void globalAdmin_withoutAssumedRole_canViewAllRbacSubjects() {
|
||||
// given
|
||||
context("superuser-alex@hostsharing.net");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findByOptionalNameLike(null);
|
||||
final var result = rbacSubjectRepository.findByOptionalNameLike(null);
|
||||
|
||||
// then
|
||||
allTheseRbacUsersAreReturned(result, ALL_TEST_DATA_USERS);
|
||||
allTheseRbacSubjectsAreReturned(result, ALL_TEST_DATA_USERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void globalAdmin_withAssumedglobalAdminRole_canViewAllRbacUsers() {
|
||||
public void globalAdmin_withAssumedglobalAdminRole_canViewAllRbacSubjects() {
|
||||
given:
|
||||
context("superuser-alex@hostsharing.net", "global#global:ADMIN");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findByOptionalNameLike(null);
|
||||
final var result = rbacSubjectRepository.findByOptionalNameLike(null);
|
||||
|
||||
then:
|
||||
allTheseRbacUsersAreReturned(result, ALL_TEST_DATA_USERS);
|
||||
allTheseRbacSubjectsAreReturned(result, ALL_TEST_DATA_USERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -131,10 +131,10 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("superuser-alex@hostsharing.net", "test_customer#xxx:ADMIN");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findByOptionalNameLike(null);
|
||||
final var result = rbacSubjectRepository.findByOptionalNameLike(null);
|
||||
|
||||
then:
|
||||
exactlyTheseRbacUsersAreReturned(
|
||||
exactlyTheseRbacSubjectsAreReturned(
|
||||
result,
|
||||
"customer-admin@xxx.example.com",
|
||||
"pac-admin-xxx00@xxx.example.com", "pac-admin-xxx01@xxx.example.com", "pac-admin-xxx02@xxx.example.com"
|
||||
@ -147,10 +147,10 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("customer-admin@xxx.example.com");
|
||||
|
||||
// when:
|
||||
final var result = rbacUserRepository.findByOptionalNameLike(null);
|
||||
final var result = rbacSubjectRepository.findByOptionalNameLike(null);
|
||||
|
||||
// then:
|
||||
exactlyTheseRbacUsersAreReturned(
|
||||
exactlyTheseRbacSubjectsAreReturned(
|
||||
result,
|
||||
"customer-admin@xxx.example.com",
|
||||
"pac-admin-xxx00@xxx.example.com", "pac-admin-xxx01@xxx.example.com", "pac-admin-xxx02@xxx.example.com"
|
||||
@ -161,24 +161,24 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyUsersHavingRolesInThatPackage() {
|
||||
context("customer-admin@xxx.example.com", "test_package#xxx00:ADMIN");
|
||||
|
||||
final var result = rbacUserRepository.findByOptionalNameLike(null);
|
||||
final var result = rbacSubjectRepository.findByOptionalNameLike(null);
|
||||
|
||||
exactlyTheseRbacUsersAreReturned(result, "pac-admin-xxx00@xxx.example.com");
|
||||
exactlyTheseRbacSubjectsAreReturned(result, "pac-admin-xxx00@xxx.example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void packageAdmin_withoutAssumedRole_canViewOnlyUsersHavingRolesInThatPackage() {
|
||||
context("pac-admin-xxx00@xxx.example.com");
|
||||
|
||||
final var result = rbacUserRepository.findByOptionalNameLike(null);
|
||||
final var result = rbacSubjectRepository.findByOptionalNameLike(null);
|
||||
|
||||
exactlyTheseRbacUsersAreReturned(result, "pac-admin-xxx00@xxx.example.com");
|
||||
exactlyTheseRbacSubjectsAreReturned(result, "pac-admin-xxx00@xxx.example.com");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ListUserPermissions {
|
||||
class ListSubjectPermissions {
|
||||
|
||||
private static final String[] ALL_USER_PERMISSIONS = Array.of(
|
||||
// @formatter:off
|
||||
@ -232,9 +232,9 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("superuser-alex@hostsharing.net");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findPermissionsOfUserByUuid(subjectUuid("superuser-fran@hostsharing.net"))
|
||||
final var result = rbacSubjectRepository.findPermissionsOfUserByUuid(subjectUuid("superuser-fran@hostsharing.net"))
|
||||
.stream().filter(p -> p.getObjectTable().contains("test_"))
|
||||
.sorted(comparing(RbacUserPermission::toString)).toList();
|
||||
.sorted(comparing(RbacSubjectPermission::toString)).toList();
|
||||
|
||||
// then
|
||||
allTheseRbacPermissionsAreReturned(result, ALL_USER_PERMISSIONS);
|
||||
@ -246,7 +246,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("customer-admin@xxx.example.com");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findPermissionsOfUserByUuid(subjectUuid("customer-admin@xxx.example.com"));
|
||||
final var result = rbacSubjectRepository.findPermissionsOfUserByUuid(subjectUuid("customer-admin@xxx.example.com"));
|
||||
|
||||
// then
|
||||
allTheseRbacPermissionsAreReturned(
|
||||
@ -290,7 +290,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
|
||||
// when
|
||||
final var result = attempt(em, () ->
|
||||
rbacUserRepository.findPermissionsOfUserByUuid(subjectUuid)
|
||||
rbacSubjectRepository.findPermissionsOfUserByUuid(subjectUuid)
|
||||
);
|
||||
|
||||
// then
|
||||
@ -306,7 +306,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("customer-admin@xxx.example.com");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findPermissionsOfUserByUuid(subjectUuid("pac-admin-xxx00@xxx.example.com"));
|
||||
final var result = rbacSubjectRepository.findPermissionsOfUserByUuid(subjectUuid("pac-admin-xxx00@xxx.example.com"));
|
||||
|
||||
// then
|
||||
allTheseRbacPermissionsAreReturned(
|
||||
@ -342,7 +342,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("customer-admin@xxx.example.com");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findPermissionsOfUserByUuid(subjectUuid("pac-admin-yyy00@yyy.example.com"));
|
||||
final var result = rbacSubjectRepository.findPermissionsOfUserByUuid(subjectUuid("pac-admin-yyy00@yyy.example.com"));
|
||||
|
||||
// then
|
||||
noRbacPermissionsAreReturned(result);
|
||||
@ -354,7 +354,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
context("pac-admin-xxx00@xxx.example.com");
|
||||
|
||||
// when
|
||||
final var result = rbacUserRepository.findPermissionsOfUserByUuid(subjectUuid("pac-admin-xxx00@xxx.example.com"));
|
||||
final var result = rbacSubjectRepository.findPermissionsOfUserByUuid(subjectUuid("pac-admin-xxx00@xxx.example.com"));
|
||||
|
||||
// then
|
||||
allTheseRbacPermissionsAreReturned(
|
||||
@ -386,50 +386,42 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
}
|
||||
|
||||
UUID subjectUuid(final String userName) {
|
||||
return rbacUserRepository.findByName(userName).getUuid();
|
||||
return rbacSubjectRepository.findByName(userName).getUuid();
|
||||
}
|
||||
|
||||
RbacUserEntity givenANewUser() {
|
||||
RbacSubjectEntity givenANewSubject() {
|
||||
final var givenUserName = "test-user-" + System.currentTimeMillis() + "@example.com";
|
||||
final var givenUser = jpaAttempt.transacted(() -> {
|
||||
context(null);
|
||||
return rbacUserRepository.create(new RbacUserEntity(UUID.randomUUID(), givenUserName));
|
||||
return rbacSubjectRepository.create(new RbacSubjectEntity(UUID.randomUUID(), givenUserName));
|
||||
}).assumeSuccessful().returnedValue();
|
||||
assertThat(rbacUserRepository.findByName(givenUser.getName())).isNotNull();
|
||||
assertThat(rbacSubjectRepository.findByName(givenUser.getName())).isNotNull();
|
||||
return givenUser;
|
||||
}
|
||||
|
||||
void exactlyTheseRbacUsersAreReturned(final List<RbacUserEntity> actualResult, final String... expectedUserNames) {
|
||||
void exactlyTheseRbacSubjectsAreReturned(final List<RbacSubjectEntity> actualResult, final String... expectedUserNames) {
|
||||
assertThat(actualResult)
|
||||
.extracting(RbacUserEntity::getName)
|
||||
.extracting(RbacSubjectEntity::getName)
|
||||
.filteredOn(n -> !n.startsWith("test-user"))
|
||||
.containsExactlyInAnyOrder(expectedUserNames);
|
||||
}
|
||||
|
||||
void allTheseRbacUsersAreReturned(final List<RbacUserEntity> actualResult, final String... expectedUserNames) {
|
||||
void allTheseRbacSubjectsAreReturned(final List<RbacSubjectEntity> actualResult, final String... expectedUserNames) {
|
||||
assertThat(actualResult)
|
||||
.extracting(RbacUserEntity::getName)
|
||||
.extracting(RbacSubjectEntity::getName)
|
||||
.filteredOn(n -> !n.startsWith("test-user"))
|
||||
.contains(expectedUserNames);
|
||||
}
|
||||
|
||||
void noRbacPermissionsAreReturned(
|
||||
final List<RbacUserPermission> actualResult) {
|
||||
final List<RbacSubjectPermission> actualResult) {
|
||||
assertThat(actualResult)
|
||||
.extracting(p -> p.getRoleName() + " -> " + p.getObjectTable() + "#" + p.getObjectIdName() + ": " + p.getOp())
|
||||
.containsExactlyInAnyOrder();
|
||||
}
|
||||
|
||||
void exactlyTheseRbacPermissionsAreReturned(
|
||||
final List<RbacUserPermission> actualResult,
|
||||
final String... expectedRoleNames) {
|
||||
assertThat(actualResult)
|
||||
.extracting(p -> p.getRoleName() + " -> " + p.getObjectTable() + "#" + p.getObjectIdName() + ": " + p.getOp())
|
||||
.containsExactlyInAnyOrder(expectedRoleNames);
|
||||
}
|
||||
|
||||
void allTheseRbacPermissionsAreReturned(
|
||||
final List<RbacUserPermission> actualResult,
|
||||
final List<RbacSubjectPermission> actualResult,
|
||||
final String... expectedRoleNames) {
|
||||
assertThat(actualResult)
|
||||
.extracting(p -> p.getRoleName() + " -> " + p.getObjectTable() + "#" + p.getObjectIdName() + ": " + p.getOp()
|
||||
@ -438,7 +430,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
|
||||
}
|
||||
|
||||
void noneOfTheseRbacPermissionsAreReturned(
|
||||
final List<RbacUserPermission> actualResult,
|
||||
final List<RbacSubjectPermission> actualResult,
|
||||
final String... unexpectedRoleNames) {
|
||||
assertThat(actualResult)
|
||||
.extracting(p -> p.getRoleName() + " -> " + p.getObjectTable() + "#" + p.getObjectIdName() + ": " + p.getOp())
|
@ -0,0 +1,14 @@
|
||||
package net.hostsharing.hsadminng.rbac.subject;
|
||||
|
||||
|
||||
import static java.util.UUID.randomUUID;
|
||||
|
||||
public class TestRbacSubject {
|
||||
|
||||
static final RbacSubjectEntity userxxx = rbacRole("customer-admin@xxx.example.com");
|
||||
static final RbacSubjectEntity userBbb = rbacRole("customer-admin@bbb.example.com");
|
||||
|
||||
static public RbacSubjectEntity rbacRole(final String userName) {
|
||||
return new RbacSubjectEntity(randomUUID(), userName);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user