diff options
Diffstat (limited to 'src/main')
8 files changed, 98 insertions, 3 deletions
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<UserRole> 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<SecurityIdentity> augment( + SecurityIdentity identity, AuthenticationRequestContext context) { + + if (identity.isAnonymous()) { + return Uni.createFrom().item(identity); + } + + return augmentWithRoles(identity, context); + } + + @Transactional + Uni<SecurityIdentity> augmentWithRoles( + SecurityIdentity identity, AuthenticationRequestContext context) { + return context.runBlocking( + () -> { + Set<String> loginRoles = getUserLoginRoles(identity.getPrincipal().getName()); + return QuarkusSecurityIdentity.builder(identity).addRoles(loginRoles).build(); + }); + } + + @CacheResult(cacheName = "login-role-cache") + Set<String> getUserLoginRoles(String userNickname) { + var user = User.findByNicknameWithRoles(userNickname); + return user.effectiveRoles.stream() + .flatMap(RoleAugmentor::roleTags) + .flatMap(RoleAugmentor::loginRoleOfTag) + .collect(Collectors.toSet()); + } + + private static Stream<String> roleTags(Role role) { + return role.tags.stream(); + } + + private static Stream<String> 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 @@ </createIndex> </changeSet> + <changeSet id="1.8-4" author="mulk"> + <sql> + 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'])); + </sql> + </changeSet> + </databaseChangeLog> 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 @@ </ol> </li> - {#if inject:LoginStatus.loggedIn} + {#if inject:LoginStatus.isEditor} <li class='{#if siteSection == "Wiki"}this-page{/}' data-site-section="Wiki"><a href="/wiki/Home">Wiki</a></li> {/if} |