Migrate REST classes to Kotlin and upgrade Javalin

This commit is contained in:
Torsten Grote
2018-08-27 16:26:41 -03:00
parent 33c509cd1f
commit 348968018a
27 changed files with 397 additions and 496 deletions

View File

@@ -36,6 +36,9 @@
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" /> <option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" /> <option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
</JavaCodeStyleSettings> </JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<Objective-C-extensions> <Objective-C-extensions>
<file> <file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" /> <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
@@ -258,14 +261,10 @@
</arrangement> </arrangement>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="kotlin"> <codeStyleSettings language="kotlin">
<option name="CALL_PARAMETERS_WRAP" value="1" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="PARAMETER_ANNOTATION_WRAP" value="1" /> <option name="PARAMETER_ANNOTATION_WRAP" value="1" />
<option name="VARIABLE_ANNOTATION_WRAP" value="1" /> <option name="VARIABLE_ANNOTATION_WRAP" value="1" />
<option name="ENUM_CONSTANTS_WRAP" value="1" /> <option name="ENUM_CONSTANTS_WRAP" value="1" />
</codeStyleSettings> </codeStyleSettings>
</code_scheme> </code_scheme>
</component> </component>

View File

@@ -14,11 +14,12 @@ dependencies {
implementation project(path: ':briar-core', configuration: 'default') implementation project(path: ':briar-core', configuration: 'default')
implementation project(path: ':bramble-java', configuration: 'default') implementation project(path: ':bramble-java', configuration: 'default')
implementation 'io.javalin:javalin:1.7.0' implementation 'io.javalin:javalin:2.1.0'
implementation 'org.slf4j:slf4j-simple:1.7.25' implementation 'org.slf4j:slf4j-simple:1.7.25'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.6' implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.6'
apt 'com.google.dagger:dagger-compiler:2.0.2' apt 'com.google.dagger:dagger-compiler:2.0.2'
kapt 'com.google.dagger:dagger-compiler:2.0.2'
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput') testImplementation project(path: ':bramble-core', configuration: 'testOutput')

View File

@@ -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();
}
}

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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);
}));
});
}
}

View File

@@ -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)
}
}

View File

@@ -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);
}
}
}

View File

@@ -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))
}
}

View File

@@ -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)

View File

@@ -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();
}
}

View File

@@ -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
}

View File

@@ -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);
}
}

View File

@@ -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)
}
}

View File

@@ -0,0 +1,5 @@
package org.briarproject.briar.headless.contact
import org.briarproject.bramble.api.contact.Contact
internal fun Contact.output() = OutputContact(this)

View File

@@ -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();
}
}

View File

@@ -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
}

View File

@@ -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() }

View File

@@ -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));
}
}
}

View File

@@ -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())
}
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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;
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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();
}
}

View File

@@ -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
}
}

View File

@@ -7,7 +7,7 @@ dependencyVerification {
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b', 'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9', 'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99', 'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'io.javalin:javalin:1.7.0:javalin-1.7.0.jar:d97d2044a7b050a3b6564c9a99a0a94a4c6d8c57818033cf0d8236bc90a8069b', 'io.javalin:javalin:2.1.0:javalin-2.1.0.jar:d52264afbecddd1a8926a6d3b6f84ca534afa4d3997176c99e96ca2e0874577a',
'io.mockk:mockk-agent-api:1.8.6:mockk-agent-api-1.8.6.jar:613512c66538e6349e03df641a868f4ee324f13e2e1dbd67a0ed388aa664a444', 'io.mockk:mockk-agent-api:1.8.6:mockk-agent-api-1.8.6.jar:613512c66538e6349e03df641a868f4ee324f13e2e1dbd67a0ed388aa664a444',
'io.mockk:mockk-agent-common:1.8.6:mockk-agent-common-1.8.6.jar:cb7cb26fae5bfd3c89090858548990f311b27f673b9efa9d0c94f97c463b2863', 'io.mockk:mockk-agent-common:1.8.6:mockk-agent-common-1.8.6.jar:cb7cb26fae5bfd3c89090858548990f311b27f673b9efa9d0c94f97c463b2863',
'io.mockk:mockk-agent-jvm:1.8.6:mockk-agent-jvm-1.8.6.jar:3f30b98d23ada8b5a44d75b43cd58fc03252fcb96939ff31e7ad659818af1e5d', 'io.mockk:mockk-agent-jvm:1.8.6:mockk-agent-jvm-1.8.6.jar:3f30b98d23ada8b5a44d75b43cd58fc03252fcb96939ff31e7ad659818af1e5d',
@@ -20,29 +20,28 @@ dependencyVerification {
'net.bytebuddy:byte-buddy-agent:1.8.8:byte-buddy-agent-1.8.8.jar:dc1a2dcefe72731fa89ae84e32231c74d545ccf8216c79865096e546f20c57e8', 'net.bytebuddy:byte-buddy-agent:1.8.8:byte-buddy-agent-1.8.8.jar:dc1a2dcefe72731fa89ae84e32231c74d545ccf8216c79865096e546f20c57e8',
'net.bytebuddy:byte-buddy:1.8.8:byte-buddy-1.8.8.jar:30aed1ae2ee5261b1d2f0e98ec3fcb40755c3f61b378089fb65d56098df1f16b', 'net.bytebuddy:byte-buddy:1.8.8:byte-buddy-1.8.8.jar:30aed1ae2ee5261b1d2f0e98ec3fcb40755c3f61b378089fb65d56098df1f16b',
'org.apiguardian:apiguardian-api:1.0.0:apiguardian-api-1.0.0.jar:1f58b77470d8d147a0538d515347dd322f49a83b9e884b8970051160464b65b3', 'org.apiguardian:apiguardian-api:1.0.0:apiguardian-api-1.0.0.jar:1f58b77470d8d147a0538d515347dd322f49a83b9e884b8970051160464b65b3',
'org.eclipse.jetty.websocket:websocket-api:9.4.9.v20180320:websocket-api-9.4.9.v20180320.jar:985b737f5c0928d48fc9890b261cbed096625350b9c0e321f44bde8a803c85ec', 'org.eclipse.jetty.websocket:websocket-api:9.4.11.v20180605:websocket-api-9.4.11.v20180605.jar:924edcf7fb17f2ff2e541afce7fd692305235e51b5a16f7223d7e8b4de77559d',
'org.eclipse.jetty.websocket:websocket-client:9.4.9.v20180320:websocket-client-9.4.9.v20180320.jar:2f5c6a64987ac27a21862a6349bd2b1d25545cba9aa68084e50ef77af7adcd7d', 'org.eclipse.jetty.websocket:websocket-client:9.4.11.v20180605:websocket-client-9.4.11.v20180605.jar:d3c812f80ac18d7031ffe2a324f2f83d8b260a99863be81b81668184ad5f2cca',
'org.eclipse.jetty.websocket:websocket-common:9.4.9.v20180320:websocket-common-9.4.9.v20180320.jar:26fc6bba6ad8e6522b27d5f397429c349264bcea076bd186ad885ef0cd0a73c8', 'org.eclipse.jetty.websocket:websocket-common:9.4.11.v20180605:websocket-common-9.4.11.v20180605.jar:f00731b8f9d2f2155bd87a2040cdef991fbcd24ff843ff4ba1ab1829bf62c04c',
'org.eclipse.jetty.websocket:websocket-server:9.4.9.v20180320:websocket-server-9.4.9.v20180320.jar:93ebcfa8e8af9876491d1524b4e8d273be8a7576e18b75ef699bad9564f76de2', 'org.eclipse.jetty.websocket:websocket-server:9.4.11.v20180605:websocket-server-9.4.11.v20180605.jar:0cfa90029d46618116f986cc6aea1c4f2e7408f3c97ad3eb2f92f74aff37279b',
'org.eclipse.jetty.websocket:websocket-servlet:9.4.9.v20180320:websocket-servlet-9.4.9.v20180320.jar:cac3f46db4917722b860e194907c36c251d2765ca1ce8323085c47cefafec52b', 'org.eclipse.jetty.websocket:websocket-servlet:9.4.11.v20180605:websocket-servlet-9.4.11.v20180605.jar:76f52b482ad174944e07f552cbfaaa2ccf498063e0a3837bb930eee8a06373aa',
'org.eclipse.jetty:jetty-client:9.4.9.v20180320:jetty-client-9.4.9.v20180320.jar:d6d8eca17806261a96137f64ad14c33feed26ba031c92180162961589141072d', 'org.eclipse.jetty:jetty-client:9.4.11.v20180605:jetty-client-9.4.11.v20180605.jar:b096ea6ee2607886323791930a470b2e04fb3327459b287ef99647226bd7a09c',
'org.eclipse.jetty:jetty-http:9.4.9.v20180320:jetty-http-9.4.9.v20180320.jar:823e76a9565f8a98c96542745f34560e2a6a9dfa6fbe320614061ad9b17b950b', 'org.eclipse.jetty:jetty-http:9.4.11.v20180605:jetty-http-9.4.11.v20180605.jar:963b75730aa92b0dfbe65fe8a2e413edc88aeb53e8686ba6b1617d7caeb14067',
'org.eclipse.jetty:jetty-io:9.4.9.v20180320:jetty-io-9.4.9.v20180320.jar:fffa35ca529d3267ad80d87f83ad4f6796b0981ae21d3ff621151bbe0a8f4155', 'org.eclipse.jetty:jetty-io:9.4.11.v20180605:jetty-io-9.4.11.v20180605.jar:75c82d6e542a3518e2517c4084c83d8216ec2d2458f8747b8b5c944355ebd732',
'org.eclipse.jetty:jetty-security:9.4.9.v20180320:jetty-security-9.4.9.v20180320.jar:5cbaeb9837aa331a8ee918724786655c6f60f8cc65ab84e03ff587bc212a2327', 'org.eclipse.jetty:jetty-security:9.4.11.v20180605:jetty-security-9.4.11.v20180605.jar:5a12b1c69264466004baff33b14fc1555007c86fb2fece2a420c480aa7f8ef56',
'org.eclipse.jetty:jetty-server:9.4.9.v20180320:jetty-server-9.4.9.v20180320.jar:b45869789b8f8081c1c75c059b4fd262d2fd440fa676c54bc753365fdd1f82d6', 'org.eclipse.jetty:jetty-server:9.4.11.v20180605:jetty-server-9.4.11.v20180605.jar:b74af5ac482b05c242ed231e00b7c08a0b6649f76f2e039a0885de0cf1376ef8',
'org.eclipse.jetty:jetty-servlet:9.4.9.v20180320:jetty-servlet-9.4.9.v20180320.jar:a96f8711d4f9d5d4c3fcafa046fb5caefec17eefcbfcd35b6c2e1d5a0549edfc', 'org.eclipse.jetty:jetty-servlet:9.4.11.v20180605:jetty-servlet-9.4.11.v20180605.jar:e24f145a6d95c7653ad2fe0c34cf8ce7311effb7eb8ed9399fae63d8af63eaf4',
'org.eclipse.jetty:jetty-util:9.4.9.v20180320:jetty-util-9.4.9.v20180320.jar:86ccb5e178e7001f26a12ec4bf56c522911424a0edf60424f15add8601355fc5', 'org.eclipse.jetty:jetty-util:9.4.11.v20180605:jetty-util-9.4.11.v20180605.jar:936e5ed74275c16164cc1eccaeae55900eb00edd9f1b1d3b83d70782dd25f505',
'org.eclipse.jetty:jetty-webapp:9.4.9.v20180320:jetty-webapp-9.4.9.v20180320.jar:7d6c6af12f10a47524e8eabc607226b038100680612ea569f92c030158bd5566', 'org.eclipse.jetty:jetty-webapp:9.4.11.v20180605:jetty-webapp-9.4.11.v20180605.jar:858f3f16cecb0891f07a4e8d82554201c513bf058c0f65969b366936155b6a36',
'org.eclipse.jetty:jetty-xml:9.4.9.v20180320:jetty-xml-9.4.9.v20180320.jar:2a0c8e64364cb8d0f483e5e050db6fbd26f0ad9e5098367f8af7928887fa5ece', 'org.eclipse.jetty:jetty-xml:9.4.11.v20180605:jetty-xml-9.4.11.v20180605.jar:1780bdaee2b1908e032fbc286bb856d730c4d0c9de39d5e14a1b9c48028c295e',
'org.jetbrains.kotlin:kotlin-compiler-embeddable:1.2.61:kotlin-compiler-embeddable-1.2.61.jar:f8165810c61f440a2de6003ed9857d28a1dfc990bacbecee1436610c8ebe565b', 'org.jetbrains.kotlin:kotlin-compiler-embeddable:1.2.61:kotlin-compiler-embeddable-1.2.61.jar:f8165810c61f440a2de6003ed9857d28a1dfc990bacbecee1436610c8ebe565b',
'org.jetbrains.kotlin:kotlin-reflect:1.2.41:kotlin-reflect-1.2.41.jar:1bab75771dfa2bb5949cd383ceaedf6f8d354fa0d677804fc5a39e320bab70d3', 'org.jetbrains.kotlin:kotlin-reflect:1.2.41:kotlin-reflect-1.2.41.jar:1bab75771dfa2bb5949cd383ceaedf6f8d354fa0d677804fc5a39e320bab70d3',
'org.jetbrains.kotlin:kotlin-reflect:1.2.61:kotlin-reflect-1.2.61.jar:a4f1ed542390f9bf967fb9aff2c232b90988f7ce138a4b7bcc70b754821a8943', 'org.jetbrains.kotlin:kotlin-reflect:1.2.61:kotlin-reflect-1.2.61.jar:a4f1ed542390f9bf967fb9aff2c232b90988f7ce138a4b7bcc70b754821a8943',
'org.jetbrains.kotlin:kotlin-script-runtime:1.2.61:kotlin-script-runtime-1.2.61.jar:793e4c54a8d59cf1f1cda68a7bc6be1ad54c41d771a08d308aa28c2cd304f1b1', 'org.jetbrains.kotlin:kotlin-script-runtime:1.2.61:kotlin-script-runtime-1.2.61.jar:793e4c54a8d59cf1f1cda68a7bc6be1ad54c41d771a08d308aa28c2cd304f1b1',
'org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.2.61:kotlin-scripting-compiler-embeddable-1.2.61.jar:99e0ee865f9c7c8ddcc0975185c69392182311067fe2a6faa72e942185631c1c', 'org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.2.61:kotlin-scripting-compiler-embeddable-1.2.61.jar:99e0ee865f9c7c8ddcc0975185c69392182311067fe2a6faa72e942185631c1c',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.61:kotlin-stdlib-common-1.2.61.jar:54a6fab7dae0cd7528208e95868fe1869b01b613c3018f2e53dbbad2604f6595', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.61:kotlin-stdlib-common-1.2.61.jar:54a6fab7dae0cd7528208e95868fe1869b01b613c3018f2e53dbbad2604f6595',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.41:kotlin-stdlib-jdk7-1.2.41.jar:169ee5879cba8444499243ceea5e6a2cb6ecea5424211cc819f0704501154b35', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61:kotlin-stdlib-jdk7-1.2.61.jar:f02ed7a640323b162c798a7834b35c10590880151e104eeb83acd84b364ef030',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.41:kotlin-stdlib-jdk8-1.2.41.jar:b306e0e6735841e31e320bf3260c71d60fc35057cfa87895f23251ee260a64a8', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.61:kotlin-stdlib-jdk8-1.2.61.jar:1fdeec7f74c2bae97a2205bb4aff0c6fe9d133bd619d069a0928156098d1b927',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.41:kotlin-stdlib-1.2.41.jar:f0595b9ed88ddc6fd66bddf68c56c6f2f6c4b17faa51e43e478acad32b05303e',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.61:kotlin-stdlib-1.2.61.jar:62eaf9cc6e746cef4593abe7cdb4dd48694ef5f817c852e0d9fbbd11fcfc564e', 'org.jetbrains.kotlin:kotlin-stdlib:1.2.61:kotlin-stdlib-1.2.61.jar:62eaf9cc6e746cef4593abe7cdb4dd48694ef5f817c852e0d9fbbd11fcfc564e',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.junit.jupiter:junit-jupiter-api:5.2.0:junit-jupiter-api-5.2.0.jar:47f7d71b35dc331210b9ab219bbb00d54332981aa12eb5effe817de17e1ae7b3', 'org.junit.jupiter:junit-jupiter-api:5.2.0:junit-jupiter-api-5.2.0.jar:47f7d71b35dc331210b9ab219bbb00d54332981aa12eb5effe817de17e1ae7b3',