mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 14:49:53 +01:00
briar-headless: Last round of review comments
This commit is contained in:
@@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,4 +11,3 @@ fun Author.output() = JsonDict(
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun Author.Status.output() = name.toLowerCase()
|
fun Author.Status.output() = name.toLowerCase()
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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)}
|
||||||
|
|||||||
@@ -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) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)},
|
||||||
|
|||||||
Reference in New Issue
Block a user