Compare commits
7 Commits
bfd562bc60
...
cb58a4fbe0
| Author | SHA1 | Date | |
|---|---|---|---|
| cb58a4fbe0 | |||
| 64059984d3 | |||
| fdc8d34f82 | |||
| 95ec674eb8 | |||
| ea7be84ec3 | |||
| c709f2b44d | |||
| 7995a0b3e0 |
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,12 +1,3 @@
|
|||||||
# Java
|
|
||||||
.mtj.tmp/
|
|
||||||
*.class
|
|
||||||
*.jar
|
|
||||||
*.war
|
|
||||||
*.ear
|
|
||||||
*.nar
|
|
||||||
hs_err_pid*
|
|
||||||
|
|
||||||
# Gradle
|
# Gradle
|
||||||
build/
|
build/
|
||||||
.gradle
|
.gradle
|
||||||
@ -52,3 +43,4 @@ jspm_packages/
|
|||||||
|
|
||||||
# python
|
# python
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
||||||
|
|||||||
15
Dockerfile
15
Dockerfile
@ -24,4 +24,17 @@ COPY --from=jdkbuilder /myjdk /myjdk
|
|||||||
COPY simplenotes-app/build/libs/app-*-all.jar /app/simplenotes.jar
|
COPY simplenotes-app/build/libs/app-*-all.jar /app/simplenotes.jar
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
CMD ["/myjdk/bin/java", "-server", "-XX:+UnlockExperimentalVMOptions", "-Xms64m", "-Xmx256m", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=100", "-XX:+UseStringDeduplication", "-jar", "simplenotes.jar"]
|
CMD [ \
|
||||||
|
"/myjdk/bin/java", \
|
||||||
|
"--add-opens", \
|
||||||
|
"java.base/java.nio=ALL-UNNAMED", \
|
||||||
|
"-server", \
|
||||||
|
"-XX:+UnlockExperimentalVMOptions", \
|
||||||
|
"-Xms64m", \
|
||||||
|
"-Xmx256m", \
|
||||||
|
"-XX:+UseG1GC", \
|
||||||
|
"-XX:MaxGCPauseMillis=100", \
|
||||||
|
"-XX:+UseStringDeduplication", \
|
||||||
|
"-jar", \
|
||||||
|
"simplenotes.jar" \
|
||||||
|
]
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`kotlin-dsl`
|
`kotlin-dsl`
|
||||||
kotlin("jvm") version "1.4.10"
|
kotlin("jvm") version "1.4.10"
|
||||||
id("com.github.johnrengelman.shadow") version "6.1.0"
|
id("com.github.johnrengelman.shadow") version "6.1.0" apply false
|
||||||
|
kotlin("plugin.serialization") version "1.4.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@ -11,5 +12,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
|
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-serialization:1.4.10")
|
||||||
implementation("com.github.jengelman.gradle.plugins:shadow:6.1.0")
|
implementation("com.github.jengelman.gradle.plugins:shadow:6.1.0")
|
||||||
|
implementation("org.jlleitschuh.gradle:ktlint-gradle:9.4.1")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,8 @@ package be.simplenotes
|
|||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.tasks.InputDirectory
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.api.tasks.OutputDirectory
|
import org.gradle.kotlin.dsl.getByType
|
||||||
import org.gradle.api.tasks.TaskAction
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.ProcessBuilder.Redirect.PIPE
|
import java.lang.ProcessBuilder.Redirect.PIPE
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@ -12,31 +11,57 @@ import kotlin.concurrent.thread
|
|||||||
|
|
||||||
open class CssTask : DefaultTask() {
|
open class CssTask : DefaultTask() {
|
||||||
|
|
||||||
private val root = project.file(".").parent
|
private val root = project.parent!!.rootDir
|
||||||
|
|
||||||
|
private val viewsProject = project
|
||||||
|
.parent
|
||||||
|
?.project(":simplenotes-views")
|
||||||
|
?: error("Missing :simplenotes-views")
|
||||||
|
|
||||||
@get:InputDirectory
|
@get:InputDirectory
|
||||||
val templatesDir = File(root, "simplenotes-views/src/main/kotlin/be/simplenotes/views")
|
val templatesDir = viewsProject.extensions
|
||||||
|
.getByType<SourceSetContainer>()
|
||||||
|
.asMap.getOrElse("main") { error("main sources not found") }
|
||||||
|
.allSource.srcDirs
|
||||||
|
.find { it.endsWith("kotlin") }
|
||||||
|
?: error("kotlin sources not found")
|
||||||
|
|
||||||
|
private val yarnRoot = File(project.rootDir, "css")
|
||||||
|
|
||||||
@get:InputDirectory
|
@get:InputDirectory
|
||||||
val postCssDir = File(project.rootDir, "css/src")
|
val postCssDir = File(project.rootDir, "css/src")
|
||||||
|
|
||||||
|
@get:InputFiles
|
||||||
|
val postCssConfig = listOf(
|
||||||
|
"tailwind.config.js",
|
||||||
|
"postcss.config.js",
|
||||||
|
"package.json"
|
||||||
|
).map { File(yarnRoot, it) }
|
||||||
|
|
||||||
@get:OutputDirectory
|
@get:OutputDirectory
|
||||||
val outputRootDir = File(project.buildDir, "generated-resources/css")
|
val outputRootDir = File(project.buildDir, "generated-resources/css")
|
||||||
|
|
||||||
private val yarnRoot = File(project.rootDir, "css")
|
|
||||||
private val cssIndex = File(postCssDir, "styles.pcss")
|
private val cssIndex = File(postCssDir, "styles.pcss")
|
||||||
|
|
||||||
private val cssOutput = File(outputRootDir, "static/styles.css")
|
private val cssOutput = File(outputRootDir, "static/styles.css")
|
||||||
private val manifestOutput = File(outputRootDir, "css-manifest.json")
|
private val manifestOutput = File(outputRootDir, "css-manifest.json")
|
||||||
|
|
||||||
|
private val purgeGlob = "$templatesDir/**/*.kt"
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun generateCss() {
|
fun generateCss() {
|
||||||
// TODO: auto yarn install ?
|
// TODO: auto yarn install ?
|
||||||
|
|
||||||
outputRootDir.listFiles()?.let { it.forEach { it.delete() } }
|
outputRootDir.deleteRecursively()
|
||||||
|
|
||||||
ProcessBuilder("yarn", "run", "postcss", "build", "$cssIndex", "--output", "$cssOutput")
|
ProcessBuilder("yarn", "run", "postcss", "build", "$cssIndex", "--output", "$cssOutput")
|
||||||
.apply { environment()["MANIFEST"] = "$manifestOutput" }
|
.apply {
|
||||||
|
environment().let {
|
||||||
|
it["MANIFEST"] = "$manifestOutput"
|
||||||
|
it["NODE_ENV"] = "production"
|
||||||
|
it["PURGE"] = purgeGlob
|
||||||
|
}
|
||||||
|
}
|
||||||
.redirectOutput(PIPE)
|
.redirectOutput(PIPE)
|
||||||
.redirectError(PIPE)
|
.redirectError(PIPE)
|
||||||
.directory(yarnRoot)
|
.directory(yarnRoot)
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
package be.simplenotes
|
package be.simplenotes
|
||||||
|
|
||||||
object Libs {
|
object Libs {
|
||||||
const val arrowCore = "io.arrow-kt:arrow-core:0.11.0"
|
const val arrowCoreData = "io.arrow-kt:arrow-core-data:0.11.0"
|
||||||
const val commonsCompress = "org.apache.commons:commons-compress:1.20"
|
const val commonsCompress = "org.apache.commons:commons-compress:1.20"
|
||||||
const val flexmark = "com.vladsch.flexmark:flexmark:0.62.2"
|
const val flexmark = "com.vladsch.flexmark:flexmark:0.62.2"
|
||||||
const val flexmarkGfmTasklist = "com.vladsch.flexmark:flexmark-ext-gfm-tasklist:0.62.2"
|
const val flexmarkGfmTasklist = "com.vladsch.flexmark:flexmark-ext-gfm-tasklist:0.62.2"
|
||||||
|
|||||||
@ -6,6 +6,7 @@ plugins {
|
|||||||
java
|
java
|
||||||
kotlin("jvm")
|
kotlin("jvm")
|
||||||
`java-library`
|
`java-library`
|
||||||
|
id("org.jlleitschuh.gradle.ktlint")
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@ -21,6 +22,7 @@ version = "1.0-SNAPSHOT"
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("stdlib-jdk8"))
|
implementation(kotlin("stdlib-jdk8"))
|
||||||
|
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.4.10"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<Test> {
|
tasks.withType<Test> {
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
package be.simplenotes
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") apply false
|
||||||
|
kotlin("plugin.serialization")
|
||||||
|
}
|
||||||
@ -1,4 +1,3 @@
|
|||||||
arrow/core/extensions/**
|
|
||||||
org/checkerframework/**
|
org/checkerframework/**
|
||||||
org/intellij/**
|
org/intellij/**
|
||||||
com/google/errorprone/**
|
com/google/errorprone/**
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
purge: {
|
purge: {
|
||||||
content: [
|
content: [
|
||||||
'../simplenotes-app/src/main/kotlin/be/simplenotes/app/views/**/*.kt'
|
process.env.PURGE
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
@ -2,6 +2,7 @@ import be.simplenotes.Libs
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("be.simplenotes.base")
|
id("be.simplenotes.base")
|
||||||
|
id("be.simplenotes.kotlinx-serialization")
|
||||||
id("be.simplenotes.app-shadow")
|
id("be.simplenotes.app-shadow")
|
||||||
id("be.simplenotes.app-css")
|
id("be.simplenotes.app-css")
|
||||||
id("be.simplenotes.app-docker")
|
id("be.simplenotes.app-docker")
|
||||||
@ -16,7 +17,7 @@ dependencies {
|
|||||||
implementation(project(":simplenotes-views"))
|
implementation(project(":simplenotes-views"))
|
||||||
|
|
||||||
implementation(Libs.koinCore)
|
implementation(Libs.koinCore)
|
||||||
implementation(Libs.arrowCore)
|
implementation(Libs.arrowCoreData)
|
||||||
implementation(Libs.konform)
|
implementation(Libs.konform)
|
||||||
implementation(Libs.http4kCore)
|
implementation(Libs.http4kCore)
|
||||||
implementation(Libs.jettyServer)
|
implementation(Libs.jettyServer)
|
||||||
|
|||||||
@ -2,10 +2,10 @@ package be.simplenotes.app.api
|
|||||||
|
|
||||||
import be.simplenotes.app.extensions.auto
|
import be.simplenotes.app.extensions.auto
|
||||||
import be.simplenotes.app.utils.parseSearchTerms
|
import be.simplenotes.app.utils.parseSearchTerms
|
||||||
import be.simplenotes.types.PersistedNote
|
|
||||||
import be.simplenotes.types.PersistedNoteMetadata
|
|
||||||
import be.simplenotes.domain.usecases.NoteService
|
import be.simplenotes.domain.usecases.NoteService
|
||||||
import be.simplenotes.types.LoggedInUser
|
import be.simplenotes.types.LoggedInUser
|
||||||
|
import be.simplenotes.types.PersistedNote
|
||||||
|
import be.simplenotes.types.PersistedNoteMetadata
|
||||||
import kotlinx.serialization.Contextual
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
@ -28,7 +28,7 @@ class ApiNoteController(private val noteService: NoteService, private val json:
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notes(request: Request, loggedInUser: LoggedInUser): Response {
|
fun notes(@Suppress("UNUSED_PARAMETER") request: Request, loggedInUser: LoggedInUser): Response {
|
||||||
val notes = noteService.paginatedNotes(loggedInUser.userId, page = 1).notes
|
val notes = noteService.paginatedNotes(loggedInUser.userId, page = 1).notes
|
||||||
return persistedNotesMetadataLens(notes, Response(OK))
|
return persistedNotesMetadataLens(notes, Response(OK))
|
||||||
}
|
}
|
||||||
@ -40,12 +40,15 @@ class ApiNoteController(private val noteService: NoteService, private val json:
|
|||||||
|
|
||||||
fun update(request: Request, loggedInUser: LoggedInUser): Response {
|
fun update(request: Request, loggedInUser: LoggedInUser): Response {
|
||||||
val content = noteContentLens(request)
|
val content = noteContentLens(request)
|
||||||
return noteService.update(loggedInUser.userId, uuidLens(request), content).fold({
|
return noteService.update(loggedInUser.userId, uuidLens(request), content).fold(
|
||||||
|
{
|
||||||
Response(BAD_REQUEST)
|
Response(BAD_REQUEST)
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
if (it == null) Response(NOT_FOUND)
|
if (it == null) Response(NOT_FOUND)
|
||||||
else Response(OK)
|
else Response(OK)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(request: Request, loggedInUser: LoggedInUser): Response {
|
fun search(request: Request, loggedInUser: LoggedInUser): Response {
|
||||||
@ -61,7 +64,6 @@ class ApiNoteController(private val noteService: NoteService, private val json:
|
|||||||
private val persistedNotesMetadataLens = json.auto<List<PersistedNoteMetadata>>().toLens()
|
private val persistedNotesMetadataLens = json.auto<List<PersistedNoteMetadata>>().toLens()
|
||||||
private val persistedNoteLens = json.auto<PersistedNote>().toLens()
|
private val persistedNoteLens = json.auto<PersistedNote>().toLens()
|
||||||
private val uuidLens = Path.uuid().of("uuid")
|
private val uuidLens = Path.uuid().of("uuid")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|||||||
@ -7,6 +7,6 @@ import org.http4k.core.Status.Companion.OK
|
|||||||
import org.http4k.core.Status.Companion.SERVICE_UNAVAILABLE
|
import org.http4k.core.Status.Companion.SERVICE_UNAVAILABLE
|
||||||
|
|
||||||
class HealthCheckController(private val dbHealthCheck: DbHealthCheck) {
|
class HealthCheckController(private val dbHealthCheck: DbHealthCheck) {
|
||||||
fun healthCheck(request: Request) =
|
fun healthCheck(@Suppress("UNUSED_PARAMETER") request: Request) =
|
||||||
if (dbHealthCheck.isOk()) Response(OK) else Response(SERVICE_UNAVAILABLE)
|
if (dbHealthCheck.isOk()) Response(OK) else Response(SERVICE_UNAVAILABLE)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,12 +3,12 @@ package be.simplenotes.app.controllers
|
|||||||
import be.simplenotes.app.extensions.html
|
import be.simplenotes.app.extensions.html
|
||||||
import be.simplenotes.app.extensions.redirect
|
import be.simplenotes.app.extensions.redirect
|
||||||
import be.simplenotes.app.utils.parseSearchTerms
|
import be.simplenotes.app.utils.parseSearchTerms
|
||||||
import be.simplenotes.views.NoteView
|
|
||||||
import be.simplenotes.domain.usecases.NoteService
|
import be.simplenotes.domain.usecases.NoteService
|
||||||
import be.simplenotes.domain.usecases.markdown.InvalidMeta
|
import be.simplenotes.domain.usecases.markdown.InvalidMeta
|
||||||
import be.simplenotes.domain.usecases.markdown.MissingMeta
|
import be.simplenotes.domain.usecases.markdown.MissingMeta
|
||||||
import be.simplenotes.domain.usecases.markdown.ValidationError
|
import be.simplenotes.domain.usecases.markdown.ValidationError
|
||||||
import be.simplenotes.types.LoggedInUser
|
import be.simplenotes.types.LoggedInUser
|
||||||
|
import be.simplenotes.views.NoteView
|
||||||
import org.http4k.core.Method
|
import org.http4k.core.Method
|
||||||
import org.http4k.core.Request
|
import org.http4k.core.Request
|
||||||
import org.http4k.core.Response
|
import org.http4k.core.Response
|
||||||
@ -33,8 +33,16 @@ class NoteController(
|
|||||||
return noteService.create(loggedInUser.userId, markdownForm).fold(
|
return noteService.create(loggedInUser.userId, markdownForm).fold(
|
||||||
{
|
{
|
||||||
val html = when (it) {
|
val html = when (it) {
|
||||||
MissingMeta -> view.noteEditor(loggedInUser, error = "Missing note metadata", textarea = markdownForm)
|
MissingMeta -> view.noteEditor(
|
||||||
InvalidMeta -> view.noteEditor(loggedInUser, error = "Invalid note metadata", textarea = markdownForm)
|
loggedInUser,
|
||||||
|
error = "Missing note metadata",
|
||||||
|
textarea = markdownForm
|
||||||
|
)
|
||||||
|
InvalidMeta -> view.noteEditor(
|
||||||
|
loggedInUser,
|
||||||
|
error = "Invalid note metadata",
|
||||||
|
textarea = markdownForm
|
||||||
|
)
|
||||||
is ValidationError -> view.noteEditor(
|
is ValidationError -> view.noteEditor(
|
||||||
loggedInUser,
|
loggedInUser,
|
||||||
validationErrors = it.validationErrors,
|
validationErrors = it.validationErrors,
|
||||||
@ -105,8 +113,16 @@ class NoteController(
|
|||||||
return noteService.update(loggedInUser.userId, note.uuid, markdownForm).fold(
|
return noteService.update(loggedInUser.userId, note.uuid, markdownForm).fold(
|
||||||
{
|
{
|
||||||
val html = when (it) {
|
val html = when (it) {
|
||||||
MissingMeta -> view.noteEditor(loggedInUser, error = "Missing note metadata", textarea = markdownForm)
|
MissingMeta -> view.noteEditor(
|
||||||
InvalidMeta -> view.noteEditor(loggedInUser, error = "Invalid note metadata", textarea = markdownForm)
|
loggedInUser,
|
||||||
|
error = "Missing note metadata",
|
||||||
|
textarea = markdownForm
|
||||||
|
)
|
||||||
|
InvalidMeta -> view.noteEditor(
|
||||||
|
loggedInUser,
|
||||||
|
error = "Invalid note metadata",
|
||||||
|
textarea = markdownForm
|
||||||
|
)
|
||||||
is ValidationError -> view.noteEditor(
|
is ValidationError -> view.noteEditor(
|
||||||
loggedInUser,
|
loggedInUser,
|
||||||
validationErrors = it.validationErrors,
|
validationErrors = it.validationErrors,
|
||||||
|
|||||||
@ -2,11 +2,11 @@ package be.simplenotes.app.controllers
|
|||||||
|
|
||||||
import be.simplenotes.app.extensions.html
|
import be.simplenotes.app.extensions.html
|
||||||
import be.simplenotes.app.extensions.redirect
|
import be.simplenotes.app.extensions.redirect
|
||||||
import be.simplenotes.views.SettingView
|
|
||||||
import be.simplenotes.domain.usecases.UserService
|
import be.simplenotes.domain.usecases.UserService
|
||||||
import be.simplenotes.domain.usecases.users.delete.DeleteError
|
import be.simplenotes.domain.usecases.users.delete.DeleteError
|
||||||
import be.simplenotes.domain.usecases.users.delete.DeleteForm
|
import be.simplenotes.domain.usecases.users.delete.DeleteForm
|
||||||
import be.simplenotes.types.LoggedInUser
|
import be.simplenotes.types.LoggedInUser
|
||||||
|
import be.simplenotes.views.SettingView
|
||||||
import org.http4k.core.*
|
import org.http4k.core.*
|
||||||
import org.http4k.core.body.form
|
import org.http4k.core.body.form
|
||||||
import org.http4k.core.cookie.invalidateCookie
|
import org.http4k.core.cookie.invalidateCookie
|
||||||
@ -67,7 +67,10 @@ class SettingsController(
|
|||||||
Response(Status.OK)
|
Response(Status.OK)
|
||||||
.with(attachment("$filename.json", "application/json"))
|
.with(attachment("$filename.json", "application/json"))
|
||||||
.body(userService.exportAsJson(loggedInUser.userId))
|
.body(userService.exportAsJson(loggedInUser.userId))
|
||||||
} else Response(Status.OK).body(userService.exportAsJson(loggedInUser.userId)).header("Content-Type", "application/json")
|
} else Response(Status.OK).body(userService.exportAsJson(loggedInUser.userId)).header(
|
||||||
|
"Content-Type",
|
||||||
|
"application/json"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Request.deleteForm(loggedInUser: LoggedInUser) =
|
private fun Request.deleteForm(loggedInUser: LoggedInUser) =
|
||||||
|
|||||||
@ -3,14 +3,14 @@ package be.simplenotes.app.controllers
|
|||||||
import be.simplenotes.app.extensions.html
|
import be.simplenotes.app.extensions.html
|
||||||
import be.simplenotes.app.extensions.isSecure
|
import be.simplenotes.app.extensions.isSecure
|
||||||
import be.simplenotes.app.extensions.redirect
|
import be.simplenotes.app.extensions.redirect
|
||||||
import be.simplenotes.views.UserView
|
import be.simplenotes.config.JwtConfig
|
||||||
import be.simplenotes.domain.usecases.UserService
|
import be.simplenotes.domain.usecases.UserService
|
||||||
import be.simplenotes.domain.usecases.users.login.*
|
import be.simplenotes.domain.usecases.users.login.*
|
||||||
import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm
|
import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm
|
||||||
import be.simplenotes.domain.usecases.users.register.RegisterForm
|
import be.simplenotes.domain.usecases.users.register.RegisterForm
|
||||||
import be.simplenotes.domain.usecases.users.register.UserExists
|
import be.simplenotes.domain.usecases.users.register.UserExists
|
||||||
import be.simplenotes.config.JwtConfig
|
|
||||||
import be.simplenotes.types.LoggedInUser
|
import be.simplenotes.types.LoggedInUser
|
||||||
|
import be.simplenotes.views.UserView
|
||||||
import org.http4k.core.Method.GET
|
import org.http4k.core.Method.GET
|
||||||
import org.http4k.core.Request
|
import org.http4k.core.Request
|
||||||
import org.http4k.core.Response
|
import org.http4k.core.Response
|
||||||
|
|||||||
@ -23,7 +23,8 @@ fun Request.isSecure() = header("X-Forwarded-Proto")?.contains("https") ?: false
|
|||||||
|
|
||||||
val bodyLens = httpBodyRoot(
|
val bodyLens = httpBodyRoot(
|
||||||
listOf(Meta(true, "body", ParamMeta.ObjectParam, "body")),
|
listOf(Meta(true, "body", ParamMeta.ObjectParam, "body")),
|
||||||
ContentType.APPLICATION_JSON.withNoDirectives(), ContentNegotiation.StrictNoDirective
|
ContentType.APPLICATION_JSON.withNoDirectives(),
|
||||||
|
ContentNegotiation.StrictNoDirective
|
||||||
).map(
|
).map(
|
||||||
{ it.payload.asString() },
|
{ it.payload.asString() },
|
||||||
{ Body(it) }
|
{ Body(it) }
|
||||||
|
|||||||
@ -25,7 +25,7 @@ class AuthFilter(
|
|||||||
JwtSource.Header -> it.bearerTokenHeader()
|
JwtSource.Header -> it.bearerTokenHeader()
|
||||||
JwtSource.Cookie -> it.bearerTokenCookie()
|
JwtSource.Cookie -> it.bearerTokenCookie()
|
||||||
}
|
}
|
||||||
val jwtPayload = token?.let { token -> extractor(token) }
|
val jwtPayload = token?.let { extractor(token) }
|
||||||
when {
|
when {
|
||||||
jwtPayload != null -> {
|
jwtPayload != null -> {
|
||||||
ctx[it][authKey] = jwtPayload
|
ctx[it][authKey] = jwtPayload
|
||||||
|
|||||||
@ -12,9 +12,12 @@ import org.http4k.servlet.asServlet
|
|||||||
|
|
||||||
class Jetty(private val port: Int, private val server: Server) : ServerConfig {
|
class Jetty(private val port: Int, private val server: Server) : ServerConfig {
|
||||||
constructor(port: Int = 8000) : this(port, http(port))
|
constructor(port: Int = 8000) : this(port, http(port))
|
||||||
constructor(port: Int, vararg inConnectors: ConnectorBuilder) : this(port, Server().apply {
|
constructor(port: Int, vararg inConnectors: ConnectorBuilder) : this(
|
||||||
|
port,
|
||||||
|
Server().apply {
|
||||||
inConnectors.forEach { addConnector(it(this)) }
|
inConnectors.forEach { addConnector(it(this)) }
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
override fun toServer(httpHandler: HttpHandler): Http4kServer {
|
override fun toServer(httpHandler: HttpHandler): Http4kServer {
|
||||||
server.insertHandler(httpHandler.toJettyHandler())
|
server.insertHandler(httpHandler.toJettyHandler())
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import be.simplenotes.app.jetty.Jetty
|
|||||||
import be.simplenotes.app.routes.Router
|
import be.simplenotes.app.routes.Router
|
||||||
import be.simplenotes.app.utils.StaticFileResolver
|
import be.simplenotes.app.utils.StaticFileResolver
|
||||||
import be.simplenotes.app.utils.StaticFileResolverImpl
|
import be.simplenotes.app.utils.StaticFileResolverImpl
|
||||||
import be.simplenotes.views.ErrorView
|
|
||||||
import be.simplenotes.config.ServerConfig
|
import be.simplenotes.config.ServerConfig
|
||||||
import org.eclipse.jetty.server.ServerConnector
|
import org.eclipse.jetty.server.ServerConnector
|
||||||
import org.http4k.core.Filter
|
import org.http4k.core.Filter
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import java.util.*
|
|||||||
|
|
||||||
internal class UuidSerializer : KSerializer<UUID> {
|
internal class UuidSerializer : KSerializer<UUID> {
|
||||||
override val descriptor: SerialDescriptor
|
override val descriptor: SerialDescriptor
|
||||||
get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING)
|
get() = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING)
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: UUID) {
|
override fun serialize(encoder: Encoder, value: UUID) {
|
||||||
encoder.encodeString(value.toString())
|
encoder.encodeString(value.toString())
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package be.simplenotes.app.filters
|
package be.simplenotes.app.filters
|
||||||
|
|
||||||
|
import be.simplenotes.config.JwtConfig
|
||||||
import be.simplenotes.domain.security.JwtPayloadExtractor
|
import be.simplenotes.domain.security.JwtPayloadExtractor
|
||||||
import be.simplenotes.domain.security.SimpleJwt
|
import be.simplenotes.domain.security.SimpleJwt
|
||||||
import be.simplenotes.config.JwtConfig
|
|
||||||
import be.simplenotes.types.LoggedInUser
|
import be.simplenotes.types.LoggedInUser
|
||||||
import com.natpryce.hamkrest.assertion.assertThat
|
import com.natpryce.hamkrest.assertion.assertThat
|
||||||
import org.http4k.core.*
|
import org.http4k.core.*
|
||||||
|
|||||||
@ -30,7 +30,9 @@ internal class SearchTermsParserKtTest {
|
|||||||
createResult("tag:'example' title:'other' end", title = "other", tag = "example", all = "end"),
|
createResult("tag:'example' title:'other' end", title = "other", tag = "example", all = "end"),
|
||||||
createResult(
|
createResult(
|
||||||
"tag:'example abc' title:'other with words' this is the end ",
|
"tag:'example abc' title:'other with words' this is the end ",
|
||||||
title = "other with words", tag = "example abc", all = "this is the end"
|
title = "other with words",
|
||||||
|
tag = "example abc",
|
||||||
|
all = "this is the end"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import be.simplenotes.Libs
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("be.simplenotes.base")
|
id("be.simplenotes.base")
|
||||||
kotlin("plugin.serialization") version "1.4.10"
|
id("be.simplenotes.kotlinx-serialization")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -13,7 +13,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation(Libs.kotlinxSerializationJson)
|
implementation(Libs.kotlinxSerializationJson)
|
||||||
implementation(Libs.koinCore)
|
implementation(Libs.koinCore)
|
||||||
implementation(Libs.arrowCore)
|
implementation(Libs.arrowCoreData)
|
||||||
implementation(Libs.konform)
|
implementation(Libs.konform)
|
||||||
implementation(Libs.jbcrypt)
|
implementation(Libs.jbcrypt)
|
||||||
implementation(Libs.javaJwt)
|
implementation(Libs.javaJwt)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package be.simplenotes.domain.usecases.export
|
package be.simplenotes.domain.usecases.export
|
||||||
|
|
||||||
import be.simplenotes.types.ExportedNote
|
|
||||||
import be.simplenotes.persistance.repositories.NoteRepository
|
import be.simplenotes.persistance.repositories.NoteRepository
|
||||||
|
import be.simplenotes.types.ExportedNote
|
||||||
import kotlinx.serialization.builtins.ListSerializer
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
|
||||||
@ -31,7 +31,6 @@ internal class ExportUseCaseImpl(private val noteRepository: NoteRepository, pri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ZipOutput : AutoCloseable {
|
class ZipOutput : AutoCloseable {
|
||||||
val outputStream = ByteArrayOutputStream()
|
val outputStream = ByteArrayOutputStream()
|
||||||
private val zipOutputStream = ZipArchiveOutputStream(outputStream)
|
private val zipOutputStream = ZipArchiveOutputStream(outputStream)
|
||||||
|
|||||||
@ -19,7 +19,8 @@ internal class DeleteUseCaseImpl(
|
|||||||
!Either.conditionally(
|
!Either.conditionally(
|
||||||
passwordHash.verify(user.password, persistedUser.password),
|
passwordHash.verify(user.password, persistedUser.password),
|
||||||
{ DeleteError.WrongPassword },
|
{ DeleteError.WrongPassword },
|
||||||
{ Unit })
|
{ Unit }
|
||||||
|
)
|
||||||
!Either.conditionally(userRepository.delete(persistedUser.id), { DeleteError.Unregistered }, { Unit })
|
!Either.conditionally(userRepository.delete(persistedUser.id), { DeleteError.Unregistered }, { Unit })
|
||||||
searcher.dropIndex(persistedUser.id)
|
searcher.dropIndex(persistedUser.id)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,10 @@ package be.simplenotes.domain.usecases.users.register
|
|||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.filterOrElse
|
import arrow.core.filterOrElse
|
||||||
import arrow.core.leftIfNull
|
import arrow.core.leftIfNull
|
||||||
import be.simplenotes.types.PersistedUser
|
|
||||||
import be.simplenotes.domain.security.PasswordHash
|
import be.simplenotes.domain.security.PasswordHash
|
||||||
import be.simplenotes.domain.validation.UserValidations
|
import be.simplenotes.domain.validation.UserValidations
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
|
import be.simplenotes.types.PersistedUser
|
||||||
|
|
||||||
internal class RegisterUseCaseImpl(
|
internal class RegisterUseCaseImpl(
|
||||||
private val userRepository: UserRepository,
|
private val userRepository: UserRepository,
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package be.simplenotes.domain.usecases.users.register
|
package be.simplenotes.domain.usecases.users.register
|
||||||
|
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import be.simplenotes.types.PersistedUser
|
|
||||||
import be.simplenotes.domain.usecases.users.login.LoginForm
|
import be.simplenotes.domain.usecases.users.login.LoginForm
|
||||||
|
import be.simplenotes.types.PersistedUser
|
||||||
import io.konform.validation.ValidationErrors
|
import io.konform.validation.ValidationErrors
|
||||||
|
|
||||||
sealed class RegisterError
|
sealed class RegisterError
|
||||||
|
|||||||
@ -3,13 +3,13 @@ package be.simplenotes.domain.validation
|
|||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.left
|
import arrow.core.left
|
||||||
import arrow.core.right
|
import arrow.core.right
|
||||||
import be.simplenotes.types.User
|
|
||||||
import be.simplenotes.domain.usecases.users.delete.DeleteError
|
import be.simplenotes.domain.usecases.users.delete.DeleteError
|
||||||
import be.simplenotes.domain.usecases.users.delete.DeleteForm
|
import be.simplenotes.domain.usecases.users.delete.DeleteForm
|
||||||
import be.simplenotes.domain.usecases.users.login.InvalidLoginForm
|
import be.simplenotes.domain.usecases.users.login.InvalidLoginForm
|
||||||
import be.simplenotes.domain.usecases.users.login.LoginForm
|
import be.simplenotes.domain.usecases.users.login.LoginForm
|
||||||
import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm
|
import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm
|
||||||
import be.simplenotes.domain.usecases.users.register.RegisterForm
|
import be.simplenotes.domain.usecases.users.register.RegisterForm
|
||||||
|
import be.simplenotes.types.User
|
||||||
import io.konform.validation.Validation
|
import io.konform.validation.Validation
|
||||||
import io.konform.validation.jsonschema.maxLength
|
import io.konform.validation.jsonschema.maxLength
|
||||||
import io.konform.validation.jsonschema.minLength
|
import io.konform.validation.jsonschema.minLength
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package be.simplenotes.domain.security
|
package be.simplenotes.domain.security
|
||||||
|
|
||||||
import be.simplenotes.domain.usecases.users.login.Token
|
|
||||||
import be.simplenotes.config.JwtConfig
|
import be.simplenotes.config.JwtConfig
|
||||||
|
import be.simplenotes.domain.usecases.users.login.Token
|
||||||
import be.simplenotes.types.LoggedInUser
|
import be.simplenotes.types.LoggedInUser
|
||||||
import com.auth0.jwt.JWT
|
import com.auth0.jwt.JWT
|
||||||
import com.auth0.jwt.algorithms.Algorithm
|
import com.auth0.jwt.algorithms.Algorithm
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
package be.simplenotes.domain.usecases.users.login
|
package be.simplenotes.domain.usecases.users.login
|
||||||
|
|
||||||
import be.simplenotes.types.PersistedUser
|
import be.simplenotes.config.JwtConfig
|
||||||
import be.simplenotes.domain.security.BcryptPasswordHash
|
import be.simplenotes.domain.security.BcryptPasswordHash
|
||||||
import be.simplenotes.domain.security.SimpleJwt
|
import be.simplenotes.domain.security.SimpleJwt
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
|
||||||
import be.simplenotes.config.JwtConfig
|
|
||||||
import be.simplenotes.domain.testutils.isLeftOfType
|
import be.simplenotes.domain.testutils.isLeftOfType
|
||||||
import be.simplenotes.domain.testutils.isRight
|
import be.simplenotes.domain.testutils.isRight
|
||||||
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
|
import be.simplenotes.types.PersistedUser
|
||||||
import com.natpryce.hamkrest.assertion.assertThat
|
import com.natpryce.hamkrest.assertion.assertThat
|
||||||
import io.mockk.*
|
import io.mockk.*
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package be.simplenotes.domain.usecases.users.register
|
package be.simplenotes.domain.usecases.users.register
|
||||||
|
|
||||||
import be.simplenotes.types.PersistedUser
|
|
||||||
import be.simplenotes.domain.security.BcryptPasswordHash
|
import be.simplenotes.domain.security.BcryptPasswordHash
|
||||||
import be.simplenotes.domain.testutils.isLeftOfType
|
import be.simplenotes.domain.testutils.isLeftOfType
|
||||||
import be.simplenotes.domain.testutils.isRight
|
import be.simplenotes.domain.testutils.isRight
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
|
import be.simplenotes.types.PersistedUser
|
||||||
import com.natpryce.hamkrest.assertion.assertThat
|
import com.natpryce.hamkrest.assertion.assertThat
|
||||||
import com.natpryce.hamkrest.equalTo
|
import com.natpryce.hamkrest.equalTo
|
||||||
import io.mockk.*
|
import io.mockk.*
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package be.simplenotes.persistance
|
package be.simplenotes.persistance
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
import be.simplenotes.persistance.utils.DbType
|
import be.simplenotes.persistance.utils.DbType
|
||||||
import be.simplenotes.persistance.utils.type
|
import be.simplenotes.persistance.utils.type
|
||||||
import be.simplenotes.config.DataSourceConfig
|
|
||||||
import me.liuwj.ktorm.database.Database
|
import me.liuwj.ktorm.database.Database
|
||||||
import me.liuwj.ktorm.database.asIterable
|
import me.liuwj.ktorm.database.asIterable
|
||||||
import me.liuwj.ktorm.database.use
|
import me.liuwj.ktorm.database.use
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package be.simplenotes.persistance
|
package be.simplenotes.persistance
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
import be.simplenotes.persistance.utils.DbType
|
import be.simplenotes.persistance.utils.DbType
|
||||||
import be.simplenotes.persistance.utils.type
|
import be.simplenotes.persistance.utils.type
|
||||||
import be.simplenotes.config.DataSourceConfig
|
|
||||||
import org.flywaydb.core.Flyway
|
import org.flywaydb.core.Flyway
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import org.mapstruct.ReportingPolicy
|
|||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an abstract class because kotlin default methods in interface are not seen as default in kapt
|
* This is an abstract class because kotlin default methods in interface are not seen as default in kapt
|
||||||
* @see [KT-25960](https://youtrack.jetbrains.com/issue/KT-25960)
|
* @see [KT-25960](https://youtrack.jetbrains.com/issue/KT-25960)
|
||||||
@ -35,7 +34,11 @@ internal abstract class NoteConverter {
|
|||||||
|
|
||||||
fun toPersistedNote(entity: NoteEntity, tags: Tags) = PersistedNote(
|
fun toPersistedNote(entity: NoteEntity, tags: Tags) = PersistedNote(
|
||||||
NoteMetadata(title = entity.title, tags = tags),
|
NoteMetadata(title = entity.title, tags = tags),
|
||||||
entity.markdown, entity.html, entity.updatedAt, entity.uuid, entity.public
|
entity.markdown,
|
||||||
|
entity.html,
|
||||||
|
entity.updatedAt,
|
||||||
|
entity.uuid,
|
||||||
|
entity.public
|
||||||
)
|
)
|
||||||
|
|
||||||
@Mappings(
|
@Mappings(
|
||||||
@ -73,7 +76,6 @@ internal abstract class NoteConverter {
|
|||||||
|
|
||||||
@Mapping(target = "deleted", source = "trash")
|
@Mapping(target = "deleted", source = "trash")
|
||||||
abstract fun toEntity(exportedNote: ExportedNote): NoteEntity
|
abstract fun toEntity(exportedNote: ExportedNote): NoteEntity
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias Tags = List<String>
|
typealias Tags = List<String>
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
package be.simplenotes.persistance.notes
|
package be.simplenotes.persistance.notes
|
||||||
|
|
||||||
|
import be.simplenotes.persistance.converters.NoteConverter
|
||||||
|
import be.simplenotes.persistance.repositories.NoteRepository
|
||||||
import be.simplenotes.types.ExportedNote
|
import be.simplenotes.types.ExportedNote
|
||||||
import be.simplenotes.types.Note
|
import be.simplenotes.types.Note
|
||||||
import be.simplenotes.types.PersistedNote
|
import be.simplenotes.types.PersistedNote
|
||||||
import be.simplenotes.types.PersistedNoteMetadata
|
import be.simplenotes.types.PersistedNoteMetadata
|
||||||
import be.simplenotes.persistance.converters.NoteConverter
|
|
||||||
import be.simplenotes.persistance.repositories.NoteRepository
|
|
||||||
import me.liuwj.ktorm.database.Database
|
import me.liuwj.ktorm.database.Database
|
||||||
import me.liuwj.ktorm.dsl.*
|
import me.liuwj.ktorm.dsl.*
|
||||||
import me.liuwj.ktorm.entity.*
|
import me.liuwj.ktorm.entity.*
|
||||||
@ -211,5 +211,4 @@ internal class NoteRepositoryImpl(private val db: Database, private val converte
|
|||||||
.filter { it.noteUuid inList map { note -> note.uuid } }
|
.filter { it.noteUuid inList map { note -> note.uuid } }
|
||||||
.groupByTo(HashMap(), { it.note.uuid }, { it.name })
|
.groupByTo(HashMap(), { it.note.uuid }, { it.name })
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package be.simplenotes.persistance.users
|
package be.simplenotes.persistance.users
|
||||||
|
|
||||||
import be.simplenotes.types.PersistedUser
|
|
||||||
import be.simplenotes.types.User
|
|
||||||
import be.simplenotes.persistance.converters.UserConverter
|
import be.simplenotes.persistance.converters.UserConverter
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
|
import be.simplenotes.types.PersistedUser
|
||||||
|
import be.simplenotes.types.User
|
||||||
import me.liuwj.ktorm.database.Database
|
import me.liuwj.ktorm.database.Database
|
||||||
import me.liuwj.ktorm.dsl.*
|
import me.liuwj.ktorm.dsl.*
|
||||||
import me.liuwj.ktorm.entity.any
|
import me.liuwj.ktorm.entity.any
|
||||||
|
|||||||
@ -26,10 +26,14 @@ internal class NoteConverterTest {
|
|||||||
}
|
}
|
||||||
val tags = listOf("a", "b")
|
val tags = listOf("a", "b")
|
||||||
val note = converter.toNote(entity, tags)
|
val note = converter.toNote(entity, tags)
|
||||||
val expectedNote = Note(NoteMetadata(
|
val expectedNote = Note(
|
||||||
|
NoteMetadata(
|
||||||
title = "title",
|
title = "title",
|
||||||
tags = tags,
|
tags = tags,
|
||||||
), markdown = "md", html = "html")
|
),
|
||||||
|
markdown = "md",
|
||||||
|
html = "html"
|
||||||
|
)
|
||||||
assertThat(note).isEqualTo(expectedNote)
|
assertThat(note).isEqualTo(expectedNote)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +81,6 @@ internal class NoteConverterTest {
|
|||||||
)
|
)
|
||||||
assertThat(note).isEqualTo(expectedNote)
|
assertThat(note).isEqualTo(expectedNote)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@ -162,7 +165,5 @@ internal class NoteConverterTest {
|
|||||||
.hasFieldOrPropertyWithValue("updatedAt", exportedNote.updatedAt)
|
.hasFieldOrPropertyWithValue("updatedAt", exportedNote.updatedAt)
|
||||||
.hasFieldOrPropertyWithValue("deleted", true)
|
.hasFieldOrPropertyWithValue("deleted", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package be.simplenotes.persistance.converters
|
package be.simplenotes.persistance.converters
|
||||||
|
|
||||||
|
import be.simplenotes.persistance.users.UserEntity
|
||||||
import be.simplenotes.types.PersistedUser
|
import be.simplenotes.types.PersistedUser
|
||||||
import be.simplenotes.types.User
|
import be.simplenotes.types.User
|
||||||
import be.simplenotes.persistance.users.UserEntity
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.mapstruct.factory.Mappers
|
import org.mapstruct.factory.Mappers
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
package be.simplenotes.persistance.notes
|
package be.simplenotes.persistance.notes
|
||||||
|
|
||||||
|
import be.simplenotes.config.DataSourceConfig
|
||||||
import be.simplenotes.persistance.DbMigrations
|
import be.simplenotes.persistance.DbMigrations
|
||||||
import be.simplenotes.persistance.converters.NoteConverter
|
import be.simplenotes.persistance.converters.NoteConverter
|
||||||
import be.simplenotes.persistance.migrationModule
|
import be.simplenotes.persistance.migrationModule
|
||||||
import be.simplenotes.persistance.persistanceModule
|
import be.simplenotes.persistance.persistanceModule
|
||||||
import be.simplenotes.config.DataSourceConfig
|
|
||||||
import be.simplenotes.persistance.repositories.NoteRepository
|
import be.simplenotes.persistance.repositories.NoteRepository
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
import be.simplenotes.types.*
|
import be.simplenotes.types.*
|
||||||
import be.simplenotes.types.*
|
|
||||||
import me.liuwj.ktorm.database.Database
|
import me.liuwj.ktorm.database.Database
|
||||||
import me.liuwj.ktorm.dsl.eq
|
import me.liuwj.ktorm.dsl.eq
|
||||||
import me.liuwj.ktorm.entity.filter
|
import me.liuwj.ktorm.entity.filter
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
package be.simplenotes.persistance.users
|
package be.simplenotes.persistance.users
|
||||||
|
|
||||||
import be.simplenotes.types.User
|
import be.simplenotes.config.DataSourceConfig
|
||||||
import be.simplenotes.persistance.repositories.UserRepository
|
|
||||||
import be.simplenotes.persistance.DbMigrations
|
import be.simplenotes.persistance.DbMigrations
|
||||||
import be.simplenotes.persistance.migrationModule
|
import be.simplenotes.persistance.migrationModule
|
||||||
import be.simplenotes.persistance.persistanceModule
|
import be.simplenotes.persistance.persistanceModule
|
||||||
import be.simplenotes.config.DataSourceConfig
|
import be.simplenotes.persistance.repositories.UserRepository
|
||||||
|
import be.simplenotes.types.User
|
||||||
import me.liuwj.ktorm.database.*
|
import me.liuwj.ktorm.database.*
|
||||||
import me.liuwj.ktorm.dsl.*
|
import me.liuwj.ktorm.dsl.*
|
||||||
import me.liuwj.ktorm.entity.*
|
import me.liuwj.ktorm.entity.*
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package be.simplenotes.search
|
package be.simplenotes.search
|
||||||
|
|
||||||
import be.simplenotes.types.PersistedNote
|
import be.simplenotes.types.PersistedNote
|
||||||
import be.simplenotes.search.utils.rmdir
|
|
||||||
import org.apache.lucene.analysis.standard.StandardAnalyzer
|
import org.apache.lucene.analysis.standard.StandardAnalyzer
|
||||||
import org.apache.lucene.document.Document
|
import org.apache.lucene.document.Document
|
||||||
import org.apache.lucene.index.*
|
import org.apache.lucene.index.*
|
||||||
@ -90,7 +89,11 @@ internal class NoteSearcherImpl(basePath: Path = Path.of("/tmp", "lucene")) : No
|
|||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dropIndex(userId: Int) = rmdir(File(baseFile, userId.toString()).toPath())
|
override fun dropIndex(userId: Int) {
|
||||||
|
File(baseFile, userId.toString()).deleteRecursively()
|
||||||
override fun dropAll() = rmdir(baseFile.toPath())
|
}
|
||||||
|
|
||||||
|
override fun dropAll() {
|
||||||
|
baseFile.deleteRecursively()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
package be.simplenotes.search.utils
|
|
||||||
|
|
||||||
import java.io.IOException
|
|
||||||
import java.nio.file.FileVisitResult
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
import java.nio.file.SimpleFileVisitor
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes
|
|
||||||
|
|
||||||
internal fun rmdir(path: Path) {
|
|
||||||
try {
|
|
||||||
Files.walkFileTree(
|
|
||||||
path,
|
|
||||||
object : SimpleFileVisitor<Path>() {
|
|
||||||
override fun visitFile(file: Path, attrs: BasicFileAttributes?): FileVisitResult {
|
|
||||||
Files.delete(file)
|
|
||||||
return FileVisitResult.CONTINUE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
|
|
||||||
Files.delete(dir)
|
|
||||||
return FileVisitResult.CONTINUE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
// This is fine
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -24,12 +24,14 @@ internal class NoteSearcherImplTest {
|
|||||||
content: String = "",
|
content: String = "",
|
||||||
uuid: UUID = UUID.randomUUID(),
|
uuid: UUID = UUID.randomUUID(),
|
||||||
): PersistedNote {
|
): PersistedNote {
|
||||||
val note = PersistedNote(NoteMetadata(title, tags),
|
val note = PersistedNote(
|
||||||
|
NoteMetadata(title, tags),
|
||||||
markdown = content,
|
markdown = content,
|
||||||
html = "",
|
html = "",
|
||||||
LocalDateTime.MIN,
|
LocalDateTime.MIN,
|
||||||
uuid,
|
uuid,
|
||||||
public = false)
|
public = false
|
||||||
|
)
|
||||||
searcher.indexNote(1, note)
|
searcher.indexNote(1, note)
|
||||||
return note
|
return note
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import be.simplenotes.Libs
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("be.simplenotes.base")
|
id("be.simplenotes.base")
|
||||||
kotlin("plugin.serialization") version "1.4.10"
|
id("be.simplenotes.kotlinx-serialization")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package be.simplenotes.views
|
package be.simplenotes.views
|
||||||
|
|
||||||
import be.simplenotes.types.LoggedInUser
|
import be.simplenotes.types.LoggedInUser
|
||||||
import be.simplenotes.views.components.noteListHeader
|
|
||||||
import be.simplenotes.types.PersistedNote
|
import be.simplenotes.types.PersistedNote
|
||||||
import be.simplenotes.types.PersistedNoteMetadata
|
import be.simplenotes.types.PersistedNoteMetadata
|
||||||
import be.simplenotes.views.components.*
|
import be.simplenotes.views.components.*
|
||||||
@ -38,7 +37,9 @@ class NoteView(styles: String) : View(styles) {
|
|||||||
|tags: []
|
|tags: []
|
||||||
|---
|
|---
|
||||||
|
|
|
|
||||||
""".trimMargin("|")
|
""".trimMargin(
|
||||||
|
"|"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
submitButton("Save")
|
submitButton("Save")
|
||||||
}
|
}
|
||||||
@ -182,7 +183,8 @@ class NoteView(styles: String) : View(styles) {
|
|||||||
button(
|
button(
|
||||||
type = ButtonType.submit,
|
type = ButtonType.submit,
|
||||||
name = if (note.public) "private" else "public",
|
name = if (note.public) "private" else "public",
|
||||||
classes = "font-semibold border-b-4 ${if (!note.public) "border-teal-200" else "border-green-500"}" +
|
classes = "font-semibold border-b-4 " +
|
||||||
|
(if (!note.public) "border-teal-200" else "border-green-500") +
|
||||||
" p-2 rounded-r bg-teal-200 text-gray-800"
|
" p-2 rounded-r bg-teal-200 text-gray-800"
|
||||||
) {
|
) {
|
||||||
+"Public"
|
+"Public"
|
||||||
|
|||||||
@ -28,9 +28,11 @@ class SettingView(styles: String) : View(styles) {
|
|||||||
section("m-4 p-2 bg-gray-800 rounded flex flex-wrap justify-around items-end") {
|
section("m-4 p-2 bg-gray-800 rounded flex flex-wrap justify-around items-end") {
|
||||||
|
|
||||||
form(classes = "m-2", method = FormMethod.post, action = "/export") {
|
form(classes = "m-2", method = FormMethod.post, action = "/export") {
|
||||||
button(name = "display",
|
button(
|
||||||
|
name = "display",
|
||||||
classes = "inline btn btn-teal block",
|
classes = "inline btn btn-teal block",
|
||||||
type = submit) { +"Display my data" }
|
type = submit
|
||||||
|
) { +"Display my data" }
|
||||||
}
|
}
|
||||||
|
|
||||||
form(classes = "m-2", method = FormMethod.post, action = "/export") {
|
form(classes = "m-2", method = FormMethod.post, action = "/export") {
|
||||||
|
|||||||
@ -4,7 +4,9 @@ import kotlinx.html.*
|
|||||||
|
|
||||||
internal class SUMMARY(consumer: TagConsumer<*>) :
|
internal class SUMMARY(consumer: TagConsumer<*>) :
|
||||||
HTMLTag(
|
HTMLTag(
|
||||||
"summary", consumer, emptyMap(),
|
"summary",
|
||||||
|
consumer,
|
||||||
|
emptyMap(),
|
||||||
inlineTag = true,
|
inlineTag = true,
|
||||||
emptyTag = false
|
emptyTag = false
|
||||||
),
|
),
|
||||||
|
|||||||
@ -7,4 +7,6 @@ import java.util.*
|
|||||||
|
|
||||||
private val prettyTime = PrettyTime()
|
private val prettyTime = PrettyTime()
|
||||||
|
|
||||||
internal fun LocalDateTime.toTimeAgo(): String = prettyTime.format(Date.from(atZone(ZoneId.systemDefault()).toInstant()))
|
internal fun LocalDateTime.toTimeAgo(): String = prettyTime.format(
|
||||||
|
Date.from(atZone(ZoneId.systemDefault()).toInstant())
|
||||||
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user