improved rbacroles_ev view and raw access for testing purposes

This commit is contained in:
Michael Hoennig 2022-09-10 14:49:01 +02:00
parent 2c5ad094f1
commit 3eec8a4138
11 changed files with 189 additions and 21 deletions

View File

@ -25,6 +25,8 @@ configurations {
extendsFrom annotationProcessor extendsFrom annotationProcessor
} }
testCompile { testCompile {
extendsFrom testAnnotationProcessor
// Only JUNit 5 (Jupiter) should be used at compile time. // Only JUNit 5 (Jupiter) should be used at compile time.
// For runtime it's still needed by testcontainers, though. // For runtime it's still needed by testcontainers, though.
exclude group: 'junit', module: 'junit' exclude group: 'junit', module: 'junit'
@ -60,12 +62,14 @@ dependencies {
implementation 'org.modelmapper:modelmapper:3.1.0' implementation 'org.modelmapper:modelmapper:3.1.0'
compileOnly 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools' developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'org.postgresql:postgresql' runtimeOnly 'org.postgresql:postgresql'
annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.testcontainers:testcontainers' testImplementation 'org.testcontainers:testcontainers'

View File

@ -185,7 +185,6 @@ begin
objectIdName := pureIdentifier(objectIdName); objectIdName := pureIdentifier(objectIdName);
sql := format('select * from %sUuidByIdName(%L);', objectTable, objectIdName); sql := format('select * from %sUuidByIdName(%L);', objectTable, objectIdName);
begin begin
raise notice 'sql: %', sql;
execute sql into uuid; execute sql into uuid;
exception exception
when others then when others then
@ -205,7 +204,6 @@ begin
objectTable := pureIdentifier(objectTable); objectTable := pureIdentifier(objectTable);
sql := format('select * from %sIdNameByUuid(%L::uuid);', objectTable, objectUuid); sql := format('select * from %sIdNameByUuid(%L::uuid);', objectTable, objectUuid);
begin begin
raise notice 'sql: %', sql;
execute sql into idName; execute sql into idName;
exception exception
when others then when others then

View File

@ -106,7 +106,6 @@ begin
createTriggerSQL = 'CREATE TRIGGER ' || targetTable || '_journal' || createTriggerSQL = 'CREATE TRIGGER ' || targetTable || '_journal' ||
' AFTER INSERT OR UPDATE OR DELETE ON ' || targetTable || ' AFTER INSERT OR UPDATE OR DELETE ON ' || targetTable ||
' FOR EACH ROW EXECUTE PROCEDURE tx_journal_trigger()'; ' FOR EACH ROW EXECUTE PROCEDURE tx_journal_trigger()';
raise notice 'sql: %', createTriggerSQL;
execute createTriggerSQL; execute createTriggerSQL;
end; $$; end; $$;
--// --//

View File

@ -364,8 +364,8 @@ create table RbacGrants
( (
uuid uuid primary key default uuid_generate_v4(), uuid uuid primary key default uuid_generate_v4(),
grantedByRoleUuid uuid references RbacRole (uuid) on delete cascade, grantedByRoleUuid uuid references RbacRole (uuid) on delete cascade,
ascendantUuid uuid references RbacReference (uuid) on delete cascade, ascendantUuid uuid references RbacReference (uuid) on delete cascade not null,
descendantUuid uuid references RbacReference (uuid) on delete cascade, descendantUuid uuid references RbacReference (uuid) on delete cascade not null,
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false) assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
unique (ascendantUuid, descendantUuid) unique (ascendantUuid, descendantUuid)
); );

View File

@ -55,22 +55,45 @@ grant all privileges on rbacrole_rv to restricted;
drop view if exists rbacgrants_ev; drop view if exists rbacgrants_ev;
create or replace view rbacgrants_ev as create or replace view rbacgrants_ev as
-- @formatter:off -- @formatter:off
select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) || '.' || r.roletype as grantedByRoleIdName, select x.grantUuid as uuid,
g.objectTable || '#' || g.objectIdName || '.' || g.roletype as grantedRoleIdName, g.userName, g.assumed, go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || '.' || r.roletype as grantedByRoleIdName,
g.grantedByRoleUuid, g.descendantUuid as grantedRoleUuid, g.ascendantUuid as userUuid, x.ascendingIdName as ascendantIdName,
g.objectTable, g.objectUuid, g.objectIdName, g.roleType as grantedRoleType x.descendingIdName as descendantIdName,
x.grantedByRoleUuid,
x.ascendantUuid as ascendantUuid,
x.descendantUuid as descenantUuid,
x.assumed
from ( from (
select g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed, select g.uuid as grantUuid,
u.name as userName, o.objecttable, r.objectuuid, r.roletype, g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
coalesce(
'user ' || au.name,
'role ' || aro.objectTable || '#' || findIdNameByObjectUuid(aro.objectTable, aro.uuid) || '.' || ar.roletype
) as ascendingIdName,
aro.objectTable, aro.uuid,
coalesce(
'role ' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || '.' || dr.roletype,
'perm ' || dp.op || ' on ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid)
) as descendingIdName,
dro.objectTable, dro.uuid
from rbacgrants as g from rbacgrants as g
join rbacrole as r on r.uuid = g.descendantUuid
join rbacobject o on o.uuid = r.objectuuid left outer join rbacrole as ar on ar.uuid = g.ascendantUuid
right outer join rbacuser u on u.uuid = g.ascendantuuid left outer join rbacobject as aro on aro.uuid = ar.objectuuid
) as g left outer join rbacuser as au on au.uuid = g.ascendantUuid
join RbacRole as r on r.uuid = grantedByRoleUuid
join RbacObject as o on o.uuid = r.objectUuid left outer join rbacrole as dr on dr.uuid = g.descendantUuid
order by grantedRoleIdName; left outer join rbacobject as dro on dro.uuid = dr.objectuuid
left outer join rbacpermission dp on dp.uuid = g.descendantUuid
left outer join rbacobject as dpo on dpo.uuid = dp.objectUuid
) as x
left outer join rbacrole as r on r.uuid = grantedByRoleUuid
left outer join rbacuser u on u.uuid = x.ascendantuuid
left outer join rbacobject go on go.uuid = r.objectuuid
order by x.ascendingIdName, x.descendingIdName;
-- @formatter:on -- @formatter:on
--// --//
@ -96,7 +119,7 @@ select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) ||
from rbacgrants as g from rbacgrants as g
join rbacrole as r on r.uuid = g.descendantUuid join rbacrole as r on r.uuid = g.descendantUuid
join rbacobject o on o.uuid = r.objectuuid join rbacobject o on o.uuid = r.objectuuid
join rbacuser u on u.uuid = g.ascendantuuid left outer join rbacuser u on u.uuid = g.ascendantuuid
where isGranted(currentSubjectsUuids(), r.uuid) where isGranted(currentSubjectsUuids(), r.uuid)
) as g ) as g
join RbacRole as r on r.uuid = grantedByRoleUuid join RbacRole as r on r.uuid = grantedByRoleUuid

View File

@ -0,0 +1,14 @@
package net.hostsharing.hsadminng.rbac.rbacgrant;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.stream.Collectors;
public class RawRbacGrantDisplayExtractor {
@NotNull
public static List<String> grantDisplaysOf(final List<RawRbacGrantEntity> roles) {
return roles.stream().map(RawRbacGrantEntity::toDisplay).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,55 @@
package net.hostsharing.hsadminng.rbac.rbacgrant;
import lombok.*;
import org.springframework.data.annotation.Immutable;
import javax.persistence.*;
import java.util.UUID;
@Entity
@Table(name = "rbacgrants_ev")
@Getter
@Setter
@Builder
@ToString
@Immutable
@NoArgsConstructor
@AllArgsConstructor
public class RawRbacGrantEntity {
@Id
private UUID uuid;
@Column(name = "grantedbyroleidname", updatable = false, insertable = false)
private String grantedByRoleIdName;
@Column(name = "grantedbyroleuuid", updatable = false, insertable = false)
private UUID grantedByRoleUuid;
@Column(name = "ascendantidname", updatable = false, insertable = false)
private String ascendantIdName;
@Column(name = "ascendantuuid", updatable = false, insertable = false)
private UUID ascendingUuid;
@Column(name = "descendantidname", updatable = false, insertable = false)
private String descendantIdName;
@Column(name = "descenantuuid", updatable = false, insertable = false)
private UUID descendantUuid;
@Column(name = "assumed", updatable = false, insertable = false)
private boolean assumed;
public String toDisplay() {
// @formatter:off
return "{ grant " + descendantIdName +
" to " + ascendantIdName +
" by " + ( grantedByRoleUuid == null
? "system"
: grantedByRoleIdName ) +
( assumed ? " and assume" : "") +
" }";
// @formatter:on
}
}

View File

@ -0,0 +1,11 @@
package net.hostsharing.hsadminng.rbac.rbacgrant;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.UUID;
public interface RawRbacGrantRepository extends Repository<RawRbacGrantEntity, UUID> {
List<RawRbacGrantEntity> findAll();
}

View File

@ -0,0 +1,38 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import lombok.*;
import org.hibernate.annotations.Formula;
import org.springframework.data.annotation.Immutable;
import javax.persistence.*;
import java.util.UUID;
@Entity
@Table(name = "rbacrole_ev")
@Getter
@Setter
@ToString
@Immutable
@NoArgsConstructor
@AllArgsConstructor
public class RawRbacRoleEntity {
@Id
private UUID uuid;
@Column(name="objectuuid")
private UUID objectUuid;
@Column(name="objecttable")
private String objectTable;
@Column(name="objectidname")
private String objectIdName;
@Column(name="roletype")
@Enumerated(EnumType.STRING)
private RbacRoleType roleType;
@Formula("objectTable||'#'||objectIdName||'.'||roleType")
private String roleName;
}

View File

@ -0,0 +1,15 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.stream.Collectors;
public class RawRbacRoleNameExtractor {
@NotNull
public static List<String> roleNamesOf(@NotNull final List<RawRbacRoleEntity> roles) {
return roles.stream().map(RawRbacRoleEntity::getRoleName).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,11 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.UUID;
public interface RawRbacRoleRepository extends Repository<RawRbacRoleEntity, UUID> {
List<RawRbacRoleEntity> findAll();
}