structured-liquibase-files #29
@ -82,7 +82,7 @@ If you have at least Docker and the Java JDK installed in appropriate versions a
|
||||
|
||||
# the following command should return a JSON array with just all packages visible for the admin of the customer yyy:
|
||||
curl \
|
||||
-H 'current-user: superuser-alex@hostsharing.net' -H 'assumed-roles: test_customer#yyy:admin' \
|
||||
-H 'current-user: superuser-alex@hostsharing.net' -H 'assumed-roles: test_customer#yyy:ADMIN' \
|
||||
http://localhost:8080/api/test/packages
|
||||
|
||||
# add a new customer
|
||||
|
22
doc/rbac.md
22
doc/rbac.md
@ -206,7 +206,7 @@ and the *role-stereotype* describes a role relative to a referenced business-obj
|
||||
#### owner
|
||||
|
||||
The owner-role is granted to the subject which created the business object.
|
||||
E.g. for a new *customer* it would be granted to 'administrators' and for a new *package* to the 'customer#...:admin'.
|
||||
E.g. for a new *customer* it would be granted to 'administrators' and for a new *package* to the 'customer#...:ADMIN'.
|
||||
|
||||
Whoever has the owner-role assigned can do everything with the related business-object, including deleting (or deactivating) it.
|
||||
|
||||
@ -470,14 +470,14 @@ together {
|
||||
permCustomerXyzSELECT--> boCustXyz
|
||||
}
|
||||
|
||||
entity "Role customer#xyz:tenant" as roleCustXyzTenant
|
||||
entity "Role customer#xyz:TENANT" as roleCustXyzTenant
|
||||
roleCustXyzTenant --> permCustomerXyzSELECT
|
||||
|
||||
entity "Role customer#xyz:admin" as roleCustXyzAdmin
|
||||
entity "Role customer#xyz:ADMIN" as roleCustXyzAdmin
|
||||
roleCustXyzAdmin --> roleCustXyzTenant
|
||||
roleCustXyzAdmin --> permCustomerXyzINSERT:package
|
||||
|
||||
entity "Role customer#xyz:owner" as roleCustXyzOwner
|
||||
entity "Role customer#xyz:OWNER" as roleCustXyzOwner
|
||||
roleCustXyzOwner ..> roleCustXyzAdmin
|
||||
roleCustXyzOwner --> permCustomerXyzDELETE
|
||||
|
||||
@ -493,7 +493,7 @@ actorHostmaster --> roleAdmins
|
||||
```
|
||||
|
||||
As you can see, there something special:
|
||||
From the 'Role customer#xyz:owner' to the 'Role customer#xyz:admin' there is a dashed line, whereas all other lines are solid lines.
|
||||
From the 'Role customer#xyz:OWNER' to the 'Role customer#xyz:admin' there is a dashed line, whereas all other lines are solid lines.
|
||||
Solid lines means, that one role is granted to another and automatically assumed in all queries to the restricted views.
|
||||
The dashed line means that one role is granted to another but not automatically assumed in queries to the restricted views.
|
||||
|
||||
@ -541,15 +541,15 @@ together {
|
||||
}
|
||||
|
||||
package {
|
||||
entity "Role customer#xyz:tenant" as roleCustXyzTenant
|
||||
entity "Role customer#xyz:admin" as roleCustXyzAdmin
|
||||
entity "Role customer#xyz:owner" as roleCustXyzOwner
|
||||
entity "Role customer#xyz:TENANT" as roleCustXyzTenant
|
||||
entity "Role customer#xyz:ADMIN" as roleCustXyzAdmin
|
||||
entity "Role customer#xyz:OWNER" as roleCustXyzOwner
|
||||
}
|
||||
|
||||
package {
|
||||
entity "Role package#xyz00:owner" as rolePacXyz00Owner
|
||||
entity "Role package#xyz00:admin" as rolePacXyz00Admin
|
||||
entity "Role package#xyz00:tenant" as rolePacXyz00Tenant
|
||||
entity "Role package#xyz00:OWNER" as rolePacXyz00Owner
|
||||
entity "Role package#xyz00:ADMIN" as rolePacXyz00Admin
|
||||
entity "Role package#xyz00:TENANT" as rolePacXyz00Tenant
|
||||
}
|
||||
|
||||
rolePacXyz00Tenant --> permPacXyz00SELECT
|
||||
|
@ -1,7 +1,11 @@
|
||||
|
||||
package net.hostsharing.hsadminng.hs.office.coopassets;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||
@ -10,7 +14,16 @@ import net.hostsharing.hsadminng.stringify.Stringify;
|
||||
import net.hostsharing.hsadminng.stringify.Stringifyable;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.io.IOException;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
@ -20,8 +33,11 @@ import java.util.UUID;
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
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.INSERT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
||||
@ -109,7 +125,7 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUu
|
||||
|
||||
.toRole("membership", ADMIN).grantPermission(INSERT)
|
||||
.toRole("membership", ADMIN).grantPermission(UPDATE)
|
||||
.toRole("membership", ADMIN).grantPermission(SELECT);
|
||||
.toRole("membership", AGENT).grantPermission(SELECT);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
@ -1,6 +1,10 @@
|
||||
package net.hostsharing.hsadminng.hs.office.coopshares;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||
@ -9,7 +13,16 @@ import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||
import net.hostsharing.hsadminng.stringify.Stringifyable;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.io.IOException;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
@ -17,9 +30,11 @@ import java.util.UUID;
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||
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.INSERT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
|
||||
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.Role.ADMIN;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
||||
@ -105,7 +120,7 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUu
|
||||
|
||||
.toRole("membership", ADMIN).grantPermission(INSERT)
|
||||
.toRole("membership", ADMIN).grantPermission(UPDATE)
|
||||
.toRole("membership", ADMIN).grantPermission(SELECT);
|
||||
.toRole("membership", AGENT).grantPermission(SELECT);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
@ -27,7 +27,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.REFERRER;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql;
|
||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
|
||||
@ -145,14 +145,14 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable {
|
||||
|
||||
.createRole(OWNER, (with) -> {
|
||||
with.owningUser(CREATOR);
|
||||
with.incomingSuperRole("partnerRel", ADMIN);
|
||||
with.permission(DELETE);
|
||||
})
|
||||
.createSubRole(ADMIN, (with) -> {
|
||||
with.incomingSuperRole("partnerRel", AGENT);
|
||||
with.incomingSuperRole("partnerRel", ADMIN);
|
||||
with.permission(DELETE);
|
||||
with.permission(UPDATE);
|
||||
})
|
||||
.createSubRole(REFERRER, (with) -> {
|
||||
.createSubRole(AGENT, (with) -> {
|
||||
with.incomingSuperRole("partnerRel", AGENT);
|
||||
with.outgoingSubRole("partnerRel", TENANT);
|
||||
with.permission(SELECT);
|
||||
});
|
||||
|
@ -112,7 +112,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
|
||||
.map(s -> s.replace("hs_office_", ""))
|
||||
.containsExactlyInAnyOrder(Array.fromFormatted(
|
||||
initialGrantNames,
|
||||
"{ grant perm:coopassetstransaction#temprefB:SELECT to role:membership#M-1000101:ADMIN by system and assume }",
|
||||
"{ grant perm:coopassetstransaction#temprefB:SELECT to role:membership#M-1000101:AGENT by system and assume }",
|
||||
"{ grant perm:coopassetstransaction#temprefB:UPDATE to role:membership#M-1000101:ADMIN by system and assume }",
|
||||
null));
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase
|
||||
.map(s -> s.replace("hs_office_", ""))
|
||||
.containsExactlyInAnyOrder(Array.fromFormatted(
|
||||
initialGrantNames,
|
||||
"{ grant perm:coopsharestransaction#temprefB:SELECT to role:membership#M-1000101:ADMIN by system and assume }",
|
||||
"{ grant perm:coopsharestransaction#temprefB:SELECT to role:membership#M-1000101:AGENT by system and assume }",
|
||||
"{ grant perm:coopsharestransaction#temprefB:UPDATE to role:membership#M-1000101:ADMIN by system and assume }",
|
||||
null));
|
||||
}
|
||||
|
@ -335,18 +335,18 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle
|
||||
}
|
||||
|
||||
@Test
|
||||
void partnerRelAgent_canPatchValidityOfRelatedMembership() {
|
||||
void partnerRelAdmin_canPatchValidityOfRelatedMembership() {
|
||||
|
||||
// given
|
||||
final var givenPartnerAgent = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT";
|
||||
context.define("superuser-alex@hostsharing.net", givenPartnerAgent);
|
||||
final var givenPartnerAdmin = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN";
|
||||
context.define("superuser-alex@hostsharing.net", givenPartnerAdmin);
|
||||
final var givenMembership = givenSomeTemporaryMembershipBessler("First");
|
||||
|
||||
// when
|
||||
RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "superuser-alex@hostsharing.net")
|
||||
.header("assumed-roles", givenPartnerAgent)
|
||||
.header("assumed-roles", givenPartnerAdmin)
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""
|
||||
{
|
||||
|
@ -110,9 +110,9 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
|
||||
final var all = rawRoleRepo.findAll();
|
||||
assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(
|
||||
initialRoleNames,
|
||||
"hs_office_membership#M-1000117:ADMIN",
|
||||
"hs_office_membership#M-1000117:OWNER",
|
||||
"hs_office_membership#M-1000117:REFERRER"));
|
||||
"hs_office_membership#M-1000117:ADMIN",
|
||||
"hs_office_membership#M-1000117:AGENT"));
|
||||
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
|
||||
.map(s -> s.replace("hs_office_", ""))
|
||||
.containsExactlyInAnyOrder(Array.fromFormatted(
|
||||
@ -122,21 +122,20 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
|
||||
"{ grant perm:membership#M-1000117:INSERT>coopsharestransaction to role:membership#M-1000117:ADMIN by system and assume }",
|
||||
|
||||
// owner
|
||||
"{ grant perm:membership#M-1000117:DELETE to role:membership#M-1000117:OWNER by system and assume }",
|
||||
"{ grant perm:membership#M-1000117:DELETE to role:membership#M-1000117:ADMIN by system and assume }",
|
||||
"{ grant role:membership#M-1000117:OWNER to user:superuser-alex@hostsharing.net by membership#M-1000117:OWNER and assume }",
|
||||
|
||||
// admin
|
||||
"{ grant perm:membership#M-1000117:UPDATE to role:membership#M-1000117:ADMIN by system and assume }",
|
||||
"{ grant role:membership#M-1000117:ADMIN to role:membership#M-1000117:OWNER by system and assume }",
|
||||
"{ grant role:membership#M-1000117:OWNER to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }",
|
||||
"{ grant role:membership#M-1000117:OWNER to user:superuser-alex@hostsharing.net by membership#M-1000117:OWNER and assume }",
|
||||
"{ grant perm:membership#M-1000117:UPDATE to role:membership#M-1000117:ADMIN by system and assume }",
|
||||
"{ grant role:membership#M-1000117:ADMIN to role:membership#M-1000117:OWNER by system and assume }",
|
||||
"{ grant role:membership#M-1000117:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }",
|
||||
|
||||
// agent
|
||||
"{ grant role:membership#M-1000117:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }",
|
||||
"{ grant perm:membership#M-1000117:SELECT to role:membership#M-1000117:AGENT by system and assume }",
|
||||
"{ grant role:membership#M-1000117:AGENT to role:membership#M-1000117:ADMIN by system and assume }",
|
||||
|
||||
// referrer
|
||||
"{ grant perm:membership#M-1000117:SELECT to role:membership#M-1000117:REFERRER by system and assume }",
|
||||
"{ grant role:membership#M-1000117:REFERRER to role:membership#M-1000117:ADMIN by system and assume }",
|
||||
"{ grant role:relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT to role:membership#M-1000117:REFERRER by system and assume }",
|
||||
"{ grant role:membership#M-1000117:AGENT to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }",
|
||||
"{ grant role:relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT to role:membership#M-1000117:AGENT by system and assume }",
|
||||
|
||||
null));
|
||||
}
|
||||
@ -224,20 +223,20 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
|
||||
}
|
||||
|
||||
@Test
|
||||
public void membershipReferrer_canViewButNotUpdateRelatedMembership() {
|
||||
public void membershipAgent_canViewButNotUpdateRelatedMembership() {
|
||||
// given
|
||||
context("superuser-alex@hostsharing.net");
|
||||
final var givenMembership = givenSomeTemporaryMembership("First", "13");
|
||||
assertThatMembershipExistsAndIsAccessibleToCurrentContext(givenMembership);
|
||||
assertThatMembershipIsVisibleForRole(
|
||||
givenMembership,
|
||||
"hs_office_membership#M-1000113:REFERRER");
|
||||
"hs_office_membership#M-1000113:AGENT");
|
||||
final var newValidityEnd = LocalDate.now();
|
||||
|
||||
// when
|
||||
final var result = jpaAttempt.transacted(() -> {
|
||||
// TODO: we should test with debitor- and partner-admin as well
|
||||
context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000113:REFERRER");
|
||||
context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000113:AGENT");
|
||||
givenMembership.setValidity(
|
||||
Range.closedOpen(givenMembership.getValidity().lower(), newValidityEnd));
|
||||
return membershipRepo.save(givenMembership);
|
||||
|
@ -507,7 +507,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest {
|
||||
}).assertNotNull().returnedValue();
|
||||
}
|
||||
|
||||
RbacRoleRvEntity getRbacRoleByName(final String roleName) {
|
||||
RbacRoleEntity getRbacRoleByName(final String roleName) {
|
||||
return jpaAttempt.transacted(() -> {
|
||||
context("superuser-alex@hostsharing.net", null);
|
||||
return rbacRoleRepository.findByRoleName(roleName);
|
||||
|
Loading…
Reference in New Issue
Block a user