Skip to content
Snippets Groups Projects
Commit d2b67578 authored by akwizgran's avatar akwizgran
Browse files

Return 404 for missing or unauthorised folders.

parent 38e3567a
No related branches found
No related tags found
1 merge request!111Return 404 for missing or unauthorised folders
Pipeline #11616 passed
......@@ -153,6 +153,9 @@ POST /files/$folderId
The mailbox checks if the provided auth token is allowed to upload to $folderId
which is either an `inboxId` or an `outboxId` of a contact.
If the folder does not exist or the auth token is not allowed to upload to it, `404 Not Found`
is returned.
The file content is a raw byte stream in the request body.
The mailbox chooses a random string for the file ID (32 hex encoded bytes).
Returns `200 OK` if upload was successful (no `201` as the uploader does not need to know the `$fileName`).
......@@ -168,6 +171,9 @@ GET /files/$folderId
The mailbox checks if provided auth token is allowed to download from $folderId
which is either an `inboxId` or an `outboxId` of a contact.
If the folder does not exist or the auth token is not allowed to download from it, `404 Not Found`
is returned.
Returns `200 OK` with the list of files in JSON (example):
```json
......@@ -193,6 +199,9 @@ GET /files/$folderId/$fileName
Checks if the provided auth token is allowed to download from `$folderId`
which is either an `inboxId` or an `outboxId` of a contact.
If the folder does not exist or the auth token is not allowed to download from it, `404 Not Found`
is returned.
Returns `200 OK` if successful with the files' raw bytes in the response body.
### Delete a file (owner and contacts)
......@@ -206,6 +215,9 @@ DELETE /files/$folderId/$fileName
Checks if provided auth token is allowed to download from $folderId
which is either an `inboxId` or an `outboxId` of a contact.
If the folder does not exist or the auth token is not allowed to download from it, `404 Not Found`
is returned.
Returns `200 OK` if deletion was successful.
### List folders with files available for download (owner only)
......@@ -218,7 +230,7 @@ GET /folders
Checks if provided auth token is belonging to the owner.
Returns `200 OK` with the list of folders with files in JSON (example):
Returns `200 OK` with the list of folders that have files available to download, in JSON (example):
```json
{
......
......@@ -20,6 +20,7 @@
package org.briarproject.mailbox.core.server
import io.ktor.server.auth.Principal
import io.ktor.server.plugins.NotFoundException
import org.briarproject.mailbox.core.contacts.Contact
import org.briarproject.mailbox.core.db.Database
import org.briarproject.mailbox.core.server.MailboxPrincipal.ContactPrincipal
......@@ -61,24 +62,26 @@ class AuthManager @Inject constructor(
}
/**
* @throws [AuthException] when given [principal] is NOT allowed
* @throws [AuthException] when the given principal is null
* @throws [NotFoundException] when the given [principal] is NOT allowed
* to download or delete from the given [folderId] which is assumed to be validated already.
*/
@Throws(AuthException::class)
@Throws(NotFoundException::class)
fun assertCanDownloadFromFolder(principal: MailboxPrincipal?, folderId: String) {
if (principal == null) throw AuthException()
if (principal is OwnerPrincipal) {
val contacts = db.read { txn -> db.getContacts(txn) }
val noOutboxFound = contacts.none { c -> folderId == c.outboxId }
if (noOutboxFound) throw AuthException()
if (noOutboxFound) throw NotFoundException()
} else if (principal is ContactPrincipal) {
if (folderId != principal.contact.inboxId) throw AuthException()
if (folderId != principal.contact.inboxId) throw NotFoundException()
}
}
/**
* @throws [AuthException] when given [principal] is NOT allowed
* @throws [AuthException] when the given principal is null
* @throws [NotFoundException] when the given [principal] is NOT allowed
* to post to the given [folderId] which is assumed to be validated already.
*/
@Throws(AuthException::class)
......@@ -88,9 +91,9 @@ class AuthManager @Inject constructor(
if (principal is OwnerPrincipal) {
val contacts = db.read { txn -> db.getContacts(txn) }
val noInboxFound = contacts.none { c -> folderId == c.inboxId }
if (noInboxFound) throw AuthException()
if (noInboxFound) throw NotFoundException()
} else if (principal is ContactPrincipal) {
if (folderId != principal.contact.outboxId) throw AuthException()
if (folderId != principal.contact.outboxId) throw NotFoundException()
}
}
......
......@@ -50,7 +50,7 @@ class FileManagerIntegrationTest : IntegrationTest() {
authenticateWithToken(ownerToken)
setBody(bytes)
}
assertEquals(HttpStatusCode.Unauthorized, response.status)
assertEquals(HttpStatusCode.NotFound, response.status)
}
@Test
......@@ -165,12 +165,12 @@ class FileManagerIntegrationTest : IntegrationTest() {
val response1: HttpResponse = httpClient.get("$baseUrl/files/${contact1.inboxId}") {
authenticateWithToken(ownerToken)
}
assertEquals(HttpStatusCode.Unauthorized, response1.status)
assertEquals(HttpStatusCode.NotFound, response1.status)
val response2: HttpResponse = httpClient.get("$baseUrl/files/${contact1.inboxId}") {
authenticateWithToken(contact2.token)
}
assertEquals(HttpStatusCode.Unauthorized, response2.status)
assertEquals(HttpStatusCode.NotFound, response2.status)
}
@Test
......@@ -209,7 +209,7 @@ class FileManagerIntegrationTest : IntegrationTest() {
httpClient.get("$baseUrl/files/${contact1.inboxId}/${getNewRandomId()}") {
authenticateWithToken(ownerToken)
}
assertEquals(HttpStatusCode.Unauthorized, response.status)
assertEquals(HttpStatusCode.NotFound, response.status)
}
@Test
......@@ -265,7 +265,7 @@ class FileManagerIntegrationTest : IntegrationTest() {
httpClient.delete("$baseUrl/files/${contact1.inboxId}/${getNewRandomId()}") {
authenticateWithToken(ownerToken)
}
assertEquals(HttpStatusCode.Unauthorized, response.status)
assertEquals(HttpStatusCode.NotFound, response.status)
}
@Test
......
package org.briarproject.mailbox.core.server
import io.ktor.server.plugins.NotFoundException
import io.mockk.Runs
import io.mockk.every
import io.mockk.just
......@@ -97,17 +98,17 @@ class AuthManagerTest {
every { db.getContacts(txn) } returns emptyList()
}
assertThrows<AuthException> {
assertThrows<NotFoundException> {
authManager.assertCanDownloadFromFolder(OwnerPrincipal, id)
}
}
@Test
fun `throws if contact wants to download from folder that is not their inbox`() {
assertThrows<AuthException> {
assertThrows<NotFoundException> {
authManager.assertCanDownloadFromFolder(contactPrincipal, id)
}
assertThrows<AuthException> {
assertThrows<NotFoundException> {
authManager.assertCanDownloadFromFolder(contactPrincipal, contact.outboxId)
}
}
......@@ -139,17 +140,17 @@ class AuthManagerTest {
every { db.getContacts(txn) } returns emptyList()
}
assertThrows<AuthException> {
assertThrows<NotFoundException> {
authManager.assertCanPostToFolder(OwnerPrincipal, id)
}
}
@Test
fun `throws if contact wants to post to folder that is not their outbox`() {
assertThrows<AuthException> {
assertThrows<NotFoundException> {
authManager.assertCanPostToFolder(contactPrincipal, id)
}
assertThrows<AuthException> {
assertThrows<NotFoundException> {
authManager.assertCanPostToFolder(contactPrincipal, contact.inboxId)
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment