Enable lazy chat message submission.

Change-Id: I9e9060e29bb63a78591f618cc54acdfb5b49575f
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java
index 74b0b2a..173fb10 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java
@@ -2,25 +2,38 @@
 
 import static javax.ws.rs.core.MediaType.TEXT_HTML;
 
+import eu.mulk.mulkcms2.benki.accesscontrol.Role;
 import eu.mulk.mulkcms2.benki.users.User;
 import io.quarkus.qute.Template;
 import io.quarkus.qute.TemplateExtension;
 import io.quarkus.qute.TemplateInstance;
 import io.quarkus.qute.api.ResourcePath;
+import io.quarkus.security.Authenticated;
 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.Set;
 import javax.annotation.CheckForNull;
 import javax.inject.Inject;
 import javax.json.spi.JsonProvider;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
+import javax.transaction.Transactional;
+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.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.hibernate.Session;
 import org.jboss.logging.Logger;
@@ -63,6 +76,7 @@
         .data("posts", q.posts)
         .data("pageTitle", "Lazy Chat")
         .data("showBookmarkForm", false)
+        .data("showLazychatForm", true)
         .data("hasPreviousPage", q.prevCursor != null)
         .data("hasNextPage", q.nextCursor != null)
         .data("previousCursor", q.prevCursor)
@@ -88,6 +102,7 @@
         .data("posts", q.posts)
         .data("pageTitle", "Lazy Chat")
         .data("showBookmarkForm", false)
+        .data("showLazychatForm", true)
         .data("hasPreviousPage", q.prevCursor != null)
         .data("hasNextPage", q.nextCursor != null)
         .data("previousCursor", q.prevCursor)
@@ -95,6 +110,38 @@
         .data("pageSize", maxResults);
   }
 
+  @POST
+  @Transactional
+  @Authenticated
+  public Response postMessage(
+      @FormParam("text") String text,
+      @FormParam("visibility") @NotNull @Pattern(regexp = "public|semiprivate|private")
+          String visibility)
+      throws URISyntaxException {
+
+    var userName = identity.getPrincipal().getName();
+    var user = User.findByNickname(userName);
+
+    var message = new LazychatMessage();
+    message.content = text;
+    message.format = "markdown";
+    message.owner = user;
+    message.date = OffsetDateTime.now();
+
+    if (visibility.equals("public")) {
+      Role world = Role.find("from Role r join r.tags tag where tag = 'world'").singleResult();
+      message.targets = Set.of(world);
+    } else if (visibility.equals("semiprivate")) {
+      message.targets = Set.copyOf(user.defaultTargets);
+    } else if (!visibility.equals("private")) {
+      throw new BadRequestException(String.format("invalid visibility “%s”", visibility));
+    }
+
+    message.persistAndFlush();
+
+    return Response.seeOther(new URI("/lazychat")).build();
+  }
+
   @TemplateExtension
   static String humanDateTime(TemporalAccessor x) {
     return humanDateFormatter.format(x);