BE implementation of request system

This commit is contained in:
grimsi
2025-09-01 13:01:17 +02:00
parent 6b81d3904c
commit 0f2b45f5e9
29 changed files with 233 additions and 87 deletions
+1 -1
View File
@@ -265,4 +265,4 @@
"disableUsageStatistics": true,
"hash": "962eccc3fa0735d5234901be4f9e384096113c45bec22564a53688096d62aef4"
}
}
}
@@ -1,10 +1,10 @@
package org.gameyfin.app.core.filesystem
import org.gameyfin.app.config.ConfigService
import io.github.oshai.kotlinlogging.KotlinLogging
import org.apache.commons.io.FilenameUtils
import org.gameyfin.app.config.ConfigProperties
import org.gameyfin.app.libraries.Library
import org.gameyfin.app.config.ConfigService
import org.gameyfin.app.libraries.entities.Library
import org.springframework.stereotype.Service
import java.io.File
import java.nio.file.FileSystems
@@ -22,7 +22,7 @@ import org.gameyfin.app.games.dto.*
import org.gameyfin.app.games.entities.*
import org.gameyfin.app.games.extensions.toDtos
import org.gameyfin.app.games.repositories.GameRepository
import org.gameyfin.app.libraries.Library
import org.gameyfin.app.libraries.entities.Library
import org.gameyfin.app.media.ImageService
import org.gameyfin.app.users.UserService
import org.gameyfin.pluginapi.gamemetadata.*
@@ -1,7 +1,7 @@
package org.gameyfin.app.games.entities
import jakarta.persistence.*
import org.gameyfin.app.libraries.Library
import org.gameyfin.app.libraries.entities.Library
import org.gameyfin.pluginapi.gamemetadata.GameFeature
import org.gameyfin.pluginapi.gamemetadata.Genre
import org.gameyfin.pluginapi.gamemetadata.PlayerPerspective
@@ -12,19 +12,19 @@ import org.gameyfin.app.games.extensions.toUserDto
class GameEntityListener {
@PostPersist
fun created(game: Game) {
GameService.Companion.emitUser(GameUserEvent.Created(game.toUserDto()))
GameService.Companion.emitAdmin(GameAdminEvent.Created(game.toAdminDto()))
GameService.emitUser(GameUserEvent.Created(game.toUserDto()))
GameService.emitAdmin(GameAdminEvent.Created(game.toAdminDto()))
}
@PostUpdate
fun updated(game: Game) {
GameService.Companion.emitUser(GameUserEvent.Updated(game.toUserDto()))
GameService.Companion.emitAdmin(GameAdminEvent.Updated(game.toAdminDto()))
GameService.emitUser(GameUserEvent.Updated(game.toUserDto()))
GameService.emitAdmin(GameAdminEvent.Updated(game.toAdminDto()))
}
@PostRemove
fun deleted(game: Game) {
GameService.Companion.emitUser(GameUserEvent.Deleted(game.id!!))
GameService.Companion.emitAdmin(GameAdminEvent.Deleted(game.id!!))
GameService.emitUser(GameUserEvent.Deleted(game.id!!))
GameService.emitAdmin(GameAdminEvent.Deleted(game.id!!))
}
}
@@ -2,6 +2,7 @@ package org.gameyfin.app.libraries
import org.gameyfin.app.games.GameService
import org.gameyfin.app.games.entities.Game
import org.gameyfin.app.libraries.entities.Library
import org.springframework.stereotype.Service
import java.time.Instant
@@ -1,5 +1,6 @@
package org.gameyfin.app.libraries
import org.gameyfin.app.libraries.entities.Library
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
@@ -4,9 +4,8 @@ import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.core.filesystem.FilesystemService
import org.gameyfin.app.games.GameService
import org.gameyfin.app.games.entities.Game
import org.gameyfin.app.libraries.dto.LibraryScanProgress
import org.gameyfin.app.libraries.dto.LibraryScanStatus
import org.gameyfin.app.libraries.dto.LibraryScanStep
import org.gameyfin.app.libraries.dto.*
import org.gameyfin.app.libraries.entities.Library
import org.gameyfin.app.libraries.enums.ScanType
import org.gameyfin.app.libraries.scan.*
import org.gameyfin.app.media.ImageService
@@ -3,6 +3,8 @@ package org.gameyfin.app.libraries
import com.vaadin.hilla.exception.EndpointException
import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.libraries.dto.*
import org.gameyfin.app.libraries.entities.DirectoryMapping
import org.gameyfin.app.libraries.entities.Library
import org.gameyfin.app.libraries.enums.ScanType
import org.gameyfin.app.libraries.extensions.toDtos
import org.springframework.data.repository.findByIdOrNull
@@ -1,6 +1,5 @@
package org.gameyfin.app.libraries.dto
import org.gameyfin.app.libraries.LibraryScanResult
import org.gameyfin.app.libraries.enums.ScanType
import java.time.Instant
import java.util.*
@@ -1,4 +1,4 @@
package org.gameyfin.app.libraries
package org.gameyfin.app.libraries.dto
interface LibraryScanResult {
/**
@@ -1,4 +1,4 @@
package org.gameyfin.app.libraries
package org.gameyfin.app.libraries.entities
import jakarta.persistence.*
@@ -1,8 +1,7 @@
package org.gameyfin.app.libraries
package org.gameyfin.app.libraries.entities
import org.gameyfin.app.games.entities.Game
import jakarta.persistence.*
import org.gameyfin.app.games.entities.LibraryEntityListener
import org.gameyfin.app.games.entities.Game
import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp
import java.time.Instant
@@ -1,9 +1,8 @@
package org.gameyfin.app.games.entities
package org.gameyfin.app.libraries.entities
import jakarta.persistence.PostPersist
import jakarta.persistence.PostRemove
import jakarta.persistence.PostUpdate
import org.gameyfin.app.libraries.Library
import org.gameyfin.app.libraries.LibraryService
import org.gameyfin.app.libraries.dto.LibraryAdminEvent
import org.gameyfin.app.libraries.dto.LibraryUserEvent
@@ -1,8 +1,8 @@
package org.gameyfin.app.libraries.extensions
import org.gameyfin.app.core.security.isCurrentUserAdmin
import org.gameyfin.app.libraries.Library
import org.gameyfin.app.libraries.dto.*
import org.gameyfin.app.libraries.entities.Library
fun Library.toDto(): LibraryDto {
@@ -0,0 +1,47 @@
package org.gameyfin.app.requests
import com.vaadin.flow.server.auth.AnonymousAllowed
import com.vaadin.hilla.Endpoint
import jakarta.annotation.security.PermitAll
import jakarta.annotation.security.RolesAllowed
import org.gameyfin.app.core.Role
import org.gameyfin.app.core.annotations.DynamicPublicAccess
import org.gameyfin.app.requests.dto.GameRequestCreationDto
import org.gameyfin.app.requests.dto.GameRequestEvent
import org.gameyfin.app.requests.status.GameRequestStatus
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
@Endpoint
@Service
@DynamicPublicAccess
@AnonymousAllowed
class GameRequestEndpoint(
private val gameRequestService: GameRequestService
) {
fun subscribe(): Flux<List<GameRequestEvent>> {
return GameRequestService.subscribe()
}
fun getAll() = gameRequestService.getAll()
fun create(gameRequest: GameRequestCreationDto) {
gameRequestService.createRequest(gameRequest)
}
@PermitAll
fun toggleVote(gameRequestId: Long) {
gameRequestService.toggleRequestVote(gameRequestId)
}
@RolesAllowed(Role.Names.ADMIN)
fun changeStatus(gameRequestId: Long, newStatus: GameRequestStatus) {
gameRequestService.changeRequestStatus(gameRequestId, newStatus)
}
@RolesAllowed(Role.Names.ADMIN)
fun delete(gameRequestId: Long) {
gameRequestService.deleteRequest(gameRequestId)
}
}
@@ -1,5 +1,6 @@
package org.gameyfin.app.requests
import org.gameyfin.app.requests.entities.GameRequest
import org.springframework.data.jpa.repository.JpaRepository
interface GameRequestRepository : JpaRepository<GameRequest, Long>
@@ -2,8 +2,11 @@ package org.gameyfin.app.requests
import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.core.security.getCurrentAuth
import org.gameyfin.app.games.dto.GameUserEvent
import org.gameyfin.app.requests.dto.GameRequestCreationDto
import org.gameyfin.app.requests.dto.GameRequestDto
import org.gameyfin.app.requests.dto.GameRequestEvent
import org.gameyfin.app.requests.entities.GameRequest
import org.gameyfin.app.requests.extensions.toDtos
import org.gameyfin.app.requests.status.GameRequestStatus
import org.gameyfin.app.users.UserService
import org.springframework.stereotype.Service
@@ -22,9 +25,9 @@ class GameRequestService(
private val log = KotlinLogging.logger {}
/* Websockets */
private val gameRequestEvents = Sinks.many().multicast().onBackpressureBuffer<GameUserEvent>(1024, false)
private val gameRequestEvents = Sinks.many().multicast().onBackpressureBuffer<GameRequestEvent>(1024, false)
fun subscribe(): Flux<List<GameUserEvent>> {
fun subscribe(): Flux<List<GameRequestEvent>> {
log.debug { "New user subscription for gameRequestEvents" }
return gameRequestEvents.asFlux()
.buffer(100.milliseconds.toJavaDuration())
@@ -36,11 +39,16 @@ class GameRequestService(
}
}
fun emit(event: GameUserEvent) {
fun emit(event: GameRequestEvent) {
gameRequestEvents.tryEmitNext(event)
}
}
fun getAll(): List<GameRequestDto> {
val entities = gameRequestRepository.findAll()
return entities.toDtos()
}
fun createRequest(gameRequest: GameRequestCreationDto) {
val currentUser = userService.getByUsername(getCurrentAuth().name)
@@ -54,4 +62,36 @@ class GameRequestService(
gameRequestRepository.save(gameRequest)
}
fun deleteRequest(id: Long) {
val gameRequest = gameRequestRepository.findById(id)
.orElseThrow { NoSuchElementException("No game request found with id $id") }
gameRequestRepository.delete(gameRequest)
}
fun changeRequestStatus(id: Long, status: GameRequestStatus) {
val gameRequest = gameRequestRepository.findById(id)
.orElseThrow { NoSuchElementException("No game request found with id $id") }
gameRequest.status = status
gameRequestRepository.save(gameRequest)
}
fun toggleRequestVote(id: Long) {
val currentUser =
userService.getByUsername(getCurrentAuth().name) ?: throw IllegalStateException("Current user not found")
val gameRequest = gameRequestRepository.findById(id)
.orElseThrow { NoSuchElementException("No game request found with id $id") }
if (gameRequest.requester?.id == currentUser.id) {
throw IllegalStateException("You cannot vote for your own request")
}
if (gameRequest.voters.contains(currentUser)) {
gameRequest.voters.remove(currentUser)
} else {
gameRequest.voters.add(currentUser)
}
gameRequestRepository.save(gameRequest)
}
}
@@ -1,13 +1,18 @@
package org.gameyfin.app.requests.dto
import org.gameyfin.app.requests.entities.ExternalProviderIds
import org.gameyfin.app.requests.status.GameRequestStatus
import org.gameyfin.app.users.dto.UserInfoAdminDto
import org.gameyfin.app.users.dto.UserInfoDto
import java.time.Instant
class GameRequestDto(
val id: Long,
val title: String,
val release: Instant,
val externalProviderIds: ExternalProviderIds,
val status: GameRequestStatus,
val requester: UserInfoAdminDto
val requester: UserInfoDto?,
val voters: List<UserInfoDto>,
val createdAt: Instant?,
val updatedAt: Instant?
)
@@ -1,42 +1,45 @@
package org.gameyfin.app.requests
package org.gameyfin.app.requests.entities
import jakarta.persistence.*
import org.gameyfin.app.requests.status.GameRequestStatus
import org.gameyfin.app.users.entities.User
import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.time.Instant
typealias ExternalProviderIds = Map<String, String>
@Entity
@EntityListeners(GameRequestEntityListener::class, AuditingEntityListener::class)
class GameRequest(
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: Long? = null,
@CreationTimestamp
@Column(nullable = false, updatable = false)
var createdAt: Instant? = null,
@UpdateTimestamp
@Column(nullable = false)
var updatedAt: Instant? = null,
@Column(nullable = false)
val title: String,
@Column(nullable = false)
val release: Instant,
@ElementCollection
val externalProviderIds: ExternalProviderIds,
@Column(nullable = false)
var status: GameRequestStatus,
@ManyToOne(fetch = FetchType.EAGER)
var requester: User? = null,
@OneToMany
var voters: MutableList<User> = mutableListOf(),
@ElementCollection
val externalProviderIds: ExternalProviderIds
@CreationTimestamp
@Column(nullable = false, updatable = false)
var createdAt: Instant? = null,
@UpdateTimestamp
@Column(nullable = false)
var updatedAt: Instant? = null
)
@@ -0,0 +1,25 @@
package org.gameyfin.app.requests.entities
import jakarta.persistence.PostPersist
import jakarta.persistence.PostRemove
import jakarta.persistence.PostUpdate
import org.gameyfin.app.requests.GameRequestService
import org.gameyfin.app.requests.dto.GameRequestEvent
import org.gameyfin.app.requests.extensions.toDto
class GameRequestEntityListener {
@PostPersist
fun created(gameRequest: GameRequest) {
GameRequestService.emit(GameRequestEvent.Created(gameRequest.toDto()))
}
@PostUpdate
fun updated(gameRequest: GameRequest) {
GameRequestService.emit(GameRequestEvent.Updated(gameRequest.toDto()))
}
@PostRemove
fun deleted(gameRequest: GameRequest) {
GameRequestService.emit(GameRequestEvent.Deleted(gameRequest.id!!))
}
}
@@ -1,7 +1,8 @@
package org.gameyfin.app.requests.extensions
import org.gameyfin.app.requests.GameRequest
import org.gameyfin.app.requests.dto.GameRequestDto
import org.gameyfin.app.requests.entities.GameRequest
import org.gameyfin.app.users.extensions.toUserInfoDto
fun GameRequest.toDto(): GameRequestDto {
return GameRequestDto(
@@ -10,6 +11,13 @@ fun GameRequest.toDto(): GameRequestDto {
release = this.release,
externalProviderIds = this.externalProviderIds,
status = this.status,
requester = this.requester.toDto()
requester = this.requester?.toUserInfoDto(),
voters = this.voters.map { it.toUserInfoDto() },
createdAt = this.createdAt,
updatedAt = this.updatedAt
)
}
fun Collection<GameRequest>.toDtos(): List<GameRequestDto> {
return this.map { it.toDto() }
}
@@ -3,7 +3,7 @@ package org.gameyfin.app.setup
import com.vaadin.flow.server.auth.AnonymousAllowed
import com.vaadin.hilla.Endpoint
import com.vaadin.hilla.exception.EndpointException
import org.gameyfin.app.users.dto.UserInfoAdminDto
import org.gameyfin.app.users.dto.ExtendedUserInfoDto
import org.gameyfin.app.users.dto.UserRegistrationDto
@Endpoint
@@ -16,7 +16,7 @@ class SetupEndpoint(
}
@AnonymousAllowed
fun registerSuperAdmin(superAdminRegistration: UserRegistrationDto): UserInfoAdminDto {
fun registerSuperAdmin(superAdminRegistration: UserRegistrationDto): ExtendedUserInfoDto {
if (setupService.isSetupCompleted()) throw EndpointException("Setup already completed")
return setupService.createInitialAdminUser(superAdminRegistration)
}
@@ -3,9 +3,10 @@ package org.gameyfin.app.setup
import org.gameyfin.app.core.Role
import org.gameyfin.app.users.RoleService
import org.gameyfin.app.users.UserService
import org.gameyfin.app.users.dto.UserInfoAdminDto
import org.gameyfin.app.users.dto.ExtendedUserInfoDto
import org.gameyfin.app.users.dto.UserRegistrationDto
import org.gameyfin.app.users.entities.User
import org.gameyfin.app.users.extensions.toExtendedUserInfoDto
import org.springframework.stereotype.Service
@Service
@@ -26,7 +27,7 @@ class SetupService(
/**
* Creates the initial user with Super-Admin permissions
*/
fun createInitialAdminUser(registration: UserRegistrationDto): UserInfoAdminDto {
fun createInitialAdminUser(registration: UserRegistrationDto): ExtendedUserInfoDto {
val superAdmin = User(
username = registration.username,
password = registration.password,
@@ -36,6 +37,6 @@ class SetupService(
)
val user = userService.registerOrUpdateUser(superAdmin)
return userService.toUserInfo(user)
return user.toExtendedUserInfoDto()
}
}
@@ -6,7 +6,7 @@ import jakarta.annotation.security.PermitAll
import jakarta.annotation.security.RolesAllowed
import org.gameyfin.app.core.Role
import org.gameyfin.app.core.security.getCurrentAuth
import org.gameyfin.app.users.dto.UserInfoAdminDto
import org.gameyfin.app.users.dto.ExtendedUserInfoDto
import org.gameyfin.app.users.dto.UserUpdateDto
import org.gameyfin.app.users.enums.RoleAssignmentResult
import org.springframework.security.core.Authentication
@@ -18,7 +18,7 @@ class UserEndpoint(
private val roleService: RoleService
) {
@AnonymousAllowed
fun getUserInfo(): UserInfoAdminDto? {
fun getUserInfo(): ExtendedUserInfoDto? {
val auth = getCurrentAuth()
if (!auth.isAuthenticated || auth.principal == "anonymousUser") return null
return userService.getUserInfo()
@@ -36,7 +36,7 @@ class UserEndpoint(
}
@RolesAllowed(Role.Names.ADMIN)
fun getAllUsers(): List<UserInfoAdminDto> {
fun getAllUsers(): List<ExtendedUserInfoDto> {
return userService.getAllUsers()
}
@@ -9,15 +9,15 @@ import org.gameyfin.app.core.events.*
import org.gameyfin.app.core.security.getCurrentAuth
import org.gameyfin.app.games.entities.Image
import org.gameyfin.app.media.ImageService
import org.gameyfin.app.users.dto.UserInfoAdminDto
import org.gameyfin.app.users.dto.ExtendedUserInfoDto
import org.gameyfin.app.users.dto.UserRegistrationDto
import org.gameyfin.app.users.dto.UserUpdateDto
import org.gameyfin.app.users.emailconfirmation.EmailConfirmationService
import org.gameyfin.app.users.enums.RoleAssignmentResult
import org.gameyfin.app.users.extensions.toAuthorities
import org.gameyfin.app.users.extensions.toExtendedUserInfoDto
import org.gameyfin.app.users.persistence.UserRepository
import org.springframework.context.ApplicationEventPublisher
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
@@ -56,7 +56,7 @@ class UserService(
true,
true,
true,
toAuthorities(user.roles)
user.roles.toAuthorities()
)
}
@@ -67,7 +67,7 @@ class UserService(
true,
true,
true,
toAuthorities(user.roles)
user.roles.toAuthorities()
)
}
@@ -77,8 +77,8 @@ class UserService(
fun findByOidcProviderId(oidcProviderId: String): org.gameyfin.app.users.entities.User? =
userRepository.findByOidcProviderId(oidcProviderId)
fun getAllUsers(): List<UserInfoAdminDto> {
return userRepository.findAll().map { u -> toUserInfo(u) }
fun getAllUsers(): List<ExtendedUserInfoDto> {
return userRepository.findAll().map { it.toExtendedUserInfoDto() }
}
fun getByEmail(email: String): org.gameyfin.app.users.entities.User? {
@@ -93,20 +93,20 @@ class UserService(
return userRepository.findByUsername(username) ?: throw UsernameNotFoundException("Unknown user '$username'")
}
fun getUserInfo(): UserInfoAdminDto {
fun getUserInfo(): ExtendedUserInfoDto {
val auth = getCurrentAuth()
val principal = auth.principal
if (principal is OidcUser) {
val oidcUser = org.gameyfin.app.users.entities.User(principal)
val userInfoDto = toUserInfo(oidcUser)
val userInfoDto = oidcUser.toExtendedUserInfoDto()
userInfoDto.roles = roleService.extractGrantedAuthorities(principal.authorities)
.mapNotNull { Role.Companion.safeValueOf(it.authority) }
.mapNotNull { Role.safeValueOf(it.authority) }
return userInfoDto
}
val user = getByUsernameNonNull(auth.name)
return toUserInfo(user)
return user.toExtendedUserInfoDto()
}
fun getAvatar(username: String): Image? {
@@ -158,7 +158,7 @@ class UserService(
RegistrationAttemptWithExistingEmailEvent(
this,
it,
Utils.Companion.getBaseUrl()
Utils.getBaseUrl()
)
)
return
@@ -179,12 +179,12 @@ class UserService(
if (adminNeedsToApprove) {
eventPublisher.publishEvent(UserRegistrationWaitingForApprovalEvent(this, user))
} else {
eventPublisher.publishEvent(AccountStatusChangedEvent(this, user, Utils.Companion.getBaseUrl()))
eventPublisher.publishEvent(AccountStatusChangedEvent(this, user, Utils.getBaseUrl()))
}
if (!user.emailConfirmed) {
val token = emailConfirmationService.generate(user)
eventPublisher.publishEvent(EmailNeedsConfirmationEvent(this, token, Utils.Companion.getBaseUrl()))
eventPublisher.publishEvent(EmailNeedsConfirmationEvent(this, token, Utils.getBaseUrl()))
}
}
@@ -222,7 +222,7 @@ class UserService(
user.email = it
user.emailConfirmed = false
val token = emailConfirmationService.generate(user)
eventPublisher.publishEvent(EmailNeedsConfirmationEvent(this, token, Utils.Companion.getBaseUrl()))
eventPublisher.publishEvent(EmailNeedsConfirmationEvent(this, token, Utils.getBaseUrl()))
}
userRepository.save(user)
@@ -246,7 +246,7 @@ class UserService(
return RoleAssignmentResult.TARGET_POWER_LEVEL_TOO_HIGH
}
val newAssignedRoles = roleNames.mapNotNull { r -> Role.Companion.safeValueOf(r) }
val newAssignedRoles = roleNames.mapNotNull { r -> Role.safeValueOf(r) }
val newAssignedRolesLevel = roleService.getHighestRole(newAssignedRoles).powerLevel
val currentUserLevel = roleService.getHighestRoleFromAuthorities(currentUser.authorities).powerLevel
@@ -276,29 +276,12 @@ class UserService(
val user = getByUsernameNonNull(username)
user.enabled = enabled
userRepository.save(user)
eventPublisher.publishEvent(AccountStatusChangedEvent(this, user, Utils.Companion.getBaseUrl()))
eventPublisher.publishEvent(AccountStatusChangedEvent(this, user, Utils.getBaseUrl()))
}
fun deleteUser(username: String) {
val user = getByUsernameNonNull(username)
userRepository.delete(user)
eventPublisher.publishEvent(AccountDeletedEvent(this, user, Utils.Companion.getBaseUrl()))
}
fun toUserInfo(user: org.gameyfin.app.users.entities.User): UserInfoAdminDto {
return UserInfoAdminDto(
username = user.username,
email = user.email,
emailConfirmed = user.emailConfirmed,
enabled = user.enabled,
hasAvatar = user.avatar != null,
avatarId = user.avatar?.id,
managedBySso = user.oidcProviderId != null,
roles = user.roles
)
}
private fun toAuthorities(roles: Collection<Role>): List<GrantedAuthority> {
return roles.map { r -> SimpleGrantedAuthority(r.roleName) }
eventPublisher.publishEvent(AccountDeletedEvent(this, user, Utils.getBaseUrl()))
}
}
@@ -2,7 +2,7 @@ package org.gameyfin.app.users.dto
import org.gameyfin.app.core.Role
data class UserInfoAdminDto(
data class ExtendedUserInfoDto(
val username: String,
val managedBySso: Boolean,
val email: String,
@@ -1,6 +1,6 @@
package org.gameyfin.app.users.dto
data class UserInfoUserDto(
data class UserInfoDto(
val username: String,
val hasAvatar: Boolean,
val avatarId: Long? = null,
@@ -0,0 +1,33 @@
package org.gameyfin.app.users.extensions
import org.gameyfin.app.core.Role
import org.gameyfin.app.users.dto.ExtendedUserInfoDto
import org.gameyfin.app.users.dto.UserInfoDto
import org.gameyfin.app.users.entities.User
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
fun User.toUserInfoDto(): UserInfoDto {
return UserInfoDto(
username = this.username,
hasAvatar = this.avatar != null,
avatarId = this.avatar?.id
)
}
fun User.toExtendedUserInfoDto(): ExtendedUserInfoDto {
return ExtendedUserInfoDto(
username = this.username,
email = this.email,
emailConfirmed = this.emailConfirmed,
enabled = this.enabled,
hasAvatar = this.avatar != null,
avatarId = this.avatar?.id,
managedBySso = this.oidcProviderId != null,
roles = this.roles
)
}
fun Collection<Role>.toAuthorities(): List<GrantedAuthority> {
return this.map { r -> SimpleGrantedAuthority(r.roleName) }
}