diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2020-02-10 20:58:13 +0100 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2020-02-10 21:01:53 +0100 |
commit | bca94613c19acf02ea333d57090e535b28afd2b4 (patch) | |
tree | c753136015c276d389ca05ecba4306f02ce9b699 | |
parent | ee5d99727cfad928cdf9013f71f7439d54a70bb6 (diff) |
Book Marx: Implement bookmark submission.
Change-Id: Ieb1fef8565ed0e17de9590d5207ba11ebfe6f177
7 files changed, 103 insertions, 100 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 7c0db71..4bfba8e 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java @@ -2,7 +2,6 @@ package eu.mulk.mulkcms2.benki.accesscontrol; import eu.mulk.mulkcms2.benki.generic.PostTarget; import eu.mulk.mulkcms2.benki.users.User; -import eu.mulk.mulkcms2.benki.users.UserDefaultTarget; import eu.mulk.mulkcms2.benki.users.UserRole; import io.quarkus.hibernate.orm.panache.PanacheEntityBase; import java.util.Collection; @@ -59,8 +58,8 @@ public class Role extends PanacheEntityBase { @ManyToMany(mappedBy = "effectiveSubroles", fetch = FetchType.LAZY) public Set<Role> effectiveSuperroles; - @OneToMany(mappedBy = "target", fetch = FetchType.LAZY) - public Collection<UserDefaultTarget> usersUsedByAsDefaultTarget; + @ManyToMany(mappedBy = "defaultTargets", fetch = FetchType.LAZY) + public Set<User> usersUsedByAsDefaultTarget; @OneToMany(mappedBy = "role", fetch = FetchType.LAZY) public Collection<UserRole> directUsers; diff --git a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java index 45c7087..463551c 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java @@ -10,15 +10,27 @@ import io.quarkus.qute.TemplateExtension; import io.quarkus.qute.TemplateInstance; import io.quarkus.qute.api.ResourcePath; import io.quarkus.security.identity.SecurityIdentity; +import java.net.URI; +import java.net.URISyntaxException; +import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.time.temporal.TemporalAccessor; import java.util.List; +import java.util.Set; import javax.inject.Inject; import javax.json.spi.JsonProvider; +import javax.transaction.Transactional; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; import org.jboss.logging.Logger; @Path("/bookmarks") @@ -41,7 +53,7 @@ public class BookmarkResource { @GET @Produces(TEXT_HTML) - public TemplateInstance getPage() { + public TemplateInstance getIndex() { List<Bookmark> bookmarks; if (identity.isAnonymous()) { Role world = Role.find("from Role r join r.tags tag where tag = 'world'").singleResult(); @@ -62,7 +74,44 @@ public class BookmarkResource { user.id) .list(); } - return bookmarkList.data("bookmarks", bookmarks); + return bookmarkList + .data("bookmarks", bookmarks) + .data("authenticated", !identity.isAnonymous()); + } + + @POST + @Transactional + public Response postBookmark( + @FormParam("uri") URI uri, + @FormParam("title") @NotEmpty String title, + @FormParam("description") String description, + @FormParam("visibility") @NotNull @Pattern(regexp = "public|semiprivate|private") String visibility) + throws URISyntaxException { + + var userName = identity.getPrincipal().getName(); + User user = + User.find("from BenkiUser u join u.nicknames n where ?1 = n", userName).singleResult(); + + var bookmark = new Bookmark(); + bookmark.uri = uri.toString(); + bookmark.title = title; + bookmark.tags = Set.of(); + bookmark.description = description != null ? description : ""; + bookmark.owner = user; + bookmark.date = OffsetDateTime.now(); + + if (visibility.equals("public")) { + Role world = Role.find("from Role r join r.tags tag where tag = 'world'").singleResult(); + bookmark.targets = Set.of(world); + } else if (visibility.equals("semiprivate")) { + bookmark.targets = Set.copyOf(user.defaultTargets); + } else if (!visibility.equals("private")) { + throw new BadRequestException(String.format("invalid visibility ā%sā", visibility)); + } + + bookmark.persistAndFlush(); + + return Response.seeOther(new URI("/bookmarks")).build(); } @TemplateExtension 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 31c13dd..1a0dae6 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/users/User.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/users/User.java @@ -68,8 +68,13 @@ public class User extends PanacheEntityBase { @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY) public Collection<Post> posts; - @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) - public Collection<UserDefaultTarget> defaultTargets; + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable( + name = "user_default_target", + schema = "benki", + joinColumns = @JoinColumn(name = "user"), + inverseJoinColumns = @JoinColumn(name = "target")) + public Set<Role> defaultTargets; @ElementCollection(fetch = FetchType.LAZY) @CollectionTable( diff --git a/src/main/java/eu/mulk/mulkcms2/benki/users/UserDefaultTarget.java b/src/main/java/eu/mulk/mulkcms2/benki/users/UserDefaultTarget.java deleted file mode 100644 index 94efef1..0000000 --- a/src/main/java/eu/mulk/mulkcms2/benki/users/UserDefaultTarget.java +++ /dev/null @@ -1,34 +0,0 @@ -package eu.mulk.mulkcms2.benki.users; - -import eu.mulk.mulkcms2.benki.accesscontrol.Role; -import io.quarkus.hibernate.orm.panache.PanacheEntityBase; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; - -@Entity -@Table(name = "user_default_target", schema = "benki") -@IdClass(UserDefaultTargetPK.class) -public class UserDefaultTarget extends PanacheEntityBase { - - @Id - @Column(name = "user", nullable = false) - public int userId; - - @Id - @Column(name = "target", nullable = false) - public int targetId; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user", referencedColumnName = "id", nullable = false) - public User user; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "target", referencedColumnName = "id", nullable = false) - public Role target; -} diff --git a/src/main/java/eu/mulk/mulkcms2/benki/users/UserDefaultTargetPK.java b/src/main/java/eu/mulk/mulkcms2/benki/users/UserDefaultTargetPK.java deleted file mode 100644 index 4a41e7b..0000000 --- a/src/main/java/eu/mulk/mulkcms2/benki/users/UserDefaultTargetPK.java +++ /dev/null @@ -1,59 +0,0 @@ -package eu.mulk.mulkcms2.benki.users; - -import java.io.Serializable; -import javax.persistence.Column; -import javax.persistence.Id; - -public class UserDefaultTargetPK implements Serializable { - - private int userId; - private int targetId; - - @Column(name = "user", nullable = false) - @Id - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - - @Column(name = "target", nullable = false) - @Id - public int getTargetId() { - return targetId; - } - - public void setTargetId(int targetId) { - this.targetId = targetId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - UserDefaultTargetPK that = (UserDefaultTargetPK) o; - - if (userId != that.userId) { - return false; - } - if (targetId != that.targetId) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = userId; - result = 31 * result + targetId; - return result; - } -} diff --git a/src/main/resources/META-INF/resources/cms2/base.css b/src/main/resources/META-INF/resources/cms2/base.css index e04e5d9..735b297 100644 --- a/src/main/resources/META-INF/resources/cms2/base.css +++ b/src/main/resources/META-INF/resources/cms2/base.css @@ -159,3 +159,7 @@ article.lazychat-message { padding: 0.3em; background: #f0f8f0; } + +#bookmark-submission textarea { + min-width: calc(100% - 12em); +} diff --git a/src/main/resources/templates/benki/bookmarks/bookmarkList.html b/src/main/resources/templates/benki/bookmarks/bookmarkList.html index 0d392c8..9d4c706 100644 --- a/src/main/resources/templates/benki/bookmarks/bookmarkList.html +++ b/src/main/resources/templates/benki/bookmarks/bookmarkList.html @@ -1,4 +1,5 @@ {@java.util.List<eu.mulk.mulkcms2.benki.bookmarks.Bookmark> bookmarks} +{@java.lang.Boolean authenticated} {#include base.html} @@ -10,6 +11,44 @@ {#body} +{#if authenticated} + <section id="bookmark-submission"> + <form class="pure-form pure-form-aligned" method="post"> + <fieldset> + <legend>Submit Bookmark</legend> + + <div class="pure-control-group"> + <label for="title-input">Title:</label> + <input name="title" id="title-input" type="text" placeholder="Title" required/> + </div> + + <div class="pure-control-group"> + <label for="uri-input">URI:</label> + <input name="uri" id="uri-input" type="text" placeholder="URI" required/> + </div> + + <div class="pure-control-group"> + <label for="description-input">Description:</label> + <textarea name="description" id="description-input" placeholder="Description"></textarea> + </div> + + <div class="pure-control-group"> + <label for="visibility-input">Visibility:</label> + <select id="visibility-input" name="visibility" required> + <option value="public">Public</option> + <option value="semiprivate" selected>Semiprivate</option> + <option value="private">Private</option> + </select> + </div> + + <div class="pure-controls"> + <button type="submit" class="pure-button pure-button-primary">Submit Bookmark</button> + </div> + </fieldset> + </form> + </section> +{/if} + {#for bookmark in bookmarks} {#with bookmark} <article class="bookmark"> |