blob: a535d0db75846907e366809b5c21cb8770fe471e [file] [log] [blame]
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +01001package eu.mulk.mulkcms2.benki.bookmarks;
2
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +01003import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +01004import static javax.ws.rs.core.MediaType.TEXT_HTML;
5
6import eu.mulk.mulkcms2.benki.accesscontrol.Role;
7import eu.mulk.mulkcms2.benki.users.User;
8import io.quarkus.panache.common.Sort;
9import io.quarkus.qute.Template;
10import io.quarkus.qute.TemplateExtension;
11import io.quarkus.qute.TemplateInstance;
12import io.quarkus.qute.api.ResourcePath;
Matthias Andreas Benkardf20e9b92020-02-10 21:14:57 +010013import io.quarkus.security.Authenticated;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010014import io.quarkus.security.identity.SecurityIdentity;
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +010015import java.io.IOException;
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010016import java.net.URI;
17import java.net.URISyntaxException;
18import java.time.OffsetDateTime;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010019import java.time.format.DateTimeFormatter;
20import java.time.format.FormatStyle;
21import java.time.temporal.TemporalAccessor;
22import java.util.List;
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010023import java.util.Set;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010024import javax.inject.Inject;
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +010025import javax.json.JsonObject;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010026import javax.json.spi.JsonProvider;
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010027import javax.transaction.Transactional;
28import javax.validation.constraints.NotEmpty;
29import javax.validation.constraints.NotNull;
30import javax.validation.constraints.Pattern;
31import javax.ws.rs.BadRequestException;
32import javax.ws.rs.FormParam;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010033import javax.ws.rs.GET;
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010034import javax.ws.rs.POST;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010035import javax.ws.rs.Path;
36import javax.ws.rs.Produces;
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +010037import javax.ws.rs.QueryParam;
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010038import javax.ws.rs.core.Response;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010039import org.jboss.logging.Logger;
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +010040import org.jsoup.Jsoup;
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010041
42@Path("/bookmarks")
43public class BookmarkResource {
44
45 private static Logger log = Logger.getLogger(BookmarkResource.class);
46
47 private static DateTimeFormatter htmlDateFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
48
49 private static DateTimeFormatter humanDateFormatter =
50 DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT);
51
52 private static JsonProvider jsonProvider = JsonProvider.provider();
53
54 @ResourcePath("benki/bookmarks/bookmarkList.html")
55 @Inject
56 Template bookmarkList;
57
58 @Inject SecurityIdentity identity;
59
60 @GET
61 @Produces(TEXT_HTML)
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010062 public TemplateInstance getIndex() {
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +010063 List<Bookmark> bookmarks;
64 if (identity.isAnonymous()) {
65 Role world = Role.find("from Role r join r.tags tag where tag = 'world'").singleResult();
66 bookmarks =
67 Bookmark.find(
68 "select bm from Bookmark bm join bm.targets target left join fetch bm.owner where target = ?1",
69 Sort.by("date").descending(),
70 world)
71 .list();
72 } else {
73 var userName = identity.getPrincipal().getName();
74 User user =
75 User.find("from BenkiUser u join u.nicknames n where ?1 = n", userName).singleResult();
76 bookmarks =
77 Bookmark.find(
78 "select bm from BenkiUser u inner join u.visibleBookmarks bm left join fetch bm.owner where u.id = ?1",
79 Sort.by("date").descending(),
80 user.id)
81 .list();
82 }
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +010083 return bookmarkList.data("bookmarks", bookmarks).data("authenticated", !identity.isAnonymous());
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010084 }
85
86 @POST
87 @Transactional
Matthias Andreas Benkardf20e9b92020-02-10 21:14:57 +010088 @Authenticated
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010089 public Response postBookmark(
90 @FormParam("uri") URI uri,
91 @FormParam("title") @NotEmpty String title,
92 @FormParam("description") String description,
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +010093 @FormParam("visibility") @NotNull @Pattern(regexp = "public|semiprivate|private")
94 String visibility)
Matthias Andreas Benkardbca94612020-02-10 20:58:13 +010095 throws URISyntaxException {
96
97 var userName = identity.getPrincipal().getName();
98 User user =
99 User.find("from BenkiUser u join u.nicknames n where ?1 = n", userName).singleResult();
100
101 var bookmark = new Bookmark();
102 bookmark.uri = uri.toString();
103 bookmark.title = title;
104 bookmark.tags = Set.of();
105 bookmark.description = description != null ? description : "";
106 bookmark.owner = user;
107 bookmark.date = OffsetDateTime.now();
108
109 if (visibility.equals("public")) {
110 Role world = Role.find("from Role r join r.tags tag where tag = 'world'").singleResult();
111 bookmark.targets = Set.of(world);
112 } else if (visibility.equals("semiprivate")) {
113 bookmark.targets = Set.copyOf(user.defaultTargets);
114 } else if (!visibility.equals("private")) {
115 throw new BadRequestException(String.format("invalid visibility ā€œ%sā€", visibility));
116 }
117
118 bookmark.persistAndFlush();
119
120 return Response.seeOther(new URI("/bookmarks")).build();
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +0100121 }
122
Matthias Andreas Benkard35e14e42020-02-12 06:20:05 +0100123 @GET
124 @Path("page-info")
125 @Authenticated
126 @Produces(APPLICATION_JSON)
127 public JsonObject getPageInfo(@QueryParam("uri") URI uri) throws IOException {
128 var document = Jsoup.connect(uri.toString()).get();
129 return jsonProvider.createObjectBuilder().add("title", document.title()).build();
130 }
131
Matthias Andreas Benkard2d4f92e2020-02-09 16:15:07 +0100132 @TemplateExtension
133 static String humanDateTime(TemporalAccessor x) {
134 return humanDateFormatter.format(x);
135 }
136
137 @TemplateExtension
138 static String htmlDateTime(TemporalAccessor x) {
139 return htmlDateFormatter.format(x);
140 }
141}