mirror of
https://github.com/sct/overseerr.git
synced 2025-12-26 08:25:07 +01:00
refactor: rework login page
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import Button from '@app/components/Common/Button';
|
||||
import SensitiveInput from '@app/components/Common/SensitiveInput';
|
||||
import useSettings from '@app/hooks/useSettings';
|
||||
import { useUser } from '@app/hooks/useUser';
|
||||
import { LoginIcon, SupportIcon } from '@heroicons/react/outline';
|
||||
import {
|
||||
ArrowLeftOnRectangleIcon,
|
||||
LifebuoyIcon,
|
||||
@@ -8,7 +10,7 @@ import {
|
||||
import axios from 'axios';
|
||||
import { Field, Form, Formik } from 'formik';
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
@@ -23,14 +25,15 @@ const messages = defineMessages({
|
||||
forgotpassword: 'Forgot Password?',
|
||||
});
|
||||
|
||||
interface LocalLoginProps {
|
||||
revalidate: () => void;
|
||||
}
|
||||
type LocalLoginProps = {
|
||||
onError: (errorMessage: string) => void;
|
||||
};
|
||||
|
||||
const LocalLogin = ({ revalidate }: LocalLoginProps) => {
|
||||
const LocalLogin = ({ onError }: LocalLoginProps) => {
|
||||
const intl = useIntl();
|
||||
const router = useRouter();
|
||||
const { revalidate } = useUser();
|
||||
const settings = useSettings();
|
||||
const [loginError, setLoginError] = useState<string | null>(null);
|
||||
|
||||
const LoginSchema = Yup.object().shape({
|
||||
email: Yup.string()
|
||||
@@ -54,14 +57,20 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => {
|
||||
validationSchema={LoginSchema}
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await axios.post('/api/v1/auth/local', {
|
||||
const response = await axios.post('/api/v1/auth/local', {
|
||||
email: values.email,
|
||||
password: values.password,
|
||||
});
|
||||
|
||||
if (response.data?.id) {
|
||||
const user = await revalidate();
|
||||
|
||||
if (user) {
|
||||
router.push('/');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
setLoginError(intl.formatMessage(messages.loginerror));
|
||||
} finally {
|
||||
revalidate();
|
||||
onError(intl.formatMessage(messages.loginerror));
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -112,11 +121,6 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => {
|
||||
<div className="error">{errors.password}</div>
|
||||
)}
|
||||
</div>
|
||||
{loginError && (
|
||||
<div className="mt-1 mb-2 sm:col-span-2 sm:mt-0">
|
||||
<div className="error">{loginError}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-8 border-t border-gray-700 pt-5">
|
||||
<div className="flex flex-row-reverse justify-between">
|
||||
|
||||
49
src/components/Login/PlexLogin/index.tsx
Normal file
49
src/components/Login/PlexLogin/index.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import PlexLoginButton from '@app/components/PlexLoginButton';
|
||||
import { useUser } from '@app/hooks/useUser';
|
||||
import axios from 'axios';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useState } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
const messages = defineMessages({
|
||||
loginwithplex: 'Sign In with Plex',
|
||||
});
|
||||
|
||||
type PlexLoginProps = {
|
||||
onError: (errorMessage: string) => void;
|
||||
};
|
||||
|
||||
const PlexLogin = ({ onError }: PlexLoginProps) => {
|
||||
const intl = useIntl();
|
||||
const router = useRouter();
|
||||
const { revalidate } = useUser();
|
||||
const [isProcessing, setProcessing] = useState(false);
|
||||
|
||||
const login = async (authToken: string) => {
|
||||
setProcessing(true);
|
||||
try {
|
||||
const response = await axios.post('/api/v1/auth/plex', { authToken });
|
||||
|
||||
if (response.data?.id) {
|
||||
const user = await revalidate();
|
||||
|
||||
if (user) {
|
||||
router.push('/');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
onError(e.response.data.message);
|
||||
setProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<PlexLoginButton
|
||||
isProcessing={isProcessing}
|
||||
onAuthToken={login}
|
||||
textOverride={intl.formatMessage(messages.loginwithplex)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlexLogin;
|
||||
@@ -1,62 +1,27 @@
|
||||
import Accordion from '@app/components/Common/Accordion';
|
||||
import ImageFader from '@app/components/Common/ImageFader';
|
||||
import PageTitle from '@app/components/Common/PageTitle';
|
||||
import LanguagePicker from '@app/components/Layout/LanguagePicker';
|
||||
import LocalLogin from '@app/components/Login/LocalLogin';
|
||||
import PlexLoginButton from '@app/components/PlexLoginButton';
|
||||
import PlexLogin from '@app/components/Login/PlexLogin';
|
||||
import useSettings from '@app/hooks/useSettings';
|
||||
import { useUser } from '@app/hooks/useUser';
|
||||
import { Transition } from '@headlessui/react';
|
||||
import { XCircleIcon } from '@heroicons/react/24/solid';
|
||||
import { XCircleIcon } from '@heroicons/react/solid';
|
||||
import { useEffect, useState } from 'react';
|
||||
import axios from 'axios';
|
||||
import { useRouter } from 'next/dist/client/router';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import useSWR from 'swr';
|
||||
|
||||
const messages = defineMessages({
|
||||
signin: 'Sign In',
|
||||
signinheader: 'Sign in to continue',
|
||||
signinwithplex: 'Use your Plex account',
|
||||
signinwithoverseerr: 'Use your {applicationTitle} account',
|
||||
});
|
||||
|
||||
const Login = () => {
|
||||
const intl = useIntl();
|
||||
const [error, setError] = useState('');
|
||||
const [isProcessing, setProcessing] = useState(false);
|
||||
const [authToken, setAuthToken] = useState<string | undefined>(undefined);
|
||||
const { revalidate } = useUser();
|
||||
const router = useRouter();
|
||||
const settings = useSettings();
|
||||
|
||||
// Effect that is triggered when the `authToken` comes back from the Plex OAuth
|
||||
// We take the token and attempt to sign in. If we get a success message, we will
|
||||
// ask swr to revalidate the user which _should_ come back with a valid user.
|
||||
useEffect(() => {
|
||||
const login = async () => {
|
||||
setProcessing(true);
|
||||
try {
|
||||
const response = await axios.post('/api/v1/auth/plex', { authToken });
|
||||
|
||||
if (response.data?.id) {
|
||||
const user = await revalidate();
|
||||
|
||||
if (user) {
|
||||
router.push('/');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
setError(e.response.data.message);
|
||||
setAuthToken(undefined);
|
||||
setProcessing(false);
|
||||
}
|
||||
};
|
||||
if (authToken) {
|
||||
login();
|
||||
}
|
||||
}, [authToken, revalidate, router]);
|
||||
|
||||
const { data: backdrops } = useSWR<string[]>('/api/v1/backdrops', {
|
||||
refreshInterval: 0,
|
||||
refreshWhenHidden: false,
|
||||
@@ -84,7 +49,7 @@ const Login = () => {
|
||||
</div>
|
||||
<div className="relative z-50 mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
||||
<div
|
||||
className="bg-gray-800 bg-opacity-50 shadow sm:rounded-lg"
|
||||
className="flex flex-col space-y-4 bg-gray-800 bg-opacity-50 p-4 shadow sm:rounded-lg "
|
||||
style={{ backdropFilter: 'blur(5px)' }}
|
||||
>
|
||||
<>
|
||||
@@ -111,7 +76,13 @@ const Login = () => {
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
<Accordion single atLeastOne>
|
||||
{settings.currentSettings.plexLoginEnabled && (
|
||||
<PlexLogin onError={(msg) => setError(msg)} />
|
||||
)}
|
||||
{settings.currentSettings.localLogin && (
|
||||
<LocalLogin onError={(msg) => setError(msg)} />
|
||||
)}
|
||||
{/* <Accordion single atLeastOne>
|
||||
{({ openIndexes, handleClick, AccordionContent }) => (
|
||||
<>
|
||||
{settings.currentSettings.plexLoginEnabled && (
|
||||
@@ -162,7 +133,7 @@ const Login = () => {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Accordion>
|
||||
</Accordion> */}
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
"components.Layout.VersionStatus.outofdate": "Out of Date",
|
||||
"components.Layout.VersionStatus.streamdevelop": "Overseerr Develop",
|
||||
"components.Layout.VersionStatus.streamstable": "Overseerr Stable",
|
||||
"components.Login.PlexLogin.loginwithplex": "Sign In with Plex",
|
||||
"components.Login.email": "Email Address",
|
||||
"components.Login.forgotpassword": "Forgot Password?",
|
||||
"components.Login.loginerror": "Something went wrong while trying to sign in.",
|
||||
@@ -223,8 +224,6 @@
|
||||
"components.Login.signin": "Sign In",
|
||||
"components.Login.signingin": "Signing In…",
|
||||
"components.Login.signinheader": "Sign in to continue",
|
||||
"components.Login.signinwithoverseerr": "Use your {applicationTitle} account",
|
||||
"components.Login.signinwithplex": "Use your Plex account",
|
||||
"components.Login.validationemailrequired": "You must provide a valid email address",
|
||||
"components.Login.validationpasswordrequired": "You must provide a password",
|
||||
"components.ManageSlideOver.alltime": "All Time",
|
||||
@@ -972,7 +971,15 @@
|
||||
"components.Settings.webAppUrlTip": "Optionally direct users to the web app on your server instead of the \"hosted\" web app",
|
||||
"components.Settings.webhook": "Webhook",
|
||||
"components.Settings.webpush": "Web Push",
|
||||
"components.Setup.configureplex": "Configure Plex",
|
||||
"components.Setup.ConfigureMediaServers.continue": "Continue",
|
||||
"components.Setup.ConfigureMediaServers.goback": "Go Back",
|
||||
"components.Setup.ConfigureMediaServers.scanbackground": "Scanning will run in the background. You can continue the setup process in the meantime.",
|
||||
"components.Setup.ConfigureMediaServers.tip": "Tip",
|
||||
"components.Setup.CreateAccount.getstarted": "Let's get started! To begin, we will need to create your administrator account. You can either do this by logging in with your Plex account, or creating a local user.",
|
||||
"components.Setup.CreateAccount.validationEmail": "You must provide a valid email address",
|
||||
"components.Setup.CreateAccount.validationpasswordminchars": "Password is too short; should be a minimum of 8 characters",
|
||||
"components.Setup.CreateAccount.welcometooverseerr": "Welcome to Overseerr!",
|
||||
"components.Setup.configuremediaserver": "Configure Media Server",
|
||||
"components.Setup.configureservices": "Configure Services",
|
||||
"components.Setup.continue": "Continue",
|
||||
"components.Setup.finish": "Finish Setup",
|
||||
@@ -980,9 +987,8 @@
|
||||
"components.Setup.loginwithplex": "Create Admin Account",
|
||||
"components.Setup.scanbackground": "Scanning will run in the background. You can continue the setup process in the meantime.",
|
||||
"components.Setup.setup": "Setup",
|
||||
"components.Setup.signinMessage": "Get started by signing in with your Plex account",
|
||||
"components.Setup.signinwithplex": "Sign In with Plex",
|
||||
"components.Setup.tip": "Tip",
|
||||
"components.Setup.welcome": "Welcome to Overseerr",
|
||||
"components.StatusBadge.managemedia": "Manage {mediaType}",
|
||||
"components.StatusBadge.openinarr": "Open in {arr}",
|
||||
"components.StatusBadge.playonplex": "Play on Plex",
|
||||
@@ -1078,9 +1084,9 @@
|
||||
"components.UserProfile.ProfileHeader.profile": "View Profile",
|
||||
"components.UserProfile.ProfileHeader.settings": "Edit Settings",
|
||||
"components.UserProfile.ProfileHeader.userid": "User ID: {userid}",
|
||||
"components.UserProfile.UserSettings.UserGeneralSettings.accounttype": "Account Type",
|
||||
"components.UserProfile.UserSettings.UserGeneralSettings.admin": "Admin",
|
||||
"components.UserProfile.UserSettings.UserGeneralSettings.applanguage": "Display Language",
|
||||
"components.UserProfile.UserSettings.UserGeneralSettings.connectedaccounts": "Connected Accounts",
|
||||
"components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord User ID",
|
||||
"components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your Discord user account",
|
||||
"components.UserProfile.UserSettings.UserGeneralSettings.displayName": "Display Name",
|
||||
|
||||
Reference in New Issue
Block a user