refactor: rework login page

This commit is contained in:
sct
2022-12-28 16:09:48 +09:00
parent 05bb8f8f9c
commit 2ca573d73e
4 changed files with 92 additions and 62 deletions

View File

@@ -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">

View 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;

View File

@@ -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>

View File

@@ -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",