From 2f931dece84c0f3f974cbf0d8863046b9268277d Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Mon, 28 Jun 2021 20:56:50 +0200 Subject: KB66 Add editor role. Change-Id: Ibcf94b6532ccb1602bf169ffb434b75557767598 --- pom.xml | 4 ++ .../eu/mulk/mulkcms2/benki/accesscontrol/Role.java | 3 ++ .../eu/mulk/mulkcms2/benki/login/LoginRoles.java | 8 +++ .../eu/mulk/mulkcms2/benki/login/LoginStatus.java | 4 ++ .../mulk/mulkcms2/benki/login/RoleAugmentor.java | 59 ++++++++++++++++++++++ .../eu/mulk/mulkcms2/benki/posts/PostResource.java | 6 ++- .../java/eu/mulk/mulkcms2/benki/users/User.java | 12 +++++ src/main/resources/db/changeLog-1.8.xml | 7 +++ src/main/resources/templates/tags/navbar.html | 2 +- 9 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 src/main/java/eu/mulk/mulkcms2/benki/login/LoginRoles.java create mode 100644 src/main/java/eu/mulk/mulkcms2/benki/login/RoleAugmentor.java diff --git a/pom.xml b/pom.xml index f096d58..8e8c707 100644 --- a/pom.xml +++ b/pom.xml @@ -123,6 +123,10 @@ io.quarkus quarkus-agroal + + io.quarkus + quarkus-cache + io.quarkus quarkus-elytron-security-properties-file diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java index 87b477d..1d66939 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java @@ -22,6 +22,8 @@ import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; +import org.hibernate.annotations.LazyToOne; +import org.hibernate.annotations.LazyToOneOption; @Entity @Table(name = "roles", schema = "benki") @@ -68,6 +70,7 @@ public class Role extends PanacheEntityBase { public Collection directUsers; @OneToOne(mappedBy = "ownedRole", fetch = FetchType.LAZY) + @LazyToOne(LazyToOneOption.NO_PROXY) public User owningUsers; @ManyToMany(mappedBy = "effectiveRoles", fetch = FetchType.LAZY) diff --git a/src/main/java/eu/mulk/mulkcms2/benki/login/LoginRoles.java b/src/main/java/eu/mulk/mulkcms2/benki/login/LoginRoles.java new file mode 100644 index 0000000..27c6f5c --- /dev/null +++ b/src/main/java/eu/mulk/mulkcms2/benki/login/LoginRoles.java @@ -0,0 +1,8 @@ +package eu.mulk.mulkcms2.benki.login; + +public final class LoginRoles { + + public static final String EDITOR = "EDITOR"; + + private LoginRoles() {} +} diff --git a/src/main/java/eu/mulk/mulkcms2/benki/login/LoginStatus.java b/src/main/java/eu/mulk/mulkcms2/benki/login/LoginStatus.java index 06a184c..a217dba 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/login/LoginStatus.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/login/LoginStatus.java @@ -17,6 +17,10 @@ public class LoginStatus { return !identity.isAnonymous(); } + public boolean isEditor() { + return identity.hasRole(LoginRoles.EDITOR); + } + public String getUserName() { return identity.getPrincipal().getName(); } diff --git a/src/main/java/eu/mulk/mulkcms2/benki/login/RoleAugmentor.java b/src/main/java/eu/mulk/mulkcms2/benki/login/RoleAugmentor.java new file mode 100644 index 0000000..3aafc0e --- /dev/null +++ b/src/main/java/eu/mulk/mulkcms2/benki/login/RoleAugmentor.java @@ -0,0 +1,59 @@ +package eu.mulk.mulkcms2.benki.login; + +import eu.mulk.mulkcms2.benki.accesscontrol.Role; +import eu.mulk.mulkcms2.benki.users.User; +import io.quarkus.cache.CacheResult; +import io.quarkus.security.identity.AuthenticationRequestContext; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.identity.SecurityIdentityAugmentor; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.enterprise.context.ApplicationScoped; +import javax.transaction.Transactional; + +@ApplicationScoped +public class RoleAugmentor implements SecurityIdentityAugmentor { + + private static final String EDITOR_TAG = "editor"; + + @Override + public Uni augment( + SecurityIdentity identity, AuthenticationRequestContext context) { + + if (identity.isAnonymous()) { + return Uni.createFrom().item(identity); + } + + return augmentWithRoles(identity, context); + } + + @Transactional + Uni augmentWithRoles( + SecurityIdentity identity, AuthenticationRequestContext context) { + return context.runBlocking( + () -> { + Set loginRoles = getUserLoginRoles(identity.getPrincipal().getName()); + return QuarkusSecurityIdentity.builder(identity).addRoles(loginRoles).build(); + }); + } + + @CacheResult(cacheName = "login-role-cache") + Set getUserLoginRoles(String userNickname) { + var user = User.findByNicknameWithRoles(userNickname); + return user.effectiveRoles.stream() + .flatMap(RoleAugmentor::roleTags) + .flatMap(RoleAugmentor::loginRoleOfTag) + .collect(Collectors.toSet()); + } + + private static Stream roleTags(Role role) { + return role.tags.stream(); + } + + private static Stream loginRoleOfTag(String tag) { + return tag.equals(EDITOR_TAG) ? Stream.of(LoginRoles.EDITOR) : Stream.empty(); + } +} diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java index c0d8647..495c780 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java @@ -14,6 +14,8 @@ import com.rometools.rome.io.FeedException; import com.rometools.rome.io.WireFeedOutput; import eu.mulk.mulkcms2.benki.accesscontrol.PageKey; import eu.mulk.mulkcms2.benki.accesscontrol.Role; +import eu.mulk.mulkcms2.benki.login.LoginRoles; +import eu.mulk.mulkcms2.benki.login.LoginStatus; import eu.mulk.mulkcms2.benki.posts.Post.PostPage; import eu.mulk.mulkcms2.benki.users.User; import io.quarkus.qute.Template; @@ -419,7 +421,7 @@ public abstract class PostResource { switch (postFilter) { case ALL: case BOOKMARKS_ONLY: - return !identity.isAnonymous(); + return identity.hasRole(LoginRoles.EDITOR); case LAZYCHAT_MESSAGES_ONLY: return false; default: @@ -431,7 +433,7 @@ public abstract class PostResource { switch (postFilter) { case ALL: case LAZYCHAT_MESSAGES_ONLY: - return !identity.isAnonymous(); + return identity.hasRole(LoginRoles.EDITOR); case BOOKMARKS_ONLY: return false; default: diff --git a/src/main/java/eu/mulk/mulkcms2/benki/users/User.java b/src/main/java/eu/mulk/mulkcms2/benki/users/User.java index 96feafc..04a5cd4 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/users/User.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/users/User.java @@ -150,6 +150,18 @@ public class User extends PanacheEntityBase { return User.find("from BenkiUser u join u.nicknames n where ?1 = n", nickname).singleResult(); } + public static User findByNicknameWithRoles(String nickname) { + return User.find( + "" + + "from BenkiUser u " + + "join u.nicknames n " + + "left join fetch u.effectiveRoles r " + + "left join fetch r.tags " + + "where ?1 = n", + nickname) + .singleResult(); + } + public final boolean canSee(Post message) { return message.isVisibleTo(this); } diff --git a/src/main/resources/db/changeLog-1.8.xml b/src/main/resources/db/changeLog-1.8.xml index 2359001..05948b0 100644 --- a/src/main/resources/db/changeLog-1.8.xml +++ b/src/main/resources/db/changeLog-1.8.xml @@ -55,4 +55,11 @@ + + + ALTER TABLE benki.role_tags DROP CONSTRAINT role_tags_tag_check; + ALTER TABLE benki.role_tags ADD CONSTRAINT role_tags_tag_check CHECK (tag = ANY(ARRAY['admin', 'everyone', 'world', 'editor'])); + + + diff --git a/src/main/resources/templates/tags/navbar.html b/src/main/resources/templates/tags/navbar.html index 17a25dd..750d3e1 100644 --- a/src/main/resources/templates/tags/navbar.html +++ b/src/main/resources/templates/tags/navbar.html @@ -10,7 +10,7 @@ - {#if inject:LoginStatus.loggedIn} + {#if inject:LoginStatus.isEditor}
  • Wiki
  • {/if} -- cgit v1.2.3