Add category routes
This commit is contained in:
parent
ed1dde49bf
commit
4de09a8f1c
16 changed files with 247 additions and 309 deletions
1
api/.gitignore
vendored
Normal file
1
api/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
|
@ -23,8 +23,10 @@ fun Application.budgetRoutes(
|
||||||
block: suspend (Budget) -> Unit
|
block: suspend (Budget) -> Unit
|
||||||
) {
|
) {
|
||||||
val session = call.principal<Session>()!!
|
val session = call.principal<Session>()!!
|
||||||
val userPermission =
|
val userPermission = permissionRepository.findAll(
|
||||||
permissionRepository.findAllByUserId(session.userId).firstOrNull { it.budgetId == budgetId }
|
userId = session.userId,
|
||||||
|
budgetIds = listOf(budgetId)
|
||||||
|
).firstOrNull()
|
||||||
if (userPermission?.permission?.isNotAtLeast(permission) != true) {
|
if (userPermission?.permission?.isNotAtLeast(permission) != true) {
|
||||||
call.respond(HttpStatusCode.Forbidden)
|
call.respond(HttpStatusCode.Forbidden)
|
||||||
return
|
return
|
||||||
|
@ -33,24 +35,20 @@ fun Application.budgetRoutes(
|
||||||
}
|
}
|
||||||
|
|
||||||
routing {
|
routing {
|
||||||
|
route("/api/budgets") {
|
||||||
authenticate(optional = false) {
|
authenticate(optional = false) {
|
||||||
get("/") {
|
get("/") {
|
||||||
val session = call.principal<Session>()!!
|
val session = call.principal<Session>()!!
|
||||||
val budgetIds = permissionRepository.findAllByUserId(session.userId).map { it.budgetId }
|
val budgetIds = permissionRepository.findAll(userId = session.userId).map { it.budgetId }
|
||||||
val budgets = budgetRepository.findAllByIds(budgetIds).map {
|
val budgets = budgetRepository.findAllByIds(budgetIds).map {
|
||||||
BudgetResponse(it, permissionRepository.findAllByBudgetId(it.id))
|
BudgetResponse(it, permissionRepository.findAll(budgetIds = listOf(it.id)))
|
||||||
}
|
|
||||||
if (call.request.contentType() == ContentType.Application.Json) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
call.respondHtml()
|
|
||||||
}
|
}
|
||||||
call.respond(budgets)
|
call.respond(budgets)
|
||||||
}
|
}
|
||||||
|
|
||||||
get("/{id}") {
|
get("/{id}") {
|
||||||
budgetWithPermission(budgetId = call.parameters["id"]!!, Permission.READ) { budget ->
|
budgetWithPermission(budgetId = call.parameters["id"]!!, Permission.READ) { budget ->
|
||||||
val users = permissionRepository.findAllByBudgetId(budget.id)
|
val users = permissionRepository.findAll(budgetIds = listOf(budget.id))
|
||||||
call.respond(BudgetResponse(budget, users))
|
call.respond(BudgetResponse(budget, users))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,8 +96,8 @@ fun Application.budgetRoutes(
|
||||||
val description = request.description ?: budget.description
|
val description = request.description ?: budget.description
|
||||||
val users = request.users?.map {
|
val users = request.users?.map {
|
||||||
permissionRepository.save(UserPermission(budget.id, it.user, it.permission))
|
permissionRepository.save(UserPermission(budget.id, it.user, it.permission))
|
||||||
} ?: permissionRepository.findAllByBudgetId(budget.id)
|
} ?: permissionRepository.findAll(budgetIds = listOf(budget.id))
|
||||||
permissionRepository.findAllByBudgetId(budget.id).forEach {
|
permissionRepository.findAll(budgetIds = listOf(budget.id)).forEach {
|
||||||
if (it.permission != Permission.OWNER && users.none { userPermission -> userPermission.userId == it.userId }) {
|
if (it.permission != Permission.OWNER && users.none { userPermission -> userPermission.userId == it.userId }) {
|
||||||
permissionRepository.delete(it)
|
permissionRepository.delete(it)
|
||||||
}
|
}
|
||||||
|
@ -114,7 +112,7 @@ fun Application.budgetRoutes(
|
||||||
}
|
}
|
||||||
|
|
||||||
delete("/{id}") {
|
delete("/{id}") {
|
||||||
budgetWithPermission(budgetId = call.parameters["id"]!!, Permission.READ) { budget ->
|
budgetWithPermission(budgetId = call.parameters["id"]!!, Permission.OWNER) { budget ->
|
||||||
budgetRepository.delete(budget)
|
budgetRepository.delete(budget)
|
||||||
call.respond(HttpStatusCode.NoContent)
|
call.respond(HttpStatusCode.NoContent)
|
||||||
}
|
}
|
||||||
|
@ -122,3 +120,4 @@ fun Application.budgetRoutes(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,18 +2,11 @@ package com.wbrawner.twigs
|
||||||
|
|
||||||
import com.wbrawner.twigs.model.Category
|
import com.wbrawner.twigs.model.Category
|
||||||
|
|
||||||
data class NewCategoryRequest(
|
data class CategoryRequest(
|
||||||
val title: String,
|
|
||||||
val description: String? = null,
|
|
||||||
val amount: Long,
|
|
||||||
val budgetId: String,
|
|
||||||
val expense: Boolean
|
|
||||||
)
|
|
||||||
|
|
||||||
data class UpdateCategoryRequest(
|
|
||||||
val title: String? = null,
|
val title: String? = null,
|
||||||
val description: String? = null,
|
val description: String? = null,
|
||||||
val amount: Long? = null,
|
val amount: Long? = null,
|
||||||
|
val budgetId: String? = null,
|
||||||
val expense: Boolean? = null,
|
val expense: Boolean? = null,
|
||||||
val archived: Boolean? = null
|
val archived: Boolean? = null
|
||||||
)
|
)
|
||||||
|
|
148
api/src/main/kotlin/com/wbrawner/twigs/CategoryRoutes.kt
Normal file
148
api/src/main/kotlin/com/wbrawner/twigs/CategoryRoutes.kt
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
package com.wbrawner.twigs
|
||||||
|
|
||||||
|
import com.wbrawner.twigs.model.Category
|
||||||
|
import com.wbrawner.twigs.model.Permission
|
||||||
|
import com.wbrawner.twigs.storage.CategoryRepository
|
||||||
|
import com.wbrawner.twigs.storage.PermissionRepository
|
||||||
|
import io.ktor.application.*
|
||||||
|
import io.ktor.auth.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.request.*
|
||||||
|
import io.ktor.response.*
|
||||||
|
import io.ktor.routing.*
|
||||||
|
import io.ktor.util.pipeline.*
|
||||||
|
|
||||||
|
fun Application.categoryRoutes(
|
||||||
|
categoryRepository: CategoryRepository,
|
||||||
|
permissionRepository: PermissionRepository
|
||||||
|
) {
|
||||||
|
routing {
|
||||||
|
route("/api/categories") {
|
||||||
|
authenticate(optional = false) {
|
||||||
|
get("/") {
|
||||||
|
val session = call.principal<Session>()!!
|
||||||
|
call.respond(categoryRepository.findAll(
|
||||||
|
budgetIds = permissionRepository.findAll(
|
||||||
|
budgetIds = call.request.queryParameters.getAll("budgetIds"),
|
||||||
|
userId = session.userId
|
||||||
|
).map { it.budgetId },
|
||||||
|
expense = call.request.queryParameters["expense"]?.toBoolean(),
|
||||||
|
archived = call.request.queryParameters["archived"]?.toBoolean()
|
||||||
|
).map { CategoryResponse(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
get("/{id}") {
|
||||||
|
val session = call.principal<Session>()!!
|
||||||
|
call.respond(categoryRepository.findAll(
|
||||||
|
ids = call.parameters.getAll("id"),
|
||||||
|
budgetIds = permissionRepository.findAll(
|
||||||
|
userId = session.userId
|
||||||
|
).map { it.budgetId }
|
||||||
|
).map { CategoryResponse(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
post("/{id}") {
|
||||||
|
val session = call.principal<Session>()!!
|
||||||
|
val request = call.receive<CategoryRequest>()
|
||||||
|
if (request.title.isNullOrBlank()) {
|
||||||
|
call.respond(HttpStatusCode.BadRequest, ErrorResponse("Title cannot be null or empty"))
|
||||||
|
return@post
|
||||||
|
}
|
||||||
|
if (request.budgetId.isNullOrBlank()) {
|
||||||
|
call.respond(HttpStatusCode.BadRequest, ErrorResponse("Budget ID cannot be null or empty"))
|
||||||
|
return@post
|
||||||
|
}
|
||||||
|
requireBudgetWithPermission(
|
||||||
|
permissionRepository,
|
||||||
|
session.userId,
|
||||||
|
request.budgetId,
|
||||||
|
Permission.WRITE
|
||||||
|
) {
|
||||||
|
return@post
|
||||||
|
}
|
||||||
|
call.respond(
|
||||||
|
CategoryResponse(
|
||||||
|
categoryRepository.save(
|
||||||
|
Category(
|
||||||
|
title = request.title,
|
||||||
|
description = request.description,
|
||||||
|
amount = request.amount ?: 0L,
|
||||||
|
expense = request.expense ?: true,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
put("/{id}") {
|
||||||
|
val session = call.principal<Session>()!!
|
||||||
|
val request = call.receive<CategoryRequest>()
|
||||||
|
val category = categoryRepository.findAll(ids = call.parameters.getAll("id"))
|
||||||
|
.firstOrNull()
|
||||||
|
?: run {
|
||||||
|
call.respond(HttpStatusCode.NotFound)
|
||||||
|
return@put
|
||||||
|
}
|
||||||
|
requireBudgetWithPermission(
|
||||||
|
permissionRepository,
|
||||||
|
session.userId,
|
||||||
|
category.budgetId!!,
|
||||||
|
Permission.WRITE
|
||||||
|
) {
|
||||||
|
return@put
|
||||||
|
}
|
||||||
|
call.respond(
|
||||||
|
CategoryResponse(
|
||||||
|
categoryRepository.save(
|
||||||
|
Category(
|
||||||
|
title = request.title ?: category.title,
|
||||||
|
description = request.description ?: category.description,
|
||||||
|
amount = request.amount ?: category.amount,
|
||||||
|
expense = request.expense ?: category.expense,
|
||||||
|
archived = request.archived ?: category.archived
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete("/{id}") {
|
||||||
|
val session = call.principal<Session>()!!
|
||||||
|
val category = categoryRepository.findAll(ids = call.parameters.getAll("id"))
|
||||||
|
.firstOrNull()
|
||||||
|
?: run {
|
||||||
|
call.respond(HttpStatusCode.NotFound)
|
||||||
|
return@delete
|
||||||
|
}
|
||||||
|
requireBudgetWithPermission(
|
||||||
|
permissionRepository,
|
||||||
|
session.userId,
|
||||||
|
category.budgetId!!,
|
||||||
|
Permission.WRITE
|
||||||
|
) {
|
||||||
|
return@delete
|
||||||
|
}
|
||||||
|
categoryRepository.delete(category)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend inline fun PipelineContext<Unit, ApplicationCall>.requireBudgetWithPermission(
|
||||||
|
permissionRepository: PermissionRepository,
|
||||||
|
userId: String,
|
||||||
|
budgetId: String,
|
||||||
|
permission: Permission,
|
||||||
|
otherwise: () -> Unit
|
||||||
|
) {
|
||||||
|
permissionRepository.findAll(
|
||||||
|
userId = userId,
|
||||||
|
budgetIds = listOf(budgetId)
|
||||||
|
).firstOrNull {
|
||||||
|
it.permission.isAtLeast(permission)
|
||||||
|
} ?: run {
|
||||||
|
call.respond(HttpStatusCode.Forbidden, "Insufficient permissions on budget $budgetId")
|
||||||
|
otherwise()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package com.wbrawner.twigs.server
|
package com.wbrawner.twigs.server
|
||||||
|
|
||||||
import com.wbrawner.twigs.budgetRoutes
|
import com.wbrawner.twigs.budgetRoutes
|
||||||
|
import com.wbrawner.twigs.categoryRoutes
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
import io.ktor.auth.*
|
import io.ktor.auth.*
|
||||||
|
|
||||||
|
@ -10,4 +11,5 @@ fun Application.module(budgetReposi) {
|
||||||
|
|
||||||
install(Authentication)
|
install(Authentication)
|
||||||
budgetRoutes()
|
budgetRoutes()
|
||||||
|
categoryRoutes()
|
||||||
}
|
}
|
|
@ -1,171 +0,0 @@
|
||||||
package com.wbrawner.twigs.server.category
|
|
||||||
|
|
||||||
import com.wbrawner.twigs.ErrorResponse
|
|
||||||
import com.wbrawner.twigs.server.currentUser
|
|
||||||
import com.wbrawner.twigs.server.firstOfMonth
|
|
||||||
import com.wbrawner.twigs.server.permission.Permission
|
|
||||||
import com.wbrawner.twigs.server.permission.UserPermission
|
|
||||||
import com.wbrawner.twigs.server.permission.UserPermissionRepository
|
|
||||||
import com.wbrawner.twigs.server.transaction.Transaction
|
|
||||||
import com.wbrawner.twigs.server.transaction.TransactionRepository
|
|
||||||
import org.springframework.data.domain.PageRequest
|
|
||||||
import org.springframework.data.domain.Sort
|
|
||||||
import org.springframework.http.HttpStatus
|
|
||||||
import org.springframework.http.MediaType
|
|
||||||
import org.springframework.http.ResponseEntity
|
|
||||||
import org.springframework.web.bind.annotation.*
|
|
||||||
import java.util.function.Consumer
|
|
||||||
import java.util.stream.Collectors
|
|
||||||
import javax.transaction.Transactional
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(path = ["/categories"])
|
|
||||||
@Transactional
|
|
||||||
open class CategoryController(
|
|
||||||
private val categoryRepository: CategoryRepository,
|
|
||||||
private val transactionRepository: TransactionRepository,
|
|
||||||
private val userPermissionsRepository: UserPermissionRepository
|
|
||||||
) {
|
|
||||||
@GetMapping(path = [""], produces = [MediaType.APPLICATION_JSON_VALUE])
|
|
||||||
open fun getCategories(
|
|
||||||
@RequestParam(name = "budgetIds", required = false) budgetIds: List<String?>?,
|
|
||||||
@RequestParam(name = "isExpense", required = false) isExpense: Boolean?,
|
|
||||||
@RequestParam(name = "includeArchived", required = false) includeArchived: Boolean?,
|
|
||||||
@RequestParam(name = "count", required = false) count: Int?,
|
|
||||||
@RequestParam(name = "page", required = false) page: Int?,
|
|
||||||
@RequestParam(name = "false", required = false) sortBy: String?,
|
|
||||||
@RequestParam(name = "sortOrder", required = false) sortOrder: Sort.Direction?
|
|
||||||
): ResponseEntity<List<CategoryResponse>> {
|
|
||||||
val userPermissions: List<UserPermission>
|
|
||||||
userPermissions = if (budgetIds != null && !budgetIds.isEmpty()) {
|
|
||||||
userPermissionsRepository.findAllByUserAndBudget_IdIn(
|
|
||||||
currentUser,
|
|
||||||
budgetIds,
|
|
||||||
PageRequest.of(page ?: 0, count ?: 1000)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
userPermissionsRepository.findAllByUser(currentUser, null)
|
|
||||||
}
|
|
||||||
val budgets = userPermissions.stream()
|
|
||||||
.map { obj: UserPermission -> obj.budget }
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
val pageRequest = PageRequest.of(
|
|
||||||
Math.min(0, if (page != null) page - 1 else 0),
|
|
||||||
count ?: 1000,
|
|
||||||
sortOrder ?: Sort.Direction.ASC,
|
|
||||||
sortBy ?: "title"
|
|
||||||
)
|
|
||||||
val archived = if (includeArchived == null || includeArchived == false) false else null
|
|
||||||
val categories = categoryRepository.findAllByBudgetIn(budgets, isExpense, archived, pageRequest)
|
|
||||||
return ResponseEntity.ok(
|
|
||||||
categories.stream()
|
|
||||||
.map { category: Category -> CategoryResponse(category) }
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(path = ["/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
|
||||||
open fun getCategory(@PathVariable id: String?): ResponseEntity<CategoryResponse> {
|
|
||||||
val budgets = userPermissionsRepository.findAllByUser(currentUser, null)
|
|
||||||
.stream()
|
|
||||||
.map { obj: UserPermission -> obj.budget }
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
val category = categoryRepository.findByBudgetInAndId(budgets, id).orElse(null)
|
|
||||||
?: return ResponseEntity.notFound().build()
|
|
||||||
return ResponseEntity.ok(CategoryResponse(category))
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(path = ["/{id}/balance"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
|
||||||
open fun getCategoryBalance(@PathVariable id: String?): ResponseEntity<CategoryBalanceResponse> {
|
|
||||||
val budgets = userPermissionsRepository.findAllByUser(currentUser, null)
|
|
||||||
.stream()
|
|
||||||
.map { obj: UserPermission -> obj.budget }
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
val category = categoryRepository.findByBudgetInAndId(budgets, id).orElse(null)
|
|
||||||
?: return ResponseEntity.notFound().build()
|
|
||||||
val sum = transactionRepository.sumBalanceByCategoryId(category.id, firstOfMonth)
|
|
||||||
return ResponseEntity.ok(CategoryBalanceResponse(category.id, sum))
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(
|
|
||||||
path = [""],
|
|
||||||
consumes = [MediaType.APPLICATION_JSON_VALUE],
|
|
||||||
produces = [MediaType.APPLICATION_JSON_VALUE]
|
|
||||||
)
|
|
||||||
open fun newCategory(@RequestBody request: NewCategoryRequest): ResponseEntity<Any> {
|
|
||||||
val userResponse = userPermissionsRepository.findByUserAndBudget_Id(currentUser, request.budgetId)
|
|
||||||
.orElse(null) ?: return ResponseEntity.badRequest().body(ErrorResponse("Invalid budget ID"))
|
|
||||||
if (userResponse.permission.isNotAtLeast(Permission.WRITE)) {
|
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build()
|
|
||||||
}
|
|
||||||
val budget = userResponse.budget
|
|
||||||
return ResponseEntity.ok(
|
|
||||||
CategoryResponse(
|
|
||||||
categoryRepository.save(
|
|
||||||
Category(
|
|
||||||
title = request.title,
|
|
||||||
description = request.description,
|
|
||||||
amount = request.amount,
|
|
||||||
budget = budget,
|
|
||||||
expense = request.expense
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping(
|
|
||||||
path = ["/{id}"],
|
|
||||||
consumes = [MediaType.APPLICATION_JSON_VALUE],
|
|
||||||
produces = [MediaType.APPLICATION_JSON_VALUE]
|
|
||||||
)
|
|
||||||
open fun updateCategory(
|
|
||||||
@PathVariable id: String,
|
|
||||||
@RequestBody request: UpdateCategoryRequest
|
|
||||||
): ResponseEntity<CategoryResponse> {
|
|
||||||
val category = categoryRepository.findById(id).orElse(null)
|
|
||||||
?: return ResponseEntity.notFound().build()
|
|
||||||
val userPermission = userPermissionsRepository.findByUserAndBudget_Id(
|
|
||||||
currentUser,
|
|
||||||
category.budget!!.id
|
|
||||||
).orElse(null)
|
|
||||||
?: return ResponseEntity.notFound().build()
|
|
||||||
if (userPermission.permission.isNotAtLeast(Permission.WRITE)) {
|
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build()
|
|
||||||
}
|
|
||||||
if (request.title != null) {
|
|
||||||
category.title = request.title
|
|
||||||
}
|
|
||||||
if (request.description != null) {
|
|
||||||
category.description = request.description
|
|
||||||
}
|
|
||||||
if (request.amount != null) {
|
|
||||||
category.amount = request.amount
|
|
||||||
}
|
|
||||||
if (request.expense != null) {
|
|
||||||
category.expense = request.expense
|
|
||||||
}
|
|
||||||
if (request.archived != null) {
|
|
||||||
category.archived = request.archived
|
|
||||||
}
|
|
||||||
return ResponseEntity.ok(CategoryResponse(categoryRepository.save(category)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping(path = ["/{id}"], produces = [MediaType.TEXT_PLAIN_VALUE])
|
|
||||||
open fun deleteCategory(@PathVariable id: String): ResponseEntity<Void> {
|
|
||||||
val category = categoryRepository.findById(id).orElse(null) ?: return ResponseEntity.notFound().build()
|
|
||||||
val userPermission =
|
|
||||||
userPermissionsRepository.findByUserAndBudget_Id(currentUser, category.budget!!.id).orElse(null)
|
|
||||||
?: return ResponseEntity.notFound().build()
|
|
||||||
if (userPermission.permission.isNotAtLeast(Permission.WRITE)) {
|
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build()
|
|
||||||
}
|
|
||||||
transactionRepository.findAllByBudgetAndCategory(userPermission.budget, category)
|
|
||||||
.forEach(Consumer { transaction: Transaction ->
|
|
||||||
transaction.category = null
|
|
||||||
transactionRepository.save(transaction)
|
|
||||||
})
|
|
||||||
categoryRepository.delete(category)
|
|
||||||
return ResponseEntity.ok().build()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package com.wbrawner.twigs.server.category
|
|
||||||
|
|
||||||
import com.wbrawner.twigs.server.budget.Budget
|
|
||||||
import org.springframework.data.domain.Pageable
|
|
||||||
import org.springframework.data.jpa.repository.Query
|
|
||||||
import org.springframework.data.repository.PagingAndSortingRepository
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
interface CategoryRepository : PagingAndSortingRepository<Category, String> {
|
|
||||||
fun findAllByBudget(budget: Budget?, pageable: Pageable?): List<Category>
|
|
||||||
|
|
||||||
@Query("SELECT c FROM Category c where c.budget IN (:budgets) AND (:expense IS NULL OR c.expense = :expense) AND (:archived IS NULL OR c.archived = :archived)")
|
|
||||||
fun findAllByBudgetIn(
|
|
||||||
budgets: List<Budget?>?,
|
|
||||||
expense: Boolean?,
|
|
||||||
archived: Boolean?,
|
|
||||||
pageable: Pageable?
|
|
||||||
): List<Category>
|
|
||||||
|
|
||||||
fun findByBudgetInAndId(budgets: List<Budget?>?, id: String?): Optional<Category>
|
|
||||||
fun findByBudgetAndId(budget: Budget?, id: String?): Optional<Category>
|
|
||||||
fun findAllByBudgetInAndIdIn(budgets: List<Budget?>?, ids: List<String?>?, pageable: Pageable?): List<Category>
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.wbrawner.twigs.server.passwordresetrequest
|
|
||||||
|
|
||||||
import org.springframework.data.repository.PagingAndSortingRepository
|
|
||||||
|
|
||||||
interface PasswordResetRequestRepository : PagingAndSortingRepository<PasswordResetRequest, Long>
|
|
|
@ -1,15 +0,0 @@
|
||||||
package com.wbrawner.twigs.server.permission
|
|
||||||
|
|
||||||
import com.wbrawner.twigs.server.budget.Budget
|
|
||||||
import com.wbrawner.twigs.server.user.User
|
|
||||||
import org.springframework.data.domain.Pageable
|
|
||||||
import org.springframework.data.repository.PagingAndSortingRepository
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
interface UserPermissionRepository : PagingAndSortingRepository<UserPermission, UserPermissionKey> {
|
|
||||||
fun findByUserAndBudget_Id(user: User?, budgetId: String?): Optional<UserPermission>
|
|
||||||
fun findAllByUser(user: User?, pageable: Pageable?): List<UserPermission>
|
|
||||||
fun findAllByBudget(budget: Budget?, pageable: Pageable?): List<UserPermission>
|
|
||||||
fun findAllByUserAndBudget(user: User?, budget: Budget?, pageable: Pageable?): List<UserPermission>
|
|
||||||
fun findAllByUserAndBudget_IdIn(user: User?, budgetIds: List<String?>?, pageable: Pageable?): List<UserPermission>
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package com.wbrawner.twigs.server.session
|
|
||||||
|
|
||||||
import org.springframework.data.repository.PagingAndSortingRepository
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
interface UserSessionRepository : PagingAndSortingRepository<Session, String> {
|
|
||||||
fun findByUserId(userId: String?): List<Session?>?
|
|
||||||
fun findByToken(token: String?): Optional<Session?>?
|
|
||||||
fun findByUserIdAndToken(userId: String?, token: String?): Optional<Session?>?
|
|
||||||
fun deleteAllByExpirationBefore(expiration: Date?)
|
|
||||||
}
|
|
1
core/.gitignore
vendored
Normal file
1
core/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
|
@ -7,7 +7,7 @@ data class Category(
|
||||||
var title: String = "",
|
var title: String = "",
|
||||||
var description: String? = null,
|
var description: String? = null,
|
||||||
var amount: Long = 0L,
|
var amount: Long = 0L,
|
||||||
var budget: Budget? = null,
|
var budgetId: String? = null,
|
||||||
var expense: Boolean = true,
|
var expense: Boolean = true,
|
||||||
var archived: Boolean = false
|
var archived: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
|
@ -30,6 +30,10 @@ enum class Permission {
|
||||||
*/
|
*/
|
||||||
OWNER;
|
OWNER;
|
||||||
|
|
||||||
|
fun isAtLeast(wanted: Permission): Boolean {
|
||||||
|
return ordinal >= wanted.ordinal
|
||||||
|
}
|
||||||
|
|
||||||
fun isNotAtLeast(wanted: Permission): Boolean {
|
fun isNotAtLeast(wanted: Permission): Boolean {
|
||||||
return ordinal < wanted.ordinal
|
return ordinal < wanted.ordinal
|
||||||
}
|
}
|
||||||
|
|
1
storage/.gitignore
vendored
Normal file
1
storage/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.wbrawner.twigs.storage
|
||||||
|
|
||||||
|
import com.wbrawner.twigs.model.Category
|
||||||
|
|
||||||
|
interface CategoryRepository : Repository<Category> {
|
||||||
|
fun findAll(
|
||||||
|
ids: List<String>? = null,
|
||||||
|
budgetIds: List<String>? = null,
|
||||||
|
expense: Boolean? = null,
|
||||||
|
archived: Boolean? = null
|
||||||
|
): List<Category>
|
||||||
|
}
|
|
@ -3,6 +3,8 @@ package com.wbrawner.twigs.storage
|
||||||
import com.wbrawner.twigs.model.UserPermission
|
import com.wbrawner.twigs.model.UserPermission
|
||||||
|
|
||||||
interface PermissionRepository : Repository<UserPermission> {
|
interface PermissionRepository : Repository<UserPermission> {
|
||||||
fun findAllByBudgetId(budgetId: String): List<UserPermission>
|
fun findAll(
|
||||||
fun findAllByUserId(userId: String): List<UserPermission>
|
budgetIds: List<String>? = null,
|
||||||
|
userId: String? = null
|
||||||
|
): List<UserPermission>
|
||||||
}
|
}
|
Loading…
Reference in a new issue