briar-headless: Last round of review comments

This commit is contained in:
Torsten Grote
2018-10-09 12:19:21 -03:00
parent e3686186ee
commit b3615b4a77
11 changed files with 32 additions and 26 deletions

View File

@@ -41,7 +41,7 @@ You can test that things work as expected by running:
[] []
The answer is an empty JSON array, because you don't have any contacts. The answer is an empty JSON array, because you don't have any contacts.
Note you the HTTP request sets an `Authorization` header with the bearer token. Note that the HTTP request sets an `Authorization` header with the bearer token.
A missing or wrong token will result in a `401` response. A missing or wrong token will result in a `401` response.
## REST API ## REST API
@@ -55,6 +55,7 @@ Returns a JSON array of contacts:
```json ```json
{ {
"author": { "author": {
"formatVersion": 1,
"id": "y1wkIzAimAbYoCGgWxkWlr6vnq1F8t1QRA/UMPgI0E0=", "id": "y1wkIzAimAbYoCGgWxkWlr6vnq1F8t1QRA/UMPgI0E0=",
"name": "Test", "name": "Test",
"publicKey": "BDu6h1S02bF4W6rgoZfZ6BMjTj/9S9hNN7EQoV05qUo=" "publicKey": "BDu6h1S02bF4W6rgoZfZ6BMjTj/9S9hNN7EQoV05qUo="
@@ -80,7 +81,6 @@ It returns a JSON array of private messages:
```json ```json
{ {
"body": "test",
"contactId": 1, "contactId": 1,
"groupId": "oRRvCri85UE2XGcSloAKt/u8JDcMkmDc26SOMouxr4U=", "groupId": "oRRvCri85UE2XGcSloAKt/u8JDcMkmDc26SOMouxr4U=",
"id": "ZGDrlpCxO9v7doO4Bmijh95QqQDykaS4Oji/mZVMIJ8=", "id": "ZGDrlpCxO9v7doO4Bmijh95QqQDykaS4Oji/mZVMIJ8=",
@@ -88,6 +88,7 @@ It returns a JSON array of private messages:
"read": true, "read": true,
"seen": true, "seen": true,
"sent": true, "sent": true,
"text": "test",
"timestamp": 1537376633850, "timestamp": 1537376633850,
"type": "PrivateMessage" "type": "PrivateMessage"
} }
@@ -95,7 +96,7 @@ It returns a JSON array of private messages:
If `local` is `true`, the message was sent by the Briar peer instead of its remote contact. If `local` is `true`, the message was sent by the Briar peer instead of its remote contact.
Attention: There can messages of other `type`s where the message `body` is `null`. Attention: There can messages of other `type`s where the message `text` is `null`.
### Writing a private message ### Writing a private message
@@ -118,16 +119,17 @@ Returns a JSON array of blog posts:
```json ```json
{ {
"author": { "author": {
"formatVersion": 1,
"id": "VNKXkaERPpXmZuFbHHwYT6Qc148D+KNNxQ4hwtx7Kq4=", "id": "VNKXkaERPpXmZuFbHHwYT6Qc148D+KNNxQ4hwtx7Kq4=",
"name": "Test", "name": "Test",
"publicKey": "NbwpQWjS3gHMjjDQIASIy/j+bU6NRZnSRT8X8FKDoN4=" "publicKey": "NbwpQWjS3gHMjjDQIASIy/j+bU6NRZnSRT8X8FKDoN4="
}, },
"authorStatus": "ourselves", "authorStatus": "ourselves",
"body": "Test Post Content",
"id": "X1jmHaYfrX47kT5OEd0OD+p/bptyR92IvuOBYSgxETM=", "id": "X1jmHaYfrX47kT5OEd0OD+p/bptyR92IvuOBYSgxETM=",
"parentId": null, "parentId": null,
"read": true, "read": true,
"rssFeed": false, "rssFeed": false,
"text": "Test Post Content",
"timestamp": 1535397886749, "timestamp": 1535397886749,
"timestampReceived": 1535397886749, "timestampReceived": 1535397886749,
"type": "post" "type": "post"
@@ -152,8 +154,8 @@ The Briar peer uses a websocket to notify a connected API client about new event
`WS /v1/ws` `WS /v1/ws`
The authentication token needs to be provided with basic auth as the username The websocket request must use basic auth,
while the password can be left empty. with the authentication token as the username and a blank password.
You can test connecting to the websocket with curl: You can test connecting to the websocket with curl:
@@ -175,7 +177,6 @@ it will send a JSON object to connected websocket clients:
```json ```json
{ {
"data": { "data": {
"body": "Test Message",
"contactId": 1, "contactId": 1,
"groupId": "oRRvCri85UE2XGcSloAKt/u8JDcMkmDc26SOMouxr4U=", "groupId": "oRRvCri85UE2XGcSloAKt/u8JDcMkmDc26SOMouxr4U=",
"id": "JBc+ogQIok/yr+7XtxN2iQgNfzw635mHikNaP5QOEVs=", "id": "JBc+ogQIok/yr+7XtxN2iQgNfzw635mHikNaP5QOEVs=",
@@ -183,6 +184,7 @@ it will send a JSON object to connected websocket clients:
"read": false, "read": false,
"seen": false, "seen": false,
"sent": false, "sent": false,
"text": "Test Message",
"timestamp": 1537389146088, "timestamp": 1537389146088,
"type": "PrivateMessage" "type": "PrivateMessage"
}, },

View File

@@ -11,4 +11,3 @@ fun Author.output() = JsonDict(
) )
fun Author.Status.output() = name.toLowerCase() fun Author.Status.output() = name.toLowerCase()

View File

@@ -27,7 +27,7 @@ private val DEFAULT_DATA_DIR = getProperty("user.home") + separator + ".briar"
private class Main : CliktCommand( private class Main : CliktCommand(
name = "briar-headless", name = "briar-headless",
help = "A Briar client without GUI that exposes a REST and Websocket API" help = "A Briar peer without GUI that exposes a REST and Websocket API"
) { ) {
private val debug by option("--debug", "-d", help = "Enable printing of debug messages").flag( private val debug by option("--debug", "-d", help = "Enable printing of debug messages").flag(
default = false default = false

View File

@@ -6,7 +6,7 @@ import org.briarproject.briar.api.blog.MessageType
import org.briarproject.briar.headless.json.JsonDict import org.briarproject.briar.headless.json.JsonDict
internal fun BlogPostHeader.output(body: String) = JsonDict( internal fun BlogPostHeader.output(body: String) = JsonDict(
"body" to body, "text" to body,
"author" to author.output(), "author" to author.output(),
"authorStatus" to authorStatus.output(), "authorStatus" to authorStatus.output(),
"type" to type.output(), "type" to type.output(),

View File

@@ -21,7 +21,7 @@ constructor(private val forumManager: ForumManager) : ForumController {
} }
override fun create(ctx: Context): Context { override fun create(ctx: Context): Context {
val name = ctx.getFromJson("text") val name = ctx.getFromJson("name")
if (StringUtils.utf8IsTooLong(name, MAX_FORUM_NAME_LENGTH)) if (StringUtils.utf8IsTooLong(name, MAX_FORUM_NAME_LENGTH))
throw BadRequestResponse("Forum name is too long") throw BadRequestResponse("Forum name is too long")
return ctx.json(forumManager.addForum(name).output()) return ctx.json(forumManager.addForum(name).output())

View File

@@ -19,19 +19,22 @@ internal fun PrivateMessageHeader.output(contactId: ContactId) = JsonDict(
internal fun PrivateMessageHeader.output(contactId: ContactId, body: String?): JsonDict { internal fun PrivateMessageHeader.output(contactId: ContactId, body: String?): JsonDict {
val dict = output(contactId) val dict = output(contactId)
dict["body"] = body dict["text"] = body
return dict return dict
} }
/**
* Use only for outgoing messages that were just sent
*/
internal fun PrivateMessage.output(contactId: ContactId, body: String) = JsonDict( internal fun PrivateMessage.output(contactId: ContactId, body: String) = JsonDict(
"type" to "PrivateMessage", "type" to "PrivateMessage",
"contactId" to contactId.int, "contactId" to contactId.int,
"timestamp" to message.timestamp, "timestamp" to message.timestamp,
"read" to true, "read" to true,
"seen" to true, "seen" to false,
"sent" to true, "sent" to false,
"local" to true, "local" to true,
"id" to message.id.bytes, "id" to message.id.bytes,
"groupId" to message.groupId.bytes, "groupId" to message.groupId.bytes,
"body" to body "text" to body
) )

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.system.Clock
import org.briarproject.bramble.test.TestUtils.* import org.briarproject.bramble.test.TestUtils.*
import org.briarproject.bramble.util.StringUtils.getRandomString import org.briarproject.bramble.util.StringUtils.getRandomString
import org.skyscreamer.jsonassert.JSONAssert.assertEquals import org.skyscreamer.jsonassert.JSONAssert.assertEquals
import org.skyscreamer.jsonassert.JSONCompareMode.STRICT
import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse import javax.servlet.http.HttpServletResponse
@@ -38,7 +39,7 @@ abstract class ControllerTest {
protected val timestamp = 42L protected val timestamp = 42L
protected fun assertJsonEquals(json: String, obj: Any) { protected fun assertJsonEquals(json: String, obj: Any) {
assertEquals(json, outputCtx.json(obj).resultString(), false) assertEquals(json, outputCtx.json(obj).resultString(), STRICT)
} }
} }

View File

@@ -102,7 +102,7 @@ internal class BlogControllerTest : ControllerTest() {
fun testOutputBlogPost() { fun testOutputBlogPost() {
val json = """ val json = """
{ {
"body": "$body", "text": "$body",
"author": ${toJson(author.output())}, "author": ${toJson(author.output())},
"authorStatus": "ourselves", "authorStatus": "ourselves",
"type": "post", "type": "post",

View File

@@ -41,6 +41,7 @@ internal class ContactControllerTest : ControllerTest() {
fun testOutputAuthor() { fun testOutputAuthor() {
val json = """ val json = """
{ {
"formatVersion": 1,
"id": ${toJson(author.id.bytes)}, "id": ${toJson(author.id.bytes)},
"name": "${author.name}", "name": "${author.name}",
"publicKey": ${toJson(author.publicKey)} "publicKey": ${toJson(author.publicKey)}

View File

@@ -30,7 +30,7 @@ internal class ForumControllerTest : ControllerTest() {
@Test @Test
fun create() { fun create() {
every { ctx.body() } returns """{"text": "${forum.name}"}""" every { ctx.body() } returns """{"name": "${forum.name}"}"""
every { forumManager.addForum(forum.name) } returns forum every { forumManager.addForum(forum.name) } returns forum
every { ctx.json(forum.output()) } returns ctx every { ctx.json(forum.output()) } returns ctx
@@ -46,14 +46,14 @@ internal class ForumControllerTest : ControllerTest() {
@Test @Test
fun createEmptyName() { fun createEmptyName() {
every { ctx.body() } returns """{"text": ""}""" every { ctx.body() } returns """{"name": ""}"""
assertThrows(BadRequestResponse::class.java) { controller.create(ctx) } assertThrows(BadRequestResponse::class.java) { controller.create(ctx) }
} }
@Test @Test
fun createNullName() { fun createNullName() {
every { ctx.body() } returns """{"text": null}""" every { ctx.body() } returns """{"name": null}"""
assertThrows(BadRequestResponse::class.java) { controller.create(ctx) } assertThrows(BadRequestResponse::class.java) { controller.create(ctx) }
} }
@@ -67,7 +67,7 @@ internal class ForumControllerTest : ControllerTest() {
@Test @Test
fun createTooLongName() { fun createTooLongName() {
every { ctx.body() } returns """{"text": "${getRandomString(MAX_FORUM_NAME_LENGTH + 1)}"}""" every { ctx.body() } returns """{"name": "${getRandomString(MAX_FORUM_NAME_LENGTH + 1)}"}"""
assertThrows(BadRequestResponse::class.java) { controller.create(ctx) } assertThrows(BadRequestResponse::class.java) { controller.create(ctx) }
} }

View File

@@ -161,7 +161,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
fun testOutputPrivateMessageHeader() { fun testOutputPrivateMessageHeader() {
val json = """ val json = """
{ {
"body": "$body", "text": "$body",
"type": "PrivateMessage", "type": "PrivateMessage",
"timestamp": $timestamp, "timestamp": $timestamp,
"groupId": ${toJson(header.groupId.bytes)}, "groupId": ${toJson(header.groupId.bytes)},
@@ -180,15 +180,15 @@ internal class MessagingControllerImplTest : ControllerTest() {
fun testOutputPrivateMessage() { fun testOutputPrivateMessage() {
val json = """ val json = """
{ {
"body": "$body", "text": "$body",
"type": "PrivateMessage", "type": "PrivateMessage",
"timestamp": ${message.timestamp}, "timestamp": ${message.timestamp},
"groupId": ${toJson(message.groupId.bytes)}, "groupId": ${toJson(message.groupId.bytes)},
"contactId": ${contact.id.int}, "contactId": ${contact.id.int},
"local": true, "local": true,
"seen": true, "seen": false,
"read": true, "read": true,
"sent": true, "sent": false,
"id": ${toJson(message.id.bytes)} "id": ${toJson(message.id.bytes)}
} }
""" """
@@ -203,7 +203,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
) )
val json = """ val json = """
{ {
"body": null, "text": null,
"type": "IntroductionRequest", "type": "IntroductionRequest",
"timestamp": $timestamp, "timestamp": $timestamp,
"groupId": ${toJson(request.groupId.bytes)}, "groupId": ${toJson(request.groupId.bytes)},