SimpleNotes/domain/src/usecases/NoteService.kt
2020-11-11 23:48:27 +01:00

116 lines
4.4 KiB
Kotlin

package be.simplenotes.domain.usecases
import arrow.core.computations.either
import be.simplenotes.domain.security.HtmlSanitizer
import be.simplenotes.domain.usecases.markdown.MarkdownConverter
import be.simplenotes.domain.usecases.markdown.MarkdownParsingError
import be.simplenotes.domain.usecases.search.parseSearchTerms
import be.simplenotes.persistance.repositories.NoteRepository
import be.simplenotes.persistance.repositories.UserRepository
import be.simplenotes.persistance.transactions.TransactionService
import be.simplenotes.search.NoteSearcher
import be.simplenotes.types.LoggedInUser
import be.simplenotes.types.Note
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedNoteMetadata
import java.util.*
import javax.annotation.PostConstruct
import javax.annotation.PreDestroy
import javax.inject.Singleton
@Singleton
class NoteService(
private val markdownConverter: MarkdownConverter,
private val noteRepository: NoteRepository,
private val userRepository: UserRepository,
private val searcher: NoteSearcher,
private val htmlSanitizer: HtmlSanitizer,
private val transaction: TransactionService,
) {
fun create(user: LoggedInUser, markdownText: String) = transaction.use {
either.eager<MarkdownParsingError, PersistedNote> {
val persistedNote = !markdownConverter.renderDocument(markdownText)
.map { it.copy(html = htmlSanitizer.sanitize(user, it.html)) }
.map { Note(it.metadata, markdown = markdownText, html = it.html) }
.map { noteRepository.create(user.userId, it) }
searcher.indexNote(user.userId, persistedNote)
persistedNote
}
}
fun update(
user: LoggedInUser,
uuid: UUID,
markdownText: String,
) = transaction.use {
either.eager<MarkdownParsingError, PersistedNote?> {
val persistedNote = !markdownConverter.renderDocument(markdownText)
.map { it.copy(html = htmlSanitizer.sanitize(user, it.html)) }
.map { Note(it.metadata, markdown = markdownText, html = it.html) }
.map { noteRepository.update(user.userId, uuid, it) }
persistedNote?.let { searcher.updateIndex(user.userId, it) }
persistedNote
}
}
fun paginatedNotes(
userId: Int,
page: Int,
itemsPerPage: Int = 20,
tag: String? = null,
deleted: Boolean = false,
): PaginatedNotes {
val count = noteRepository.count(userId, tag, deleted)
val offset = (page - 1) * itemsPerPage
val numberOfPages = (count / itemsPerPage) + 1
val notes = if (count == 0) emptyList() else noteRepository.findAll(userId, itemsPerPage, offset, tag, deleted)
return PaginatedNotes(numberOfPages, notes)
}
fun find(userId: Int, uuid: UUID) = noteRepository.find(userId, uuid)
fun trash(userId: Int, uuid: UUID): Boolean = transaction.use {
val res = noteRepository.delete(userId, uuid, permanent = false)
if (res) searcher.deleteIndex(userId, uuid)
res
}
fun restore(userId: Int, uuid: UUID): Boolean = transaction.use {
val res = noteRepository.restore(userId, uuid)
if (res) find(userId, uuid)?.let { note -> searcher.indexNote(userId, note) }
res
}
fun delete(userId: Int, uuid: UUID): Boolean = transaction.use {
val res = noteRepository.delete(userId, uuid, permanent = true)
if (res) searcher.deleteIndex(userId, uuid)
res
}
fun countDeleted(userId: Int) = noteRepository.count(userId, deleted = true)
@PostConstruct
fun indexAll() {
dropAllIndexes()
val userIds = userRepository.findAll()
userIds.forEach { id ->
val notes = noteRepository.findAllDetails(id)
searcher.indexNotes(id, notes)
}
}
fun search(userId: Int, searchInput: String) = searcher.search(userId, parseSearchTerms(searchInput))
@PreDestroy
fun dropAllIndexes() = searcher.dropAll()
fun makePublic(userId: Int, uuid: UUID) = transaction.use { noteRepository.makePublic(userId, uuid) }
fun makePrivate(userId: Int, uuid: UUID) = transaction.use { noteRepository.makePrivate(userId, uuid) }
fun findPublic(uuid: UUID) = noteRepository.findPublic(uuid)
}
data class PaginatedNotes(val pages: Int, val notes: List<PersistedNoteMetadata>)