From 69ede50a5936bfb9fc00f3cad103da807e409c4b Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Sat, 25 Apr 2020 18:17:34 +0200 Subject: [PATCH] Migration done for the backend --- api/resources/db/migration/V8__Notes_uuid.sql | 13 ++-- api/resources/logback.xml | 2 +- .../extensions/ApplicationCallExtensions.kt | 7 +- api/src/routing/NotesController.kt | 13 +--- api/src/routing/TitleController.kt | 2 +- api/src/services/NotesService.kt | 65 ++++++++++++++----- 6 files changed, 65 insertions(+), 37 deletions(-) diff --git a/api/resources/db/migration/V8__Notes_uuid.sql b/api/resources/db/migration/V8__Notes_uuid.sql index ef36e39..f944b38 100644 --- a/api/resources/db/migration/V8__Notes_uuid.sql +++ b/api/resources/db/migration/V8__Notes_uuid.sql @@ -5,9 +5,9 @@ drop table if exists Notes; CREATE TABLE `Notes` ( - `uuid` binary(16) PRIMARY KEY, - `title` varchar(50) NOT NULL, - `user_id` int NOT NULL, + `uuid` binary(16) PRIMARY KEY, + `title` varchar(50) NOT NULL, + `user_id` int NOT NULL, `updated_at` datetime ); @@ -27,9 +27,10 @@ ALTER TABLE `Tags` CREATE TABLE `Chapters` ( `id` int PRIMARY KEY AUTO_INCREMENT, - `number` int NOT NULL, - `content` text NOT NULL, - `note_uuid` binary(16) NOT NULL + `number` int NOT NULL, + `title` varchar(50) NOT NULL, + `content` text NOT NULL, + `note_uuid` binary(16) NOT NULL ); ALTER TABLE `Chapters` diff --git a/api/resources/logback.xml b/api/resources/logback.xml index e573f7d..c19e387 100644 --- a/api/resources/logback.xml +++ b/api/resources/logback.xml @@ -4,7 +4,7 @@ %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - + diff --git a/api/src/extensions/ApplicationCallExtensions.kt b/api/src/extensions/ApplicationCallExtensions.kt index a09a900..a8a3f3b 100644 --- a/api/src/extensions/ApplicationCallExtensions.kt +++ b/api/src/extensions/ApplicationCallExtensions.kt @@ -1,7 +1,8 @@ package be.vandewalleh.extensions import be.vandewalleh.kodein -import be.vandewalleh.services.FullNoteDTOPatch +import be.vandewalleh.services.FullNoteCreateDTO +import be.vandewalleh.services.FullNotePatchDTO import be.vandewalleh.services.UserService import io.ktor.application.* import io.ktor.auth.* @@ -26,6 +27,6 @@ fun ApplicationCall.userId(): Int { class NoteCreate(val title: String, val tags: List) -suspend fun ApplicationCall.receiveNoteCreate(): NoteCreate = receive() +suspend fun ApplicationCall.receiveNoteCreate(): FullNoteCreateDTO = receive() -suspend fun ApplicationCall.receiveNotePatch() : FullNoteDTOPatch = receive() \ No newline at end of file +suspend fun ApplicationCall.receiveNotePatch() : FullNotePatchDTO = receive() \ No newline at end of file diff --git a/api/src/routing/NotesController.kt b/api/src/routing/NotesController.kt index e5fc693..00ec6a5 100644 --- a/api/src/routing/NotesController.kt +++ b/api/src/routing/NotesController.kt @@ -1,8 +1,6 @@ package be.vandewalleh.routing -import be.vandewalleh.extensions.noteTitle import be.vandewalleh.extensions.receiveNoteCreate -import be.vandewalleh.extensions.respondStatus import be.vandewalleh.extensions.userId import be.vandewalleh.services.NotesService import io.ktor.application.* @@ -25,16 +23,9 @@ fun Routing.notes(kodein: Kodein) { post("/notes") { val userId = call.userId() - val noteUuid = call.parameters.noteTitle() val note = call.receiveNoteCreate() - val exists = notesService.noteExistsWithTitle(userId, note.title) - - if (exists) { - return@post call.respondStatus(HttpStatusCode.Conflict) - } - - notesService.createNote(userId, note.title, note.tags) - call.respondStatus(HttpStatusCode.Created) + val uuid = notesService.createNote(userId, note) + call.respond(HttpStatusCode.Created, mapOf("uuid" to uuid)) } } } diff --git a/api/src/routing/TitleController.kt b/api/src/routing/TitleController.kt index fda2058..af8e476 100644 --- a/api/src/routing/TitleController.kt +++ b/api/src/routing/TitleController.kt @@ -23,7 +23,7 @@ fun Routing.title(kodein: Kodein) { val noteUuid = call.parameters.noteUuid() val exists = notesService.noteExists(userId, noteUuid) - if (exists) return@get call.respondStatus(HttpStatusCode.NotFound) + if (!exists) return@get call.respondStatus(HttpStatusCode.NotFound) val response = notesService.getNote(noteUuid) call.respond(response) diff --git a/api/src/services/NotesService.kt b/api/src/services/NotesService.kt index 9feeda5..38f6d6e 100644 --- a/api/src/services/NotesService.kt +++ b/api/src/services/NotesService.kt @@ -29,7 +29,7 @@ class NotesService(override val kodein: Kodein) : KodeinAware { .sortedByDescending { it.updatedAt } .toList() - if(notes.isEmpty()) return emptyList() + if (notes.isEmpty()) return emptyList() val tags = db.sequenceOf(Tags) .filterColumns { listOf(it.noteUuid, it.name) } @@ -46,37 +46,54 @@ class NotesService(override val kodein: Kodein) : KodeinAware { } } - fun noteExistsWithTitle(userId: Int, title: String): Boolean { - TODO() - } - fun noteExists(userId: Int, uuid: UUID): Boolean { - TODO() + return db.from(Notes) + .select(Notes.uuid) + .where { Notes.userId eq userId } + .where { Notes.uuid eq uuid } + .limit(0, 1) + .toList().size == 1 } - fun createNote(userId: Int, title: String, tags: List) { + fun createNote(userId: Int, note: FullNoteCreateDTO): UUID { + val uuid = UUID.randomUUID() db.useTransaction { - val uuid = UUID.randomUUID() db.insert(Notes) { it.uuid to uuid - it.title to title + it.title to note.title it.userId to userId it.updatedAt to LocalDateTime.now() } db.batchInsert(Tags) { - tags.forEach { tagName -> + note.tags.forEach { tagName -> item { it.noteUuid to uuid it.name to tagName } } } + + db.batchInsert(Chapters) { + note.chapters.forEachIndexed { index, chapter -> + item { + it.noteUuid to uuid + it.title to chapter.title + it.number to index + it.content to chapter.content + } + } + } + } + return uuid } fun getNote(noteUuid: UUID): FullNoteDTO { - TODO() + val note = db.sequenceOf(Notes) + .filterColumns { listOf(it.title, it.updatedAt) } + .find { it.uuid eq noteUuid } ?: error("Note not found") + val tags = db.from(Tags) .select(Tags.name) .where { Tags.noteUuid eq noteUuid } @@ -90,10 +107,18 @@ class NotesService(override val kodein: Kodein) : KodeinAware { .map { ChapterDTO(it[Chapters.title]!!, it[Chapters.content]!!) } .toList() + val updatedAtFormatted = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(note.updatedAt) + return FullNoteDTO( + uuid = noteUuid, + title = note.title, + updatedAt = updatedAtFormatted, + tags = tags, + chapters = chapters + ) } - fun updateNote(patch: FullNoteDTOPatch) { - if(patch.uuid == null) return + fun updateNote(patch: FullNotePatchDTO) { + if (patch.uuid == null) return db.useTransaction { if (patch.title != null) { db.update(Notes) { @@ -134,7 +159,11 @@ class NotesService(override val kodein: Kodein) : KodeinAware { .map { it[Tags.name]!! } } -data class ChapterDTO(val title: String, val content: String) +data class ChapterDTO( + val title: String, + val content: String +) + data class FullNoteDTO( val uuid: UUID, val title: String, @@ -143,7 +172,13 @@ data class FullNoteDTO( val chapters: List ) -data class FullNoteDTOPatch( +data class FullNoteCreateDTO( + val title: String, + val tags: List, + val chapters: List +) + +data class FullNotePatchDTO( val uuid: UUID? = null, val title: String? = null, val updatedAt: String? = null,