From 71aab506d5180cafcb6b858cdedd750cae2751e5 Mon Sep 17 00:00:00 2001 From: grimsi <9295182+grimsi@users.noreply.github.com> Date: Fri, 27 Sep 2024 17:51:18 +0200 Subject: [PATCH] Minor bugfixes in setup process Improved UX with small hints --- .../administration/ProfileManagement.tsx | 22 +++++++++++++++---- src/main/frontend/views/SetupView.tsx | 16 +------------- .../de/grimsi/gameyfin/setup/SetupEndpoint.kt | 19 ++-------------- .../de/grimsi/gameyfin/setup/SetupService.kt | 15 +++++++++++-- .../gameyfin/shared/token/TokenService.kt | 7 ------ .../de/grimsi/gameyfin/users/UserService.kt | 6 ++--- .../users/registration/InvitationService.kt | 6 ++++- 7 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/main/frontend/components/administration/ProfileManagement.tsx b/src/main/frontend/components/administration/ProfileManagement.tsx index d77a363..7645d3c 100644 --- a/src/main/frontend/components/administration/ProfileManagement.tsx +++ b/src/main/frontend/components/administration/ProfileManagement.tsx @@ -7,16 +7,21 @@ import React, {useEffect, useState} from "react"; import {useAuth} from "Frontend/util/auth"; import * as Yup from "yup"; import UserUpdateDto from "Frontend/generated/de/grimsi/gameyfin/users/dto/UserUpdateDto"; -import {EmailConfirmationEndpoint, UserEndpoint} from "Frontend/generated/endpoints"; +import {EmailConfirmationEndpoint, MessageEndpoint, UserEndpoint} from "Frontend/generated/endpoints"; import {SmallInfoField} from "Frontend/components/general/SmallInfoField"; import {toast} from "sonner"; import {removeAvatar, uploadAvatar} from "Frontend/endpoints/AvatarEndpoint"; import Avatar from "Frontend/components/general/Avatar"; export default function ProfileManagement() { - const [configSaved, setConfigSaved] = useState(false); const auth = useAuth(); const [avatar, setAvatar] = useState(); + const [configSaved, setConfigSaved] = useState(false); + const [messagesEnabled, setMessagesEnabled] = useState(false); + + useEffect(() => { + MessageEndpoint.isEnabled().then(setMessagesEnabled); + }, []); useEffect(() => { if (configSaved) { @@ -122,8 +127,8 @@ export default function ProfileManagement() { isDisabled={auth.state.user?.managedBySso}/>
- {auth.state.user?.emailConfirmed === false && + isDisabled={auth.state.user?.managedBySso || !messagesEnabled}/> + {(auth.state.user?.emailConfirmed === false && !auth.state.user.managedBySso) &&
+ {!messagesEnabled && +
+ + + Email services are disabled. Please contact your administrator. + +
+ }
diff --git a/src/main/frontend/views/SetupView.tsx b/src/main/frontend/views/SetupView.tsx index a837e8b..0cc5365 100644 --- a/src/main/frontend/views/SetupView.tsx +++ b/src/main/frontend/views/SetupView.tsx @@ -3,7 +3,7 @@ import * as Yup from 'yup'; import Wizard from "Frontend/components/wizard/Wizard"; import WizardStep from "Frontend/components/wizard/WizardStep"; import Input from "Frontend/components/general/Input"; -import {GearFine, HandWaving, Palette, User} from "@phosphor-icons/react"; +import {HandWaving, Palette, User} from "@phosphor-icons/react"; import {Card} from "@nextui-org/react"; import {SetupEndpoint} from "Frontend/generated/endpoints"; import {ThemeSelector} from "Frontend/components/theming/ThemeSelector"; @@ -76,17 +76,6 @@ function UserStep() { ); } -function SettingsStep() { - return ( -
-
-

Settings

-

Configure your settings

-
-
- ); -} - function SetupView() { const navigate = useNavigate(); @@ -131,9 +120,6 @@ function SetupView() { > - }> - - diff --git a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt index 46a72c2..c6fd289 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupEndpoint.kt @@ -3,18 +3,12 @@ package de.grimsi.gameyfin.setup import com.vaadin.flow.server.auth.AnonymousAllowed import com.vaadin.hilla.Endpoint import com.vaadin.hilla.exception.EndpointException -import de.grimsi.gameyfin.core.Roles -import de.grimsi.gameyfin.users.RoleService -import de.grimsi.gameyfin.users.UserService import de.grimsi.gameyfin.users.dto.UserInfoDto import de.grimsi.gameyfin.users.dto.UserRegistrationDto -import de.grimsi.gameyfin.users.entities.User @Endpoint class SetupEndpoint( - private val setupService: SetupService, - private val roleService: RoleService, - private val userService: UserService + private val setupService: SetupService ) { @AnonymousAllowed fun isSetupCompleted(): Boolean { @@ -24,15 +18,6 @@ class SetupEndpoint( @AnonymousAllowed fun registerSuperAdmin(superAdminRegistration: UserRegistrationDto): UserInfoDto { if (setupService.isSetupCompleted()) throw EndpointException("Setup already completed") - - val user = User( - username = superAdminRegistration.username, - password = superAdminRegistration.password, - email = superAdminRegistration.email, - roles = setOf(roleService.toRole(Roles.SUPERADMIN)) - ) - - val superAdmin = setupService.createInitialAdminUser(user) - return userService.toUserInfo(superAdmin) + return setupService.createInitialAdminUser(superAdminRegistration) } } \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt index 94fba9e..19e3057 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/setup/SetupService.kt @@ -3,6 +3,8 @@ package de.grimsi.gameyfin.setup import de.grimsi.gameyfin.core.Roles import de.grimsi.gameyfin.users.RoleService import de.grimsi.gameyfin.users.UserService +import de.grimsi.gameyfin.users.dto.UserInfoDto +import de.grimsi.gameyfin.users.dto.UserRegistrationDto import de.grimsi.gameyfin.users.entities.User import org.springframework.stereotype.Service @@ -24,7 +26,16 @@ class SetupService( /** * Creates the initial user with Super-Admin permissions */ - fun createInitialAdminUser(superAdmin: User): User { - return userService.registerOrUpdateUser(superAdmin, Roles.SUPERADMIN) + fun createInitialAdminUser(registration: UserRegistrationDto): UserInfoDto { + val superAdmin = User( + username = registration.username, + password = registration.password, + email = registration.email, + roles = setOf(roleService.toRole(Roles.SUPERADMIN)), + enabled = true + ) + + val user = userService.registerOrUpdateUser(superAdmin, Roles.SUPERADMIN) + return userService.toUserInfo(user) } } \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/shared/token/TokenService.kt b/src/main/kotlin/de/grimsi/gameyfin/shared/token/TokenService.kt index 9da7357..cafea7c 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/shared/token/TokenService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/shared/token/TokenService.kt @@ -2,7 +2,6 @@ package de.grimsi.gameyfin.shared.token import de.grimsi.gameyfin.users.entities.User import io.github.oshai.kotlinlogging.KotlinLogging -import jakarta.transaction.Transactional abstract class TokenService( private val type: T, @@ -11,7 +10,6 @@ abstract class TokenService( private val log = KotlinLogging.logger {} - @Transactional open fun generate(user: User): Token { val token = Token( creator = user, @@ -26,7 +24,6 @@ abstract class TokenService( return tokenRepository.save(token) } - @Transactional open fun generateWithPayload(user: User, payload: Map): Token { val token = Token( creator = user, @@ -42,7 +39,6 @@ abstract class TokenService( return tokenRepository.save(token) } - @Transactional open fun get(secret: String, type: T): Token? { val token = tokenRepository.findBySecret(secret) ?: return null @@ -55,12 +51,10 @@ abstract class TokenService( } } - @Transactional open fun getPayload(secret: String): Map? { return tokenRepository.findBySecret(secret)?.payload } - @Transactional open fun delete(token: Token) { try { tokenRepository.delete(token) @@ -69,7 +63,6 @@ abstract class TokenService( } } - @Transactional open fun validate(secret: String): TokenValidationResult { val token = tokenRepository.findBySecret(secret) ?: return TokenValidationResult.INVALID return if (token.expired) TokenValidationResult.EXPIRED else TokenValidationResult.VALID diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt b/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt index cf51d34..a635c8b 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/UserService.kt @@ -179,10 +179,10 @@ class UserService( } } - fun registerUserFromInvitation(user: UserRegistrationDto, email: String): User { + fun registerUserFromInvitation(registration: UserRegistrationDto, email: String): User { val user = User( - username = user.username, - password = passwordEncoder.encode(user.password), + username = registration.username, + password = passwordEncoder.encode(registration.password), email = email, emailConfirmed = true, enabled = true, diff --git a/src/main/kotlin/de/grimsi/gameyfin/users/registration/InvitationService.kt b/src/main/kotlin/de/grimsi/gameyfin/users/registration/InvitationService.kt index 7e3390f..f2be9c3 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/users/registration/InvitationService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/users/registration/InvitationService.kt @@ -2,6 +2,7 @@ package de.grimsi.gameyfin.users.registration import de.grimsi.gameyfin.core.Utils import de.grimsi.gameyfin.core.events.UserInvitationEvent +import de.grimsi.gameyfin.core.events.UserRegistrationEvent import de.grimsi.gameyfin.shared.token.TokenDto import de.grimsi.gameyfin.shared.token.TokenRepository import de.grimsi.gameyfin.shared.token.TokenService @@ -48,7 +49,10 @@ class InvitationService( val email = invitationToken.payload[EMAIL_KEY] ?: return TokenValidationResult.INVALID if (invitationToken.expired) return TokenValidationResult.EXPIRED - userService.registerUserFromInvitation(registration, email) + val user = userService.registerUserFromInvitation(registration, email) + super.delete(invitationToken) + eventPublisher.publishEvent(UserRegistrationEvent(this, user, Utils.getBaseUrl())) + return TokenValidationResult.VALID } } \ No newline at end of file