make email an optional setting + add device name validation

This commit is contained in:
mrjvs 2023-12-02 00:02:09 +01:00
parent 83bc9637b0
commit 7841fadcb6
7 changed files with 40 additions and 9 deletions

View File

@ -16,6 +16,7 @@
"title": "Login to your account",
"description": "Please enter your passphrase to login to your account",
"validationError": "Invalid or incomplete passphrase",
"deviceLengthError": "Please entire a device name",
"submit": "Login",
"passphraseLabel": "12-Word passphrase",
"passphrasePlaceholder": "Passphrase"

View File

@ -4,6 +4,7 @@ import { useHistory } from "react-router-dom";
import { Icon, Icons } from "@/components/Icon";
import { BrandPill } from "@/components/layout/BrandPill";
import { WideContainer } from "@/components/layout/WideContainer";
import { shouldHaveDmcaPage } from "@/pages/Dmca";
import { conf } from "@/setup/config";
function FooterLink(props: {
@ -30,6 +31,8 @@ function Dmca() {
const { t } = useTranslation();
const history = useHistory();
if (!shouldHaveDmcaPage()) return null;
return (
<FooterLink icon={Icons.DRAGON} onClick={() => history.push("/dmca")}>
{t("footer.links.dmca")}

View File

@ -4,10 +4,14 @@ import { Icon, Icons } from "@/components/Icon";
import { ThinContainer } from "@/components/layout/ThinContainer";
import { Heading1, Paragraph } from "@/components/utils/Text";
import { PageTitle } from "@/pages/parts/util/PageTitle";
import { conf } from "@/setup/config";
import { SubPageLayout } from "./layouts/SubPageLayout";
// TODO make email a constant
export function shouldHaveDmcaPage() {
return !!conf().DMCA_EMAIL;
}
export function DmcaPage() {
const { t } = useTranslation();
@ -19,7 +23,7 @@ export function DmcaPage() {
<Paragraph>{t("screens.dmca.text")}</Paragraph>
<Paragraph className="flex space-x-3 items-center">
<Icon icon={Icons.MAIL} />
<span>dmca@movie-web.app</span>
<span>{conf().DMCA_EMAIL ?? ""}</span>
</Paragraph>
</ThinContainer>
</SubPageLayout>

View File

@ -32,11 +32,18 @@ export function AccountCreatePart(props: AccountCreatePartProps) {
const [colorB, setColorB] = useState("#2E65CF");
const [userIcon, setUserIcon] = useState<UserIcons>(UserIcons.USER);
const { t } = useTranslation();
// TODO validate device and account before next step
const [hasDeviceError, setHasDeviceError] = useState(false);
const nextStep = useCallback(() => {
setHasDeviceError(false);
const validatedDevice = device.trim();
if (validatedDevice.length === 0) {
setHasDeviceError(true);
return;
}
props.onNext?.({
device,
device: validatedDevice,
profile: {
colorA,
colorB,
@ -75,6 +82,11 @@ export function AccountCreatePart(props: AccountCreatePartProps) {
value={userIcon}
onInput={setUserIcon}
/>
{hasDeviceError ? (
<p className="text-authentication-errorText">
{t("auth.login.deviceLengthError")}
</p>
) : null}
</div>
<LargeCardButtons>
<Button theme="purple" onClick={() => nextStep()}>

View File

@ -29,14 +29,17 @@ export function LoginFormPart(props: LoginFormPartProps) {
const [result, execute] = useAsyncFn(
async (inputMnemonic: string, inputdevice: string) => {
// TODO verify valid device input
if (!verifyValidMnemonic(inputMnemonic))
throw new Error(t("auth.login.validationError") ?? undefined);
const validatedDevice = inputdevice.trim();
if (validatedDevice.length === 0)
throw new Error(t("auth.login.deviceLengthError") ?? undefined);
const account = await login({
mnemonic: inputMnemonic,
userData: {
device: inputdevice,
device: validatedDevice,
},
});
@ -46,7 +49,7 @@ export function LoginFormPart(props: LoginFormPartProps) {
props.onLogin?.();
},
[props, login, restore]
[props, login, restore, t]
);
return (

View File

@ -14,7 +14,7 @@ import { useOnlineListener } from "@/hooks/usePing";
import { AboutPage } from "@/pages/About";
import { AdminPage } from "@/pages/admin/AdminPage";
import VideoTesterView from "@/pages/developer/VideoTesterView";
import { DmcaPage } from "@/pages/Dmca";
import { DmcaPage, shouldHaveDmcaPage } from "@/pages/Dmca";
import { NotFoundPage } from "@/pages/errors/NotFoundPage";
import { HomePage } from "@/pages/HomePage";
import { LoginPage } from "@/pages/Login";
@ -93,7 +93,10 @@ function App() {
<Route exact path="/register" component={RegisterPage} />
<Route exact path="/login" component={LoginPage} />
<Route exact path="/faq" component={AboutPage} />
<Route exact path="/dmca" component={DmcaPage} />
{shouldHaveDmcaPage() ? (
<Route exact path="/dmca" component={DmcaPage} />
) : null}
{/* Settings page */}
<Route exact path="/settings" component={SettingsPage} />

View File

@ -10,6 +10,7 @@ interface Config {
GITHUB_LINK: string;
DONATION_LINK: string;
DISCORD_LINK: string;
DMCA_EMAIL: string;
TMDB_READ_API_KEY: string;
CORS_PROXY_URL: string;
NORMAL_ROUTER: boolean;
@ -22,6 +23,7 @@ export interface RuntimeConfig {
GITHUB_LINK: string;
DONATION_LINK: string;
DISCORD_LINK: string;
DMCA_EMAIL: string | null;
TMDB_READ_API_KEY: string;
NORMAL_ROUTER: boolean;
PROXY_URLS: string[];
@ -35,6 +37,7 @@ const env: Record<keyof Config, undefined | string> = {
GITHUB_LINK: undefined,
DONATION_LINK: undefined,
DISCORD_LINK: undefined,
DMCA_EMAIL: import.meta.env.VITE_DMCA_EMAIL,
CORS_PROXY_URL: import.meta.env.VITE_CORS_PROXY_URL,
NORMAL_ROUTER: import.meta.env.VITE_NORMAL_ROUTER,
BACKEND_URL: import.meta.env.VITE_BACKEND_URL,
@ -54,11 +57,13 @@ function getKey(key: keyof Config, defaultString?: string): string {
}
export function conf(): RuntimeConfig {
const dmcaEmail = getKey("DMCA_EMAIL");
return {
APP_VERSION,
GITHUB_LINK,
DONATION_LINK,
DISCORD_LINK,
DMCA_EMAIL: dmcaEmail.length > 0 ? dmcaEmail : null,
BACKEND_URL: getKey("BACKEND_URL"),
TMDB_READ_API_KEY: getKey("TMDB_READ_API_KEY"),
PROXY_URLS: getKey("CORS_PROXY_URL")