233 lines
12 KiB
Kotlin
233 lines
12 KiB
Kotlin
package space.luminic.budgerapp.services
|
||
|
||
import org.bson.types.ObjectId
|
||
import org.springframework.data.domain.Sort
|
||
import org.springframework.data.domain.Sort.Direction
|
||
import org.springframework.security.core.context.ReactiveSecurityContextHolder
|
||
import org.springframework.stereotype.Service
|
||
import reactor.core.publisher.Mono
|
||
import space.luminic.budgerapp.models.Space
|
||
import space.luminic.budgerapp.models.SpaceInvite
|
||
import space.luminic.budgerapp.models.Transaction
|
||
import space.luminic.budgerapp.repos.BudgetRepo
|
||
import space.luminic.budgerapp.repos.SpaceRepo
|
||
import space.luminic.budgerapp.repos.UserRepo
|
||
import java.time.LocalDateTime
|
||
import java.util.UUID
|
||
|
||
@Service
|
||
class SpaceService(
|
||
private val spaceRepo: SpaceRepo,
|
||
private val userService: UserService,
|
||
private val budgetRepo: BudgetRepo,
|
||
private val userRepo: UserRepo
|
||
) {
|
||
|
||
fun isValidRequest(spaceId: String): Mono<Space> {
|
||
return ReactiveSecurityContextHolder.getContext()
|
||
.map { it.authentication }
|
||
.flatMap { authentication ->
|
||
val username = authentication.name
|
||
// Получаем пользователя по имени
|
||
userService.getByUsername(username)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||
.flatMap { user ->
|
||
// Получаем пространство по ID
|
||
spaceRepo.findById(spaceId)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("Space not found for id: $spaceId")))
|
||
.flatMap { space ->
|
||
// Проверяем доступ пользователя к пространству
|
||
if (space.users.none { it.id.toString() == user.id }) {
|
||
return@flatMap Mono.error<Space>(IllegalArgumentException("User does not have access to this Space"))
|
||
}
|
||
// Если проверка прошла успешно, возвращаем пространство
|
||
Mono.just(space)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
fun getSpaces(): Mono<List<Space>> {
|
||
return ReactiveSecurityContextHolder.getContext()
|
||
.map { it.authentication }
|
||
.flatMap { authentication ->
|
||
val username = authentication.name
|
||
userService.getByUsername(username)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||
.flatMapMany { user ->
|
||
spaceRepo.findByArrayElement(ObjectId(user.id!!))
|
||
}
|
||
.collectList() // Возвращаем Mono<List<Space>>
|
||
}
|
||
}
|
||
|
||
fun getSpace(spaceId: String): Mono<Space> {
|
||
return spaceRepo.findById(spaceId)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("SpaceId not found for spaceId: $spaceId")))
|
||
}
|
||
|
||
fun createSpace(space: Space): Mono<Space> {
|
||
return ReactiveSecurityContextHolder.getContext()
|
||
.map { it.authentication }
|
||
.flatMap { authentication ->
|
||
val username = authentication.name
|
||
userService.getByUsername(username)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||
.flatMap { user ->
|
||
space.owner = user
|
||
space.users.add(user)
|
||
spaceRepo.save(space)
|
||
}
|
||
}
|
||
}
|
||
|
||
fun deleteSpace(spaceId: String): Mono<Void> {
|
||
return budgetRepo.findBySpaceId(ObjectId(spaceId), Sort.by(Direction.DESC, "dateFrom"))
|
||
.flatMap { budget ->
|
||
budgetRepo.delete(budget) // Удаляем все бюджеты, связанные с этим Space
|
||
}
|
||
.then(spaceRepo.deleteById(spaceId)) // Затем удаляем сам Space
|
||
}
|
||
|
||
|
||
fun createInviteSpace(spaceId: String): Mono<SpaceInvite> {
|
||
return ReactiveSecurityContextHolder.getContext()
|
||
.map { it.authentication }
|
||
.flatMap { authentication ->
|
||
val username = authentication.name
|
||
userService.getByUsername(username)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||
.flatMap { user ->
|
||
spaceRepo.findById(spaceId)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("Space not found for id: $spaceId")))
|
||
.flatMap { space ->
|
||
if (space.users.none { it.id.toString() == user.id }) {
|
||
return@flatMap Mono.error<SpaceInvite>(IllegalArgumentException("User does not have access to this Space"))
|
||
}
|
||
|
||
val invite = SpaceInvite(
|
||
UUID.randomUUID().toString().split("-")[0],
|
||
user,
|
||
LocalDateTime.now().plusHours(1),
|
||
|
||
)
|
||
space.invites.add(invite)
|
||
|
||
// Сохраняем изменения и возвращаем созданное приглашение
|
||
spaceRepo.save(space).thenReturn(invite)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
fun acceptInvite(code: String): Mono<Space> {
|
||
return ReactiveSecurityContextHolder.getContext()
|
||
.map { it.authentication }
|
||
.flatMap { authentication ->
|
||
val username = authentication.name
|
||
userService.getByUsername(username)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||
.flatMap { user ->
|
||
spaceRepo.findSpaceByInvites(code)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("Space with invite code: $code not found")))
|
||
.flatMap { space ->
|
||
val invite = space.invites.find { it.code == code }
|
||
|
||
// Проверяем, есть ли инвайт и не истек ли он
|
||
if (invite == null || invite.activeTill.isBefore(LocalDateTime.now())) {
|
||
return@flatMap Mono.error<Space>(IllegalArgumentException("Invite is invalid or expired"))
|
||
}
|
||
|
||
// Проверяем, не является ли пользователь уже участником
|
||
if (space.users.any { it.id == user.id }) {
|
||
return@flatMap Mono.error<Space>(IllegalArgumentException("User is already a member of this Space"))
|
||
}
|
||
|
||
// Добавляем пользователя и удаляем использованный инвайт
|
||
space.users.add(user)
|
||
space.invites.remove(invite)
|
||
|
||
spaceRepo.save(space)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
fun leaveSpace(spaceId: String): Mono<Void> {
|
||
return ReactiveSecurityContextHolder.getContext()
|
||
.map { it.authentication }
|
||
.flatMap { authentication ->
|
||
val username = authentication.name
|
||
userService.getByUsername(username)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||
.flatMap { user ->
|
||
spaceRepo.findById(spaceId)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("Space not found for id: $spaceId")))
|
||
.flatMap { space ->
|
||
if (space.users.none { it.id.toString() == user.id }) {
|
||
return@flatMap Mono.error<Void>(IllegalArgumentException("User does not have access to this Space"))
|
||
}
|
||
// Удаляем пользователя из массива
|
||
space.users.removeIf { it.id == user.id }
|
||
// Сохраняем изменения
|
||
spaceRepo.save(space).then() // .then() для Mono<Void>
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
fun kickMember(spaceId: String, kickedUsername: String): Mono<Void> {
|
||
return ReactiveSecurityContextHolder.getContext()
|
||
.map { it.authentication }
|
||
.flatMap { authentication ->
|
||
val username = authentication.name
|
||
// Получаем текущего пользователя
|
||
userService.getByUsername(username)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $username")))
|
||
.flatMap { user ->
|
||
// Получаем пользователя, которого нужно исключить
|
||
userService.getByUsername(kickedUsername)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("User not found for username: $kickedUsername")))
|
||
.flatMap { kickedUser ->
|
||
// Получаем пространство
|
||
spaceRepo.findById(spaceId)
|
||
.switchIfEmpty(Mono.error(IllegalArgumentException("Space not found for id: $spaceId")))
|
||
.flatMap { space ->
|
||
// Проверяем, является ли текущий пользователь владельцем
|
||
if (space.owner?.id != user.id) {
|
||
return@flatMap Mono.error<Void>(IllegalArgumentException("Only owners allowed for this action"))
|
||
}
|
||
|
||
// Проверяем, что пользователь, которого нужно исключить, присутствует в списке пользователей
|
||
val userToKick = space.users.find { it.username == kickedUsername }
|
||
if (userToKick != null) {
|
||
// Удаляем пользователя из пространства
|
||
space.users.removeIf { it.username == kickedUsername }
|
||
// Сохраняем изменения
|
||
return@flatMap spaceRepo.save(space).then()
|
||
} else {
|
||
return@flatMap Mono.error<Void>(IllegalArgumentException("User not found in this space"))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// fun regenSpaces(): Mono<List<Space>> {
|
||
// return spaceRepo.findAll()
|
||
// .flatMap { space ->
|
||
// userService.getUsers()
|
||
// .flatMap { users ->
|
||
// if (users.isEmpty()) {
|
||
// return@flatMap Mono.error<Space>(IllegalStateException("No users found"))
|
||
// }
|
||
// val updatedSpace = space.copy(owner = users.first()) // Создаем копию (если `Space` data class)
|
||
// spaceRepo.save(updatedSpace)
|
||
// }
|
||
// }
|
||
// .collectList()
|
||
// }
|
||
|
||
} |