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