add spaces

This commit is contained in:
xds
2025-02-17 17:58:07 +03:00
parent a5b334f6c2
commit d680345a9f
23 changed files with 1097 additions and 285 deletions

View File

@@ -0,0 +1,233 @@
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()
// }
}