Fix authentication for websocket based endpoints

This commit is contained in:
grimsi
2025-05-18 09:52:16 +02:00
parent 2f2b18fade
commit 01cc758b07
4 changed files with 27 additions and 16 deletions
+10 -5
View File
@@ -1,12 +1,12 @@
import {useAuth} from "Frontend/util/auth";
import {useEffect, useState} from "react";
import {Button, Card, CardBody, CardHeader, Link, useDisclosure} from "@heroui/react";
import {useNavigate} from "react-router";
import {Form, Formik} from "formik";
import Input from "Frontend/components/general/input/Input";
import PasswordResetModal from "Frontend/components/general/modals/PasswordResetModal";
import SignUpModal from "Frontend/components/general/modals/SignUpModal";
import {RegistrationEndpoint} from "Frontend/generated/endpoints";
import {useNavigate} from "react-router";
export default function LoginView() {
const {state, login} = useAuth();
@@ -15,26 +15,31 @@ export default function LoginView() {
const passwordResetModal = useDisclosure();
const signUpModal = useDisclosure();
const [url, setUrl] = useState<string>();
const [signUpAllowed, setSignUpAllowed] = useState<boolean>(false);
useEffect(() => {
if (state.user) {
const path = url ? new URL(url, document.baseURI).pathname : '/'
navigate(path, {replace: true});
redirectAfterLogin();
} else {
RegistrationEndpoint.isSelfRegistrationAllowed().then(setSignUpAllowed);
}
}, [state.user]);
async function tryLogin(values: any, formik: any) {
const {error} = await login(values.username, values.password);
const {defaultUrl, error, redirectUrl} = await login(values.username, values.password);
if (error) {
formik.setFieldError("username", " "); // Mark the field red, but don't show an error message
formik.setFieldError("password", "Invalid username and/or password.");
} else {
redirectAfterLogin(redirectUrl, defaultUrl);
}
}
function redirectAfterLogin(redirectUrl?: string, defaultUrl?: string) {
const url = redirectUrl ?? defaultUrl ?? '/';
navigate(url, {replace: true});
}
return (
<div className="flex size-full gradient-primary">
<Card className="m-auto p-12">
@@ -1,12 +1,14 @@
package de.grimsi.gameyfin.config
import com.vaadin.flow.server.auth.AnonymousAllowed
import com.vaadin.hilla.Endpoint
import de.grimsi.gameyfin.config.dto.ConfigEntryDto
import de.grimsi.gameyfin.config.dto.ConfigUpdateDto
import de.grimsi.gameyfin.core.Role
import de.grimsi.gameyfin.users.util.isAdmin
import jakarta.annotation.security.PermitAll
import jakarta.annotation.security.RolesAllowed
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
import reactor.core.publisher.Flux
import reactor.core.publisher.Sinks
@@ -23,9 +25,12 @@ class ConfigEndpoint(
return config.getAll(null)
}
// FIXME
@AnonymousAllowed
fun subscribe(): Flux<ConfigUpdateDto> = configUpdates.asFlux()
@PermitAll
fun subscribe(): Flux<ConfigUpdateDto> {
val user = SecurityContextHolder.getContext().authentication.principal as UserDetails
return if (user.isAdmin()) configUpdates.asFlux()
else Flux.empty()
}
fun update(update: ConfigUpdateDto) {
config.update(update.updates)
@@ -1,9 +1,12 @@
package de.grimsi.gameyfin.core.logging
import com.vaadin.flow.server.auth.AnonymousAllowed
import com.vaadin.hilla.Endpoint
import de.grimsi.gameyfin.core.Role
import de.grimsi.gameyfin.users.util.isAdmin
import jakarta.annotation.security.PermitAll
import jakarta.annotation.security.RolesAllowed
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
import reactor.core.publisher.Flux
@Endpoint
@@ -16,9 +19,10 @@ class LogEndpoint(
logService.configureFileLogging()
}
// FIXME: see https://vaadin.com/forum/t/can-only-access-flux-endpoint-with-anonymousallowed/167117
@AnonymousAllowed
@PermitAll
fun getApplicationLogs(): Flux<String> {
return logService.streamLogs()
val user = SecurityContextHolder.getContext().authentication.principal as UserDetails
return if (user.isAdmin()) logService.streamLogs()
else Flux.empty()
}
}
@@ -1,6 +1,3 @@
@file:JvmName("Utils")
@file:JvmMultifileClass
package de.grimsi.gameyfin.users.util
import de.grimsi.gameyfin.core.Role