diff --git a/app/src/main/frontend/components/administration/SsoManagement.tsx b/app/src/main/frontend/components/administration/SsoManagement.tsx
index 78568f2..b77be72 100644
--- a/app/src/main/frontend/components/administration/SsoManagement.tsx
+++ b/app/src/main/frontend/components/administration/SsoManagement.tsx
@@ -3,8 +3,8 @@ import withConfigPage from "Frontend/components/administration/withConfigPage";
import * as Yup from 'yup';
import ConfigFormField from "Frontend/components/administration/ConfigFormField";
import Section from "Frontend/components/general/Section";
-import {addToast, Button} from "@heroui/react";
-import {MagicWand} from "@phosphor-icons/react";
+import {addToast, Button, Checkbox, CheckboxGroup, Tooltip} from "@heroui/react";
+import {MagicWand, Warning} from "@phosphor-icons/react";
function SsoManagementLayout({getConfig, formik, setSaveMessage}: any) {
@@ -50,8 +50,21 @@ function SsoManagementLayout({getConfig, formik, setSaveMessage}: any) {
-
+
+
+
+ Automatically create new users after registration
+
+
+
+
+
+
+ {/*TODO: enable when the issues with unregistered SSO users are sorted
+
+
+ */}
diff --git a/app/src/main/kotlin/org/gameyfin/app/core/security/SsoAuthenticationSuccessHandler.kt b/app/src/main/kotlin/org/gameyfin/app/core/security/SsoAuthenticationSuccessHandler.kt
index 30784d4..15cb458 100644
--- a/app/src/main/kotlin/org/gameyfin/app/core/security/SsoAuthenticationSuccessHandler.kt
+++ b/app/src/main/kotlin/org/gameyfin/app/core/security/SsoAuthenticationSuccessHandler.kt
@@ -1,12 +1,12 @@
package org.gameyfin.app.core.security
-import org.gameyfin.app.config.ConfigService
-import org.gameyfin.app.users.UserService
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.gameyfin.app.config.ConfigProperties
+import org.gameyfin.app.config.ConfigService
import org.gameyfin.app.config.MatchUsersBy
import org.gameyfin.app.users.RoleService
+import org.gameyfin.app.users.UserService
import org.gameyfin.app.users.entities.User
import org.springframework.security.core.Authentication
import org.springframework.security.oauth2.core.oidc.user.OidcUser
@@ -42,11 +42,13 @@ class SsoAuthenticationSuccessHandler(
// User could not be found in the database
if (matchedUser == null) {
+ // TODO: User registration is currently forced, but this should be configurable.
+ // However, this causes conflict with user preferences and game entities (since both reference the user entity)
// Check if new user registration is enabled
- if (config.get(ConfigProperties.SSO.OIDC.AutoRegisterNewUsers) == false) {
- response.sendRedirect("/")
- return
- }
+ //if (config.get(ConfigProperties.SSO.OIDC.AutoRegisterNewUsers) == false) {
+ // response.sendRedirect("/")
+ // return
+ //
// Register as new user
matchedUser = User(oidcUser)
diff --git a/app/src/main/kotlin/org/gameyfin/app/games/GameService.kt b/app/src/main/kotlin/org/gameyfin/app/games/GameService.kt
index c503f36..e496747 100644
--- a/app/src/main/kotlin/org/gameyfin/app/games/GameService.kt
+++ b/app/src/main/kotlin/org/gameyfin/app/games/GameService.kt
@@ -26,6 +26,7 @@ import org.gameyfin.pluginapi.gamemetadata.*
import org.springframework.data.repository.findByIdOrNull
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
+import org.springframework.security.oauth2.core.oidc.user.OidcUser
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import reactor.core.publisher.Flux
@@ -125,8 +126,12 @@ class GameService(
val existingGame = gameRepository.findByIdOrNull(gameUpdateDto.id)
?: throw IllegalArgumentException("Game with ID $gameUpdateDto.id not found")
- val userDetails = SecurityContextHolder.getContext().authentication.principal as UserDetails
- val user = userService.getByUsernameNonNull(userDetails.username)
+ val userDetails = SecurityContextHolder.getContext().authentication.principal
+ val user = when (userDetails) {
+ is UserDetails -> userService.getByUsernameNonNull(userDetails.username)
+ is OidcUser -> userService.getByUsernameNonNull(userDetails.preferredUsername)
+ else -> throw IllegalStateException("Unkown user type: ${userDetails::class.java.name}")
+ }
// Update only non-null fields
gameUpdateDto.title?.let {
diff --git a/app/src/main/kotlin/org/gameyfin/app/users/UserEndpoint.kt b/app/src/main/kotlin/org/gameyfin/app/users/UserEndpoint.kt
index 15853c0..7b0411e 100644
--- a/app/src/main/kotlin/org/gameyfin/app/users/UserEndpoint.kt
+++ b/app/src/main/kotlin/org/gameyfin/app/users/UserEndpoint.kt
@@ -1,12 +1,12 @@
package org.gameyfin.app.users
import com.vaadin.hilla.Endpoint
-import org.gameyfin.app.users.dto.UserUpdateDto
-import org.gameyfin.app.users.enums.RoleAssignmentResult
import jakarta.annotation.security.PermitAll
import jakarta.annotation.security.RolesAllowed
import org.gameyfin.app.core.Role
import org.gameyfin.app.users.dto.UserInfoDto
+import org.gameyfin.app.users.dto.UserUpdateDto
+import org.gameyfin.app.users.enums.RoleAssignmentResult
import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContextHolder
@@ -23,8 +23,7 @@ class UserEndpoint(
@PermitAll
fun getUserInfo(): UserInfoDto {
- val auth: Authentication = SecurityContextHolder.getContext().authentication
- return userService.getUserInfo(auth)
+ return userService.getUserInfo()
}
@PermitAll
diff --git a/app/src/main/kotlin/org/gameyfin/app/users/UserService.kt b/app/src/main/kotlin/org/gameyfin/app/users/UserService.kt
index 31a76c4..8ecc257 100644
--- a/app/src/main/kotlin/org/gameyfin/app/users/UserService.kt
+++ b/app/src/main/kotlin/org/gameyfin/app/users/UserService.kt
@@ -1,25 +1,20 @@
package org.gameyfin.app.users
+import io.github.oshai.kotlinlogging.KotlinLogging
+import org.gameyfin.app.config.ConfigProperties
import org.gameyfin.app.config.ConfigService
+import org.gameyfin.app.core.Role
+import org.gameyfin.app.core.Utils
+import org.gameyfin.app.core.events.*
import org.gameyfin.app.games.entities.Image
+import org.gameyfin.app.media.ImageService
+import org.gameyfin.app.users.dto.UserInfoDto
+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.persistence.UserRepository
-import io.github.oshai.kotlinlogging.KotlinLogging
-import org.gameyfin.app.config.ConfigProperties
-import org.gameyfin.app.core.Role
-import org.gameyfin.app.core.Utils
-import org.gameyfin.app.core.events.AccountDeletedEvent
-import org.gameyfin.app.core.events.AccountStatusChangedEvent
-import org.gameyfin.app.core.events.EmailNeedsConfirmationEvent
-import org.gameyfin.app.core.events.RegistrationAttemptWithExistingEmailEvent
-import org.gameyfin.app.core.events.UserRegistrationWaitingForApprovalEvent
-import org.gameyfin.app.media.ImageService
-import org.gameyfin.app.users.dto.UserInfoDto
-import org.gameyfin.app.users.dto.UserRegistrationDto
import org.springframework.context.ApplicationEventPublisher
-import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
@@ -66,7 +61,8 @@ class UserService(
fun existsByUsername(username: String): Boolean = userRepository.existsByUsername(username)
fun existsByEmail(email: String): Boolean = userRepository.existsByEmail(email)
- fun findByOidcProviderId(oidcProviderId: String): org.gameyfin.app.users.entities.User? = userRepository.findByOidcProviderId(oidcProviderId)
+ fun findByOidcProviderId(oidcProviderId: String): org.gameyfin.app.users.entities.User? =
+ userRepository.findByOidcProviderId(oidcProviderId)
fun getAllUsers(): List {
return userRepository.findAll().map { u -> toUserInfo(u) }
@@ -84,7 +80,8 @@ class UserService(
return userRepository.findByUsername(username) ?: throw UsernameNotFoundException("Unknown user '$username'")
}
- fun getUserInfo(auth: Authentication): UserInfoDto {
+ fun getUserInfo(): UserInfoDto {
+ val auth = SecurityContextHolder.getContext().authentication
val principal = auth.principal
if (principal is OidcUser) {
@@ -99,6 +96,15 @@ class UserService(
return toUserInfo(user)
}
+ fun getCurrentUser(): org.gameyfin.app.users.entities.User {
+ val auth = SecurityContextHolder.getContext().authentication
+ if (auth.principal is OidcUser) {
+ return userRepository.findByOidcProviderId((auth.principal as OidcUser).subject)
+ ?: throw UsernameNotFoundException("OIDC user not found")
+ }
+ return getByUsernameNonNull(auth.name)
+ }
+
fun getAvatar(username: String): Image? {
val user = getByUsernameNonNull(username)
return user.avatar
@@ -174,7 +180,10 @@ class UserService(
}
}
- fun registerUserFromInvitation(registration: UserRegistrationDto, email: String): org.gameyfin.app.users.entities.User {
+ fun registerUserFromInvitation(
+ registration: UserRegistrationDto,
+ email: String
+ ): org.gameyfin.app.users.entities.User {
val user = org.gameyfin.app.users.entities.User(
username = registration.username,
password = passwordEncoder.encode(registration.password),