mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 03:09:04 +01:00
Migrate REST classes to Kotlin and upgrade Javalin
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
package org.briarproject.bramble.identity;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class OutputAuthor {
|
||||
|
||||
public final byte[] id;
|
||||
public final String name;
|
||||
public final byte[] publicKey;
|
||||
|
||||
public OutputAuthor(Author author) {
|
||||
this.id = author.getId().getBytes();
|
||||
this.name = author.getName();
|
||||
this.publicKey = author.getPublicKey();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.briarproject.bramble.identity
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author
|
||||
import javax.annotation.concurrent.Immutable
|
||||
|
||||
@Immutable
|
||||
@Suppress("unused")
|
||||
class OutputAuthor(author: Author) {
|
||||
|
||||
val id: ByteArray = author.id.bytes
|
||||
val name: String = author.name
|
||||
val publicKey: ByteArray = author.publicKey
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.briarproject.briar.headless
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author
|
||||
import org.briarproject.bramble.identity.OutputAuthor
|
||||
import org.briarproject.briar.api.blog.MessageType
|
||||
|
||||
fun Author.output() = OutputAuthor(this)
|
||||
|
||||
fun Author.Status.output() = name.toLowerCase()
|
||||
|
||||
fun MessageType.output() = name.toLowerCase()
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package org.briarproject.briar.headless;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.briar.headless.blogs.BlogController;
|
||||
import org.briarproject.briar.headless.contact.ContactController;
|
||||
import org.briarproject.briar.headless.forums.ForumController;
|
||||
import org.briarproject.briar.headless.messaging.MessagingController;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.javalin.Javalin;
|
||||
|
||||
import static io.javalin.ApiBuilder.get;
|
||||
import static io.javalin.ApiBuilder.path;
|
||||
import static io.javalin.ApiBuilder.post;
|
||||
import static io.javalin.event.EventType.SERVER_START_FAILED;
|
||||
import static io.javalin.event.EventType.SERVER_STOPPED;
|
||||
import static java.lang.Runtime.getRuntime;
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
public class Router {
|
||||
|
||||
private final BriarService briarService;
|
||||
private final ContactController contactController;
|
||||
private final MessagingController messagingController;
|
||||
private final ForumController forumController;
|
||||
private final BlogController blogController;
|
||||
|
||||
@Inject
|
||||
public Router(BriarService briarService,
|
||||
ContactController contactController,
|
||||
MessagingController messagingController,
|
||||
ForumController forumController,
|
||||
BlogController blogController) {
|
||||
this.briarService = briarService;
|
||||
this.contactController = contactController;
|
||||
this.messagingController = messagingController;
|
||||
this.forumController = forumController;
|
||||
this.blogController = blogController;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
briarService.start();
|
||||
getRuntime().addShutdownHook(new Thread(briarService::stop));
|
||||
|
||||
Javalin app = Javalin.create()
|
||||
.port(7000)
|
||||
.disableStartupBanner()
|
||||
.enableStandardRequestLogging()
|
||||
.enableRouteOverview("/")
|
||||
.enableDynamicGzip()
|
||||
.event(SERVER_START_FAILED, event -> briarService.stop())
|
||||
.event(SERVER_STOPPED, event -> briarService.stop())
|
||||
.start();
|
||||
|
||||
app.routes(() -> {
|
||||
path("/contacts", () -> get(contactController::list));
|
||||
path("/messages/:contactId", () -> {
|
||||
get(messagingController::list);
|
||||
post(messagingController::write);
|
||||
});
|
||||
path("/forums", () -> {
|
||||
get(forumController::list);
|
||||
post(forumController::create);
|
||||
});
|
||||
path("/blogs", () -> path("/posts", () -> {
|
||||
get(blogController::listPosts);
|
||||
post(blogController::createPost);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.briarproject.briar.headless
|
||||
|
||||
import io.javalin.Javalin
|
||||
import io.javalin.JavalinEvent.SERVER_START_FAILED
|
||||
import io.javalin.JavalinEvent.SERVER_STOPPED
|
||||
import io.javalin.apibuilder.ApiBuilder.*
|
||||
import org.briarproject.briar.headless.blogs.BlogController
|
||||
import org.briarproject.briar.headless.contact.ContactController
|
||||
import org.briarproject.briar.headless.forums.ForumController
|
||||
import org.briarproject.briar.headless.messaging.MessagingController
|
||||
import java.lang.Runtime.getRuntime
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
class Router @Inject
|
||||
constructor(
|
||||
private val briarService: BriarService,
|
||||
private val contactController: ContactController,
|
||||
private val messagingController: MessagingController,
|
||||
private val forumController: ForumController,
|
||||
private val blogController: BlogController
|
||||
) {
|
||||
|
||||
fun start() {
|
||||
briarService.start()
|
||||
getRuntime().addShutdownHook(Thread(Runnable { briarService.stop() }))
|
||||
|
||||
val app = Javalin.create()
|
||||
.port(7000)
|
||||
.disableStartupBanner()
|
||||
.enableDebugLogging()
|
||||
.enableCaseSensitiveUrls()
|
||||
.enableRouteOverview("/")
|
||||
.event(SERVER_START_FAILED) { stop() }
|
||||
.event(SERVER_STOPPED) { stop() }
|
||||
.start()
|
||||
|
||||
app.routes {
|
||||
path("/contacts") {
|
||||
get { ctx -> contactController.list(ctx) }
|
||||
}
|
||||
path("/messages/:contactId") {
|
||||
get { ctx -> messagingController.list(ctx) }
|
||||
post { ctx -> messagingController.write(ctx) }
|
||||
}
|
||||
path("/forums") {
|
||||
get { ctx -> forumController.list(ctx) }
|
||||
post { ctx -> forumController.create(ctx) }
|
||||
}
|
||||
path("/blogs") {
|
||||
path("/posts") {
|
||||
get { ctx -> blogController.listPosts(ctx) }
|
||||
post { ctx -> blogController.createPost(ctx) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stop() {
|
||||
briarService.stop()
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package org.briarproject.briar.headless.blogs;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.blog.Blog;
|
||||
import org.briarproject.briar.api.blog.BlogManager;
|
||||
import org.briarproject.briar.api.blog.BlogPost;
|
||||
import org.briarproject.briar.api.blog.BlogPostFactory;
|
||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.javalin.Context;
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
public class BlogController {
|
||||
|
||||
private final BlogManager blogManager;
|
||||
private final BlogPostFactory blogPostFactory;
|
||||
private final IdentityManager identityManager;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
public BlogController(BlogManager blogManager,
|
||||
BlogPostFactory blogPostFactory, IdentityManager identityManager,
|
||||
Clock clock) {
|
||||
this.blogManager = blogManager;
|
||||
this.blogPostFactory = blogPostFactory;
|
||||
this.identityManager = identityManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
public Context listPosts(Context ctx) throws DbException {
|
||||
List<OutputBlogPost> posts = new ArrayList<>();
|
||||
for (Blog b : blogManager.getBlogs()) {
|
||||
Collection<BlogPostHeader> headers =
|
||||
blogManager.getPostHeaders(b.getId());
|
||||
for (BlogPostHeader header : headers) {
|
||||
String body = blogManager.getPostBody(header.getId());
|
||||
OutputBlogPost post = new OutputBlogPost(header, body);
|
||||
posts.add(post);
|
||||
}
|
||||
}
|
||||
return ctx.json(posts);
|
||||
}
|
||||
|
||||
public Context createPost(Context ctx)
|
||||
throws DbException, GeneralSecurityException, FormatException {
|
||||
String text = ctx.formParam("text");
|
||||
if (text == null || text.length() < 1) {
|
||||
return ctx.status(500).result("Expecting Blog text");
|
||||
} else {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
Blog blog = blogManager.getPersonalBlog(author);
|
||||
long now = clock.currentTimeMillis();
|
||||
BlogPost post = blogPostFactory
|
||||
.createBlogPost(blog.getId(), now, null, author, text);
|
||||
blogManager.addLocalPost(post);
|
||||
BlogPostHeader header = blogManager
|
||||
.getPostHeader(blog.getId(), post.getMessage().getId());
|
||||
OutputBlogPost outputPost = new OutputBlogPost(header, text);
|
||||
return ctx.json(outputPost);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.briarproject.briar.headless.blogs
|
||||
|
||||
import io.javalin.BadRequestResponse
|
||||
import io.javalin.Context
|
||||
import org.briarproject.bramble.api.identity.IdentityManager
|
||||
import org.briarproject.bramble.api.system.Clock
|
||||
import org.briarproject.briar.api.blog.BlogManager
|
||||
import org.briarproject.briar.api.blog.BlogPostFactory
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
class BlogController @Inject
|
||||
constructor(
|
||||
private val blogManager: BlogManager,
|
||||
private val blogPostFactory: BlogPostFactory,
|
||||
private val identityManager: IdentityManager,
|
||||
private val clock: Clock
|
||||
) {
|
||||
|
||||
fun listPosts(ctx: Context): Context {
|
||||
val posts = blogManager.blogs.flatMap { blog ->
|
||||
blogManager.getPostHeaders(blog.id).map { header ->
|
||||
val body = blogManager.getPostBody(header.id)
|
||||
header.output(body)
|
||||
}
|
||||
}
|
||||
return ctx.json(posts)
|
||||
}
|
||||
|
||||
fun createPost(ctx: Context): Context {
|
||||
val text = ctx.formParam("text")
|
||||
if (text == null || text.isEmpty())
|
||||
throw BadRequestResponse("Expecting Blog text")
|
||||
|
||||
val author = identityManager.localAuthor
|
||||
val blog = blogManager.getPersonalBlog(author)
|
||||
val now = clock.currentTimeMillis()
|
||||
val post = blogPostFactory.createBlogPost(blog.id, now, null, author, text)
|
||||
blogManager.addLocalPost(post)
|
||||
val header = blogManager.getPostHeader(blog.id, post.message.id)
|
||||
return ctx.json(header.output(text))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.briarproject.briar.headless.blogs
|
||||
|
||||
import org.briarproject.briar.api.blog.BlogPostHeader
|
||||
|
||||
internal fun BlogPostHeader.output(body: String) = OutputBlogPost(this, body)
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.briarproject.briar.headless.blogs;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.identity.OutputAuthor;
|
||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
class OutputBlogPost {
|
||||
|
||||
public final String body;
|
||||
public final OutputAuthor author;
|
||||
public final String authorStatus, type;
|
||||
public final byte[] id;
|
||||
@Nullable
|
||||
public final byte[] parentId;
|
||||
public final boolean read, rssFeed;
|
||||
public final long timestamp, timestampReceived;
|
||||
|
||||
OutputBlogPost(BlogPostHeader header, String body) {
|
||||
this.body = body;
|
||||
this.author = new OutputAuthor(header.getAuthor());
|
||||
this.authorStatus = header.getAuthorStatus().name().toLowerCase();
|
||||
this.type = header.getType().name().toLowerCase();
|
||||
this.id = header.getId().getBytes();
|
||||
this.parentId = header.getParentId() == null ? null :
|
||||
header.getParentId().getBytes();
|
||||
this.read = header.isRead();
|
||||
this.rssFeed = header.isRssFeed();
|
||||
this.timestamp = header.getTimestamp();
|
||||
this.timestampReceived = header.getTimeReceived();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.briarproject.briar.headless.blogs
|
||||
|
||||
import org.briarproject.bramble.identity.OutputAuthor
|
||||
import org.briarproject.briar.api.blog.BlogPostHeader
|
||||
import org.briarproject.briar.headless.output
|
||||
import javax.annotation.concurrent.Immutable
|
||||
|
||||
@Immutable
|
||||
@Suppress("unused")
|
||||
internal class OutputBlogPost(header: BlogPostHeader, val body: String) {
|
||||
|
||||
val author: OutputAuthor = OutputAuthor(header.author)
|
||||
val authorStatus: String = header.authorStatus.output()
|
||||
val type = header.type.output()
|
||||
val id: ByteArray = header.id.bytes
|
||||
val parentId = header.parentId?.bytes
|
||||
val read = header.isRead
|
||||
val rssFeed = header.isRssFeed
|
||||
val timestamp = header.timestamp
|
||||
val timestampReceived = header.timeReceived
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package org.briarproject.briar.headless.contact;
|
||||
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.javalin.Context;
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
@NotNullByDefault
|
||||
public class ContactController {
|
||||
|
||||
private final ContactManager contactManager;
|
||||
|
||||
@Inject
|
||||
public ContactController(ContactManager contactManager) {
|
||||
this.contactManager = contactManager;
|
||||
}
|
||||
|
||||
public Context list(Context ctx) throws DbException {
|
||||
Collection<Contact> contacts = contactManager.getActiveContacts();
|
||||
List<OutputContact> outputContacts = new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) {
|
||||
outputContacts.add(new OutputContact(c));
|
||||
}
|
||||
return ctx.json(outputContacts);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.briarproject.briar.headless.contact
|
||||
|
||||
import io.javalin.Context
|
||||
import org.briarproject.bramble.api.contact.ContactManager
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
class ContactController @Inject
|
||||
constructor(private val contactManager: ContactManager) {
|
||||
|
||||
fun list(ctx: Context): Context {
|
||||
val contacts = contactManager.activeContacts.map { contact ->
|
||||
contact.output()
|
||||
}
|
||||
return ctx.json(contacts)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.briarproject.briar.headless.contact
|
||||
|
||||
import org.briarproject.bramble.api.contact.Contact
|
||||
|
||||
internal fun Contact.output() = OutputContact(this)
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.briarproject.briar.headless.contact;
|
||||
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.identity.OutputAuthor;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class OutputContact {
|
||||
|
||||
public final int id;
|
||||
public final OutputAuthor author;
|
||||
public final boolean verified;
|
||||
|
||||
public OutputContact(Contact c) {
|
||||
this.id = c.getId().getInt();
|
||||
this.author = new OutputAuthor(c.getAuthor());
|
||||
this.verified = c.isVerified();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.briarproject.briar.headless.contact
|
||||
|
||||
import org.briarproject.bramble.api.contact.Contact
|
||||
import org.briarproject.briar.headless.output
|
||||
import javax.annotation.concurrent.Immutable
|
||||
|
||||
@Immutable
|
||||
@Suppress("unused")
|
||||
internal class OutputContact(c: Contact) {
|
||||
|
||||
val id = c.id.int
|
||||
val author = c.author.output()
|
||||
val verified = c.isVerified
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.briarproject.briar.headless.forums
|
||||
|
||||
import org.briarproject.briar.api.forum.Forum
|
||||
|
||||
internal fun Forum.output() = OutputForum(this)
|
||||
|
||||
internal fun Collection<Forum>.output() = map { it.output() }
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.briarproject.briar.headless.forums;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.briar.api.forum.Forum;
|
||||
import org.briarproject.briar.api.forum.ForumManager;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.javalin.Context;
|
||||
|
||||
import static io.javalin.translator.json.JavalinJsonPlugin.getObjectToJsonMapper;
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
public class ForumController {
|
||||
|
||||
private final ForumManager forumManager;
|
||||
|
||||
@Inject
|
||||
public ForumController(ForumManager forumManager) {
|
||||
this.forumManager = forumManager;
|
||||
}
|
||||
|
||||
public Context list(Context ctx) throws DbException {
|
||||
Collection<Forum> forums = forumManager.getForums();
|
||||
return ctx.result(getObjectToJsonMapper().map(forums));
|
||||
}
|
||||
|
||||
public Context create(Context ctx) throws DbException {
|
||||
String name = ctx.formParam("name");
|
||||
if (name == null || name.length() < 1) {
|
||||
return ctx.status(500).result("Expecting Forum Name");
|
||||
} else {
|
||||
Forum forum = forumManager.addForum(name);
|
||||
return ctx.result(getObjectToJsonMapper().map(forum));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.briarproject.briar.headless.forums
|
||||
|
||||
import io.javalin.BadRequestResponse
|
||||
import io.javalin.Context
|
||||
import org.briarproject.briar.api.forum.ForumManager
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
class ForumController @Inject
|
||||
constructor(private val forumManager: ForumManager) {
|
||||
|
||||
fun list(ctx: Context): Context {
|
||||
return ctx.json(forumManager.forums.output())
|
||||
}
|
||||
|
||||
fun create(ctx: Context): Context {
|
||||
val name = ctx.formParam("name")
|
||||
if (name == null || name.isEmpty())
|
||||
throw BadRequestResponse("Expecting Forum Name")
|
||||
return ctx.json(forumManager.addForum(name).output())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.briarproject.briar.headless.forums
|
||||
|
||||
import org.briarproject.briar.api.forum.Forum
|
||||
import javax.annotation.concurrent.Immutable
|
||||
|
||||
@Immutable
|
||||
@Suppress("unused")
|
||||
internal class OutputForum(forum: Forum) {
|
||||
|
||||
val name: String = forum.name
|
||||
val id: ByteArray = forum.id.bytes
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.briarproject.briar.headless.messaging
|
||||
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader
|
||||
|
||||
internal fun PrivateMessageHeader.output(body: String) = OutputPrivateMessage(this, body)
|
||||
|
||||
internal fun PrivateMessage.output(body: String) = OutputPrivateMessage(this, body)
|
||||
@@ -1,97 +0,0 @@
|
||||
package org.briarproject.briar.headless.messaging;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.NoSuchContactException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.javalin.Context;
|
||||
|
||||
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
@NotNullByDefault
|
||||
public class MessagingController {
|
||||
|
||||
private final MessagingManager messagingManager;
|
||||
private final PrivateMessageFactory privateMessageFactory;
|
||||
private final ContactManager contactManager;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
public MessagingController(MessagingManager messagingManager,
|
||||
PrivateMessageFactory privateMessageFactory,
|
||||
ContactManager contactManager,
|
||||
Clock clock) {
|
||||
this.messagingManager = messagingManager;
|
||||
this.privateMessageFactory = privateMessageFactory;
|
||||
this.contactManager = contactManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
public Context list(Context ctx) throws DbException {
|
||||
Contact contact = getContact(ctx);
|
||||
if (contact == null) return ctx.status(404);
|
||||
|
||||
Collection<PrivateMessageHeader> headers =
|
||||
messagingManager.getMessageHeaders(contact.getId());
|
||||
List<OutputPrivateMessage> messages = new ArrayList<>(headers.size());
|
||||
for (PrivateMessageHeader header : headers) {
|
||||
String body = messagingManager.getMessageBody(header.getId());
|
||||
messages.add(new OutputPrivateMessage(header, body));
|
||||
}
|
||||
return ctx.json(messages);
|
||||
}
|
||||
|
||||
public Context write(Context ctx) throws DbException, FormatException {
|
||||
Contact contact = getContact(ctx);
|
||||
if (contact == null) return ctx.status(404);
|
||||
|
||||
String message = ctx.formParam("message");
|
||||
if (message == null || message.length() < 1)
|
||||
return ctx.status(500).result("Expecting Message text");
|
||||
if (message.length() > MAX_PRIVATE_MESSAGE_BODY_LENGTH)
|
||||
return ctx.status(500).result("Message text too large");
|
||||
|
||||
Group group = messagingManager.getContactGroup(contact);
|
||||
long now = clock.currentTimeMillis();
|
||||
PrivateMessage m = privateMessageFactory
|
||||
.createPrivateMessage(group.getId(), now, message);
|
||||
|
||||
messagingManager.addLocalMessage(m);
|
||||
return ctx.json(new OutputPrivateMessage(m, message));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Contact getContact(Context ctx) throws DbException {
|
||||
String contactString = ctx.param("contactId");
|
||||
if (contactString == null) return null;
|
||||
int contactInt = Integer.parseInt(contactString);
|
||||
ContactId contactId = new ContactId(contactInt);
|
||||
try {
|
||||
return contactManager.getContact(contactId);
|
||||
} catch (NoSuchContactException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.briarproject.briar.headless.messaging
|
||||
|
||||
import io.javalin.BadRequestResponse
|
||||
import io.javalin.Context
|
||||
import io.javalin.NotFoundResponse
|
||||
import org.briarproject.bramble.api.contact.Contact
|
||||
import org.briarproject.bramble.api.contact.ContactId
|
||||
import org.briarproject.bramble.api.contact.ContactManager
|
||||
import org.briarproject.bramble.api.db.NoSuchContactException
|
||||
import org.briarproject.bramble.api.system.Clock
|
||||
import org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH
|
||||
import org.briarproject.briar.api.messaging.MessagingManager
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Immutable
|
||||
@Singleton
|
||||
class MessagingController @Inject
|
||||
constructor(
|
||||
private val messagingManager: MessagingManager,
|
||||
private val privateMessageFactory: PrivateMessageFactory,
|
||||
private val contactManager: ContactManager,
|
||||
private val clock: Clock
|
||||
) {
|
||||
|
||||
fun list(ctx: Context): Context {
|
||||
val contact = getContact(ctx)
|
||||
|
||||
val messages = messagingManager.getMessageHeaders(contact.id).map { header ->
|
||||
val body = messagingManager.getMessageBody(header.id)
|
||||
header.output(body)
|
||||
}
|
||||
return ctx.json(messages)
|
||||
}
|
||||
|
||||
fun write(ctx: Context): Context {
|
||||
val contact = getContact(ctx)
|
||||
|
||||
val message = ctx.formParam("message")
|
||||
if (message == null || message.isEmpty())
|
||||
throw BadRequestResponse("Expecting Message text")
|
||||
if (message.length > MAX_PRIVATE_MESSAGE_BODY_LENGTH)
|
||||
throw BadRequestResponse("Message text too large")
|
||||
|
||||
val group = messagingManager.getContactGroup(contact)
|
||||
val now = clock.currentTimeMillis()
|
||||
val m = privateMessageFactory.createPrivateMessage(group.id, now, message)
|
||||
|
||||
messagingManager.addLocalMessage(m)
|
||||
return ctx.json(m.output(message))
|
||||
}
|
||||
|
||||
private fun getContact(ctx: Context): Contact {
|
||||
val contactString = ctx.pathParam("contactId")
|
||||
val contactInt = Integer.parseInt(contactString)
|
||||
val contactId = ContactId(contactInt)
|
||||
return try {
|
||||
contactManager.getContact(contactId)
|
||||
} catch (e: NoSuchContactException) {
|
||||
throw NotFoundResponse()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.briarproject.briar.headless.messaging;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class OutputPrivateMessage {
|
||||
|
||||
public final String body;
|
||||
public final long timestamp;
|
||||
public final boolean read, seen, sent, local;
|
||||
public final byte[] id, groupId;
|
||||
|
||||
OutputPrivateMessage(PrivateMessageHeader header, String body) {
|
||||
this.body = body;
|
||||
this.timestamp = header.getTimestamp();
|
||||
this.read = header.isRead();
|
||||
this.seen = header.isSeen();
|
||||
this.sent = header.isSent();
|
||||
this.local = header.isLocal();
|
||||
this.id = header.getId().getBytes();
|
||||
this.groupId = header.getGroupId().getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Only meant for own {@link PrivateMessage}s directly after creation.
|
||||
*/
|
||||
OutputPrivateMessage(PrivateMessage m, String body) {
|
||||
this.body = body;
|
||||
this.timestamp = m.getMessage().getTimestamp();
|
||||
this.read = true;
|
||||
this.seen = true;
|
||||
this.sent = false;
|
||||
this.local = true;
|
||||
this.id = m.getMessage().getId().getBytes();
|
||||
this.groupId = m.getMessage().getGroupId().getBytes();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.briarproject.briar.headless.messaging
|
||||
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader
|
||||
import javax.annotation.concurrent.Immutable
|
||||
|
||||
@Immutable
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
internal class OutputPrivateMessage {
|
||||
|
||||
val body: String
|
||||
val timestamp: Long
|
||||
val read: Boolean
|
||||
val seen: Boolean
|
||||
val sent: Boolean
|
||||
val local: Boolean
|
||||
val id: ByteArray
|
||||
val groupId: ByteArray
|
||||
|
||||
internal constructor(header: PrivateMessageHeader, body: String) {
|
||||
this.body = body
|
||||
this.timestamp = header.timestamp
|
||||
this.read = header.isRead
|
||||
this.seen = header.isSeen
|
||||
this.sent = header.isSent
|
||||
this.local = header.isLocal
|
||||
this.id = header.id.bytes
|
||||
this.groupId = header.groupId.bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Only meant for own [PrivateMessage]s directly after creation.
|
||||
*/
|
||||
internal constructor(m: PrivateMessage, body: String) {
|
||||
this.body = body
|
||||
this.timestamp = m.message.timestamp
|
||||
this.read = true
|
||||
this.seen = true
|
||||
this.sent = false
|
||||
this.local = true
|
||||
this.id = m.message.id.bytes
|
||||
this.groupId = m.message.groupId.bytes
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user