From 8cd5b93b4728feecd1b9947543dc15251a4e9d86 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 12 Jan 2022 08:15:40 -0600 Subject: [PATCH] server: Make registration implicit --- .../uhabits/core/sync/AbstractSyncServer.kt | 9 ---- .../uhabits/server/app/RegistrationModule.kt | 39 -------------- .../uhabits/server/app/StorageModule.kt | 2 - .../uhabits/server/app/SyncApplication.kt | 3 +- .../server/sync/RepositorySyncServer.kt | 36 ++----------- .../server/app/RegistrationModuleTest.kt | 51 ------------------- .../uhabits/server/app/StorageModuleTest.kt | 10 ---- .../server/sync/RepositorySyncServerTest.kt | 9 +--- 8 files changed, 7 insertions(+), 152 deletions(-) delete mode 100644 uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/RegistrationModule.kt delete mode 100644 uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/RegistrationModuleTest.kt diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/sync/AbstractSyncServer.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/sync/AbstractSyncServer.kt index 713c81a5e..7d4ff704c 100644 --- a/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/sync/AbstractSyncServer.kt +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/uhabits/core/sync/AbstractSyncServer.kt @@ -20,15 +20,6 @@ package org.isoron.uhabits.core.sync interface AbstractSyncServer { - /** - * Generates and returns a new sync key, which can be used to store and retrive - * data. - * - * @throws ServiceUnavailable If key cannot be generated at this time, for example, - * due to insufficient server resources, temporary server maintenance or network problems. - */ - suspend fun register(): String - /** * Replaces data for a given sync key. * diff --git a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/RegistrationModule.kt b/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/RegistrationModule.kt deleted file mode 100644 index ae7b196f9..000000000 --- a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/RegistrationModule.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2016-2021 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -package org.isoron.uhabits.server.app - -import io.ktor.application.call -import io.ktor.http.HttpStatusCode -import io.ktor.response.respond -import io.ktor.routing.Routing -import io.ktor.routing.post -import org.isoron.uhabits.core.sync.RegisterReponse -import org.isoron.uhabits.core.sync.ServiceUnavailable - -fun Routing.registration(app: SyncApplication) { - post("/register") { - try { - val key = app.server.register() - call.respond(HttpStatusCode.OK, RegisterReponse(key)) - } catch (e: ServiceUnavailable) { - call.respond(HttpStatusCode.ServiceUnavailable) - } - } -} diff --git a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/StorageModule.kt b/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/StorageModule.kt index cd337f15d..116d1958c 100644 --- a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/StorageModule.kt +++ b/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/StorageModule.kt @@ -49,8 +49,6 @@ fun Routing.storage(app: SyncApplication) { try { app.server.put(key, data) call.respond(HttpStatusCode.OK) - } catch (e: KeyNotFoundException) { - call.respond(HttpStatusCode.NotFound) } catch (e: EditConflictException) { call.respond(HttpStatusCode.Conflict) } diff --git a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/SyncApplication.kt b/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/SyncApplication.kt index dd7cf1856..1ab03e36e 100644 --- a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/SyncApplication.kt +++ b/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/app/SyncApplication.kt @@ -26,8 +26,8 @@ import io.ktor.features.ContentNegotiation import io.ktor.features.DefaultHeaders import io.ktor.jackson.jackson import io.ktor.routing.routing -import org.isoron.uhabits.server.sync.Repository import org.isoron.uhabits.core.sync.AbstractSyncServer +import org.isoron.uhabits.server.sync.Repository import org.isoron.uhabits.server.sync.RepositorySyncServer import java.nio.file.Path import java.nio.file.Paths @@ -48,7 +48,6 @@ class SyncApplication( jackson { } } routing { - registration(this@SyncApplication) storage(this@SyncApplication) metrics(this@SyncApplication) } diff --git a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServer.kt b/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServer.kt index 2372725c8..9bd17a3c9 100644 --- a/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServer.kt +++ b/uhabits-server/src/main/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServer.kt @@ -24,8 +24,6 @@ import org.isoron.uhabits.core.sync.AbstractSyncServer import org.isoron.uhabits.core.sync.EditConflictException import org.isoron.uhabits.core.sync.KeyNotFoundException import org.isoron.uhabits.core.sync.SyncData -import java.util.Random -import kotlin.streams.asSequence /** * An AbstractSyncServer that stores all data in a [Repository]. @@ -40,21 +38,13 @@ class RepositorySyncServer( .labelNames("method") .register() - override suspend fun register(): String { - requestsCounter.labels("register").inc() - val key = generateKey() - repo.put(key, SyncData(0, "")) - return key - } - override suspend fun put(key: String, newData: SyncData) { requestsCounter.labels("put").inc() - if (!repo.contains(key)) { - throw KeyNotFoundException() - } - val prevData = repo.get(key) - if (newData.version != prevData.version + 1) { - throw EditConflictException() + if (repo.contains(key)) { + val prevData = repo.get(key) + if (newData.version != prevData.version + 1) { + throw EditConflictException() + } } repo.put(key, newData) } @@ -74,20 +64,4 @@ class RepositorySyncServer( } return repo.get(key).version } - - private fun generateKey(): String { - while (true) { - val key = randomString(64) - if (!repo.contains(key)) - return key - } - } - - private fun randomString(length: Long): String { - val chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - return Random().ints(length, 0, chars.length) - .asSequence() - .map(chars::get) - .joinToString("") - } } diff --git a/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/RegistrationModuleTest.kt b/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/RegistrationModuleTest.kt deleted file mode 100644 index 4f2ab516f..000000000 --- a/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/RegistrationModuleTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2016-2021 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -package org.isoron.uhabits.server.app - -import com.nhaarman.mockitokotlin2.whenever -import io.ktor.http.HttpMethod -import io.ktor.http.HttpStatusCode -import io.ktor.server.testing.handleRequest -import io.ktor.server.testing.withTestApplication -import kotlinx.coroutines.runBlocking -import org.isoron.uhabits.core.sync.ServiceUnavailable -import org.junit.Test -import kotlin.test.assertEquals - -class RegistrationModuleTest : BaseApplicationTest() { - @Test - fun `when register succeeds should return generated key`(): Unit = runBlocking { - whenever(server.register()).thenReturn("ABCDEF") - withTestApplication(app()) { - val call = handleRequest(HttpMethod.Post, "/register") - assertEquals(HttpStatusCode.OK, call.response.status()) - assertEquals("{\"key\":\"ABCDEF\"}", call.response.content) - } - } - - @Test - fun `when registration is unavailable should return 503`(): Unit = runBlocking { - whenever(server.register()).thenThrow(ServiceUnavailable()) - withTestApplication(app()) { - val call = handleRequest(HttpMethod.Post, "/register") - assertEquals(HttpStatusCode.ServiceUnavailable, call.response.status()) - } - } -} diff --git a/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/StorageModuleTest.kt b/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/StorageModuleTest.kt index 71576fb86..8e6300df2 100644 --- a/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/StorageModuleTest.kt +++ b/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/app/StorageModuleTest.kt @@ -87,16 +87,6 @@ class StorageModuleTest : BaseApplicationTest() { } } - @Test - fun `when put with invalid key should return 404`(): Unit = runBlocking { - whenever(server.put("k1", data1)).thenThrow(KeyNotFoundException()) - withTestApplication(app()) { - handlePut("/db/k1", data1).apply { - assertEquals(HttpStatusCode.NotFound, response.status()) - } - } - } - @Test fun `when put with invalid version should return 409 and current data`(): Unit = runBlocking { whenever(server.put("k1", data1)).thenThrow(EditConflictException()) diff --git a/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServerTest.kt b/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServerTest.kt index a6854d677..6e245fe25 100644 --- a/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServerTest.kt +++ b/uhabits-server/src/test/kotlin/org/isoron/uhabits/server/sync/RepositorySyncServerTest.kt @@ -32,13 +32,10 @@ class RepositorySyncServerTest { private val tempdir = Files.createTempDirectory("db") private val server = RepositorySyncServer(Repository(tempdir)) - private val key = runBlocking { server.register() } + private val key = "abcdefgh" @Test fun testUsage(): Unit = runBlocking { - val data0 = SyncData(0, "") - assertEquals(server.getData(key), data0) - val data1 = SyncData(1, "Hello world") server.put(key, data1) assertEquals(server.getData(key), data1) @@ -54,9 +51,5 @@ class RepositorySyncServerTest { assertFailsWith { server.getData("INVALID") } - - assertFailsWith { - server.put("INVALID", data0) - } } }