mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-16 16:20:04 +00:00
Fix authentication for websocket based endpoints
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
import {useAuth} from "Frontend/util/auth";
|
import {useAuth} from "Frontend/util/auth";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {Button, Card, CardBody, CardHeader, Link, useDisclosure} from "@heroui/react";
|
import {Button, Card, CardBody, CardHeader, Link, useDisclosure} from "@heroui/react";
|
||||||
import {useNavigate} from "react-router";
|
|
||||||
import {Form, Formik} from "formik";
|
import {Form, Formik} from "formik";
|
||||||
import Input from "Frontend/components/general/input/Input";
|
import Input from "Frontend/components/general/input/Input";
|
||||||
import PasswordResetModal from "Frontend/components/general/modals/PasswordResetModal";
|
import PasswordResetModal from "Frontend/components/general/modals/PasswordResetModal";
|
||||||
import SignUpModal from "Frontend/components/general/modals/SignUpModal";
|
import SignUpModal from "Frontend/components/general/modals/SignUpModal";
|
||||||
import {RegistrationEndpoint} from "Frontend/generated/endpoints";
|
import {RegistrationEndpoint} from "Frontend/generated/endpoints";
|
||||||
|
import {useNavigate} from "react-router";
|
||||||
|
|
||||||
export default function LoginView() {
|
export default function LoginView() {
|
||||||
const {state, login} = useAuth();
|
const {state, login} = useAuth();
|
||||||
@@ -15,26 +15,31 @@ export default function LoginView() {
|
|||||||
const passwordResetModal = useDisclosure();
|
const passwordResetModal = useDisclosure();
|
||||||
const signUpModal = useDisclosure();
|
const signUpModal = useDisclosure();
|
||||||
|
|
||||||
const [url, setUrl] = useState<string>();
|
|
||||||
const [signUpAllowed, setSignUpAllowed] = useState<boolean>(false);
|
const [signUpAllowed, setSignUpAllowed] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (state.user) {
|
if (state.user) {
|
||||||
const path = url ? new URL(url, document.baseURI).pathname : '/'
|
redirectAfterLogin();
|
||||||
navigate(path, {replace: true});
|
|
||||||
} else {
|
} else {
|
||||||
RegistrationEndpoint.isSelfRegistrationAllowed().then(setSignUpAllowed);
|
RegistrationEndpoint.isSelfRegistrationAllowed().then(setSignUpAllowed);
|
||||||
}
|
}
|
||||||
}, [state.user]);
|
}, [state.user]);
|
||||||
|
|
||||||
async function tryLogin(values: any, formik: any) {
|
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) {
|
if (error) {
|
||||||
formik.setFieldError("username", " "); // Mark the field red, but don't show an error message
|
formik.setFieldError("username", " "); // Mark the field red, but don't show an error message
|
||||||
formik.setFieldError("password", "Invalid username and/or password.");
|
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 (
|
return (
|
||||||
<div className="flex size-full gradient-primary">
|
<div className="flex size-full gradient-primary">
|
||||||
<Card className="m-auto p-12">
|
<Card className="m-auto p-12">
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package de.grimsi.gameyfin.config
|
package de.grimsi.gameyfin.config
|
||||||
|
|
||||||
import com.vaadin.flow.server.auth.AnonymousAllowed
|
|
||||||
import com.vaadin.hilla.Endpoint
|
import com.vaadin.hilla.Endpoint
|
||||||
import de.grimsi.gameyfin.config.dto.ConfigEntryDto
|
import de.grimsi.gameyfin.config.dto.ConfigEntryDto
|
||||||
import de.grimsi.gameyfin.config.dto.ConfigUpdateDto
|
import de.grimsi.gameyfin.config.dto.ConfigUpdateDto
|
||||||
import de.grimsi.gameyfin.core.Role
|
import de.grimsi.gameyfin.core.Role
|
||||||
|
import de.grimsi.gameyfin.users.util.isAdmin
|
||||||
import jakarta.annotation.security.PermitAll
|
import jakarta.annotation.security.PermitAll
|
||||||
import jakarta.annotation.security.RolesAllowed
|
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.Flux
|
||||||
import reactor.core.publisher.Sinks
|
import reactor.core.publisher.Sinks
|
||||||
|
|
||||||
@@ -23,9 +25,12 @@ class ConfigEndpoint(
|
|||||||
return config.getAll(null)
|
return config.getAll(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME
|
@PermitAll
|
||||||
@AnonymousAllowed
|
fun subscribe(): Flux<ConfigUpdateDto> {
|
||||||
fun subscribe(): Flux<ConfigUpdateDto> = configUpdates.asFlux()
|
val user = SecurityContextHolder.getContext().authentication.principal as UserDetails
|
||||||
|
return if (user.isAdmin()) configUpdates.asFlux()
|
||||||
|
else Flux.empty()
|
||||||
|
}
|
||||||
|
|
||||||
fun update(update: ConfigUpdateDto) {
|
fun update(update: ConfigUpdateDto) {
|
||||||
config.update(update.updates)
|
config.update(update.updates)
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package de.grimsi.gameyfin.core.logging
|
package de.grimsi.gameyfin.core.logging
|
||||||
|
|
||||||
import com.vaadin.flow.server.auth.AnonymousAllowed
|
|
||||||
import com.vaadin.hilla.Endpoint
|
import com.vaadin.hilla.Endpoint
|
||||||
import de.grimsi.gameyfin.core.Role
|
import de.grimsi.gameyfin.core.Role
|
||||||
|
import de.grimsi.gameyfin.users.util.isAdmin
|
||||||
|
import jakarta.annotation.security.PermitAll
|
||||||
import jakarta.annotation.security.RolesAllowed
|
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.Flux
|
||||||
|
|
||||||
@Endpoint
|
@Endpoint
|
||||||
@@ -16,9 +19,10 @@ class LogEndpoint(
|
|||||||
logService.configureFileLogging()
|
logService.configureFileLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: see https://vaadin.com/forum/t/can-only-access-flux-endpoint-with-anonymousallowed/167117
|
@PermitAll
|
||||||
@AnonymousAllowed
|
|
||||||
fun getApplicationLogs(): Flux<String> {
|
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
|
package de.grimsi.gameyfin.users.util
|
||||||
|
|
||||||
import de.grimsi.gameyfin.core.Role
|
import de.grimsi.gameyfin.core.Role
|
||||||
|
|||||||
Reference in New Issue
Block a user