From 5fe330cd79be034e41f9c5181455e50e8c2fc5c1 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Sun, 22 Sep 2024 02:17:43 +0100 Subject: feature(mobile): Allow users to login with API keys in the mobile app --- apps/mobile/app/signin.tsx | 188 +++++++++++++++++++++++++++------------------ 1 file changed, 115 insertions(+), 73 deletions(-) (limited to 'apps/mobile/app/signin.tsx') diff --git a/apps/mobile/app/signin.tsx b/apps/mobile/app/signin.tsx index 6190c258..df0c2e5f 100644 --- a/apps/mobile/app/signin.tsx +++ b/apps/mobile/app/signin.tsx @@ -8,37 +8,63 @@ import { TouchableWithoutFeedback, View, } from "react-native"; -import { Redirect, useRouter } from "expo-router"; +import { Redirect } from "expo-router"; import Logo from "@/components/Logo"; import { TailwindResolver } from "@/components/TailwindResolver"; -import { Button, buttonVariants } from "@/components/ui/Button"; +import { Button } from "@/components/ui/Button"; import { Input } from "@/components/ui/Input"; import useAppSettings from "@/lib/settings"; import { api } from "@/lib/trpc"; -import { cn } from "@/lib/utils"; -import { Bug } from "lucide-react-native"; + +enum LoginType { + Password, + ApiKey, +} export default function Signin() { - const router = useRouter(); const { settings, setSettings } = useAppSettings(); - const [serverAddress, setServerAddress] = useState(settings.address); const [error, setError] = useState(); - - const { mutate: login, isPending } = api.apiKeys.exchange.useMutation({ - onSuccess: (resp) => { - setSettings({ ...settings, apiKey: resp.key, apiKeyId: resp.id }); - }, - onError: (e) => { - if (e.data?.code === "UNAUTHORIZED") { - setError("Wrong username or password"); + const [loginType, setLoginType] = useState(LoginType.Password); + const toggleLoginType = () => { + setLoginType((prev) => { + if (prev === LoginType.Password) { + return LoginType.ApiKey; } else { - setError(`${e.message}`); + return LoginType.Password; } - }, - }); + }); + }; + + const { mutate: login, isPending: userNamePasswordRequestIsPending } = + api.apiKeys.exchange.useMutation({ + onSuccess: (resp) => { + setSettings({ ...settings, apiKey: resp.key, apiKeyId: resp.id }); + }, + onError: (e) => { + if (e.data?.code === "UNAUTHORIZED") { + setError("Wrong username or password"); + } else { + setError(`${e.message}`); + } + }, + }); + + const { mutate: validateApiKey, isPending: apiKeyValueRequestIsPending } = + api.apiKeys.validate.useMutation({ + onSuccess: () => { + setSettings({ ...settings, apiKey: apiFormData.apiKey }); + }, + onError: (e) => { + if (e.data?.code === "UNAUTHORIZED") { + setError("Invalid API key"); + } else { + setError(`${e.message}`); + } + }, + }); - const [formData, setFormData] = useState<{ + const [usernameFormData, setUserNameFormData] = useState<{ email: string; password: string; }>({ @@ -46,13 +72,23 @@ export default function Signin() { password: "", }); + const [apiFormData, setApiFormData] = useState<{ + apiKey: string; + }>({ + apiKey: "", + }); + if (settings.apiKey) { return ; } const onSignin = () => { - const randStr = (Math.random() + 1).toString(36).substring(5); - login({ ...formData, keyName: `Mobile App: (${randStr})` }); + if (loginType === LoginType.Password) { + const randStr = (Math.random() + 1).toString(36).substring(5); + login({ ...usernameFormData, keyName: `Mobile App: (${randStr})` }); + } else if (loginType === LoginType.ApiKey) { + validateApiKey({ apiKey: apiFormData.apiKey }); + } }; return ( @@ -76,66 +112,72 @@ export default function Signin() { {error && ( {error} )} - - Server Address - { - setServerAddress(e); - setSettings({ ...settings, address: e.replace(/\/$/, "") }); - }} - /> - - - Email - setFormData((s) => ({ ...s, email: e }))} - /> - - - Password - setFormData((s) => ({ ...s, password: e }))} - /> - + {loginType === LoginType.Password && ( + <> + + Email + + setUserNameFormData((s) => ({ ...s, email: e })) + } + /> + + + Password + + setUserNameFormData((s) => ({ ...s, password: e })) + } + /> + + + )} + + {loginType === LoginType.ApiKey && ( + + API Key + + setApiFormData((s) => ({ ...s, apiKey: e })) + } + /> + + )} +