From 520e87215d23d0f3eaf39956b31955439a578400 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Sun, 22 Oct 2023 19:20:34 +0530 Subject: [PATCH 01/12] fix: error handling, dark mode, consent bug fixes rebase rebase rebase rebase rebase rebase rebase rebase rebase --- .../components/captcha-challenge/index.tsx | 1 + .../app/components/input-component.tsx | 12 +-- .../app/components/main-container/index.tsx | 2 +- apps/consent/app/components/select.tsx | 47 ++++++++++ apps/consent/app/error-handler.ts | 25 ++++++ apps/consent/app/layout.tsx | 17 ++-- apps/consent/app/login/email-login-form.tsx | 90 +++++++++++++++++++ .../app/login/email-login-server-action.ts | 86 ++++++++++++++++++ apps/consent/app/login/page.tsx | 63 ++----------- apps/consent/app/login/phone/form.tsx | 17 +++- .../consent/app/login/phone/server-actions.ts | 58 +++++++----- apps/consent/app/login/verification/form.tsx | 7 +- .../app/login/verification/server-actions.ts | 39 +++----- apps/consent/services/galoy-auth/index.ts | 5 +- apps/dashboard/.env | 5 ++ pnpm-lock.yaml | 61 ++++++------- 16 files changed, 374 insertions(+), 161 deletions(-) create mode 100644 apps/consent/app/components/select.tsx create mode 100644 apps/consent/app/error-handler.ts create mode 100644 apps/consent/app/login/email-login-form.tsx create mode 100644 apps/consent/app/login/email-login-server-action.ts create mode 100644 apps/dashboard/.env diff --git a/apps/consent/app/components/captcha-challenge/index.tsx b/apps/consent/app/components/captcha-challenge/index.tsx index c75527b29b..455c26f9af 100644 --- a/apps/consent/app/components/captcha-challenge/index.tsx +++ b/apps/consent/app/components/captcha-challenge/index.tsx @@ -18,6 +18,7 @@ const CaptchaChallengeComponent: React.FC<{ login_challenge: string phone: string remember: string + channel: string } }> = ({ id, challenge, formData }) => { const captchaHandler = useCallback( diff --git a/apps/consent/app/components/input-component.tsx b/apps/consent/app/components/input-component.tsx index 1df23590fb..286dcd64f2 100644 --- a/apps/consent/app/components/input-component.tsx +++ b/apps/consent/app/components/input-component.tsx @@ -1,8 +1,8 @@ -import React, { InputHTMLAttributes } from "react" +import React, { InputHTMLAttributes } from "react"; interface InputProps extends InputHTMLAttributes { - label?: string - id: string + label?: string; + id: string; } const InputComponent: React.FC = ({ label, id, ...inputProps }) => { @@ -31,7 +31,7 @@ const InputComponent: React.FC = ({ label, id, ...inputProps }) => { focus-within:bg-[var(--inputBackground)] " /> - ) -} + ); +}; -export default InputComponent +export default InputComponent; diff --git a/apps/consent/app/components/main-container/index.tsx b/apps/consent/app/components/main-container/index.tsx index cda502f690..419331ec09 100644 --- a/apps/consent/app/components/main-container/index.tsx +++ b/apps/consent/app/components/main-container/index.tsx @@ -9,7 +9,7 @@ const MainContent: React.FC = ({ children }) => {
{children}
- ) + ); } export default MainContent diff --git a/apps/consent/app/components/select.tsx b/apps/consent/app/components/select.tsx new file mode 100644 index 0000000000..98ec83d115 --- /dev/null +++ b/apps/consent/app/components/select.tsx @@ -0,0 +1,47 @@ +import React, { SelectHTMLAttributes } from "react"; + +interface SelectProps extends SelectHTMLAttributes { + label?: string; + id: string; + options: string[]; +} + +const SelectComponent: React.FC = ({ + label, + id, + options, + ...selectProps +}) => { + return ( +
+ {label ? ( + + ) : null} + +
+ ); +}; + +export default SelectComponent; diff --git a/apps/consent/app/error-handler.ts b/apps/consent/app/error-handler.ts new file mode 100644 index 0000000000..1ff3526bc5 --- /dev/null +++ b/apps/consent/app/error-handler.ts @@ -0,0 +1,25 @@ +import axios from "axios"; + +interface ErrorResponse { + error: boolean; + message: string; + responsePayload: null; +} + +export const handleAxiosError = (err: any): ErrorResponse => { + if (axios.isAxiosError(err) && err.response) { + console.error("Error:", err.response.data.error); + return { + error: true, + message: err.response?.data?.error?.name || err?.response?.data?.error, + responsePayload: null, + }; + } + + console.error("An unknown error occurred", err); + return { + error: true, + message: "An unknown error occurred", + responsePayload: null, + }; +}; diff --git a/apps/consent/app/layout.tsx b/apps/consent/app/layout.tsx index d418641185..a0437f6d9c 100644 --- a/apps/consent/app/layout.tsx +++ b/apps/consent/app/layout.tsx @@ -1,13 +1,10 @@ -// eslint-disable-next-line import/no-unassigned-import -import "./globals.css" -// eslint-disable-next-line import/no-unassigned-import -import "react-toastify/dist/ReactToastify.css" -import Script from "next/script" -import type { Metadata } from "next" -import { Inter_Tight } from "next/font/google" -import { ToastContainer } from "react-toastify" - -import Theme from "./components/next-themes-provider" +import "./globals.css"; +import "react-toastify/dist/ReactToastify.css"; +import Script from "next/script"; +import type { Metadata } from "next"; +import { Inter_Tight } from "next/font/google"; +import { ToastContainer } from "react-toastify"; +import Theme from "./components/next-themes-provider"; const inter = Inter_Tight({ subsets: ["latin"] }) export const metadata: Metadata = { diff --git a/apps/consent/app/login/email-login-form.tsx b/apps/consent/app/login/email-login-form.tsx new file mode 100644 index 0000000000..28d4df2c5b --- /dev/null +++ b/apps/consent/app/login/email-login-form.tsx @@ -0,0 +1,90 @@ +"use client"; +import React from "react"; +// @ts-ignore-next-line no-implicit-any error +import { experimental_useFormState as useFormState } from "react-dom"; +import InputComponent from "../components/input-component"; +import Link from "next/link"; +import FormComponent from "../components/form-component"; +import Separator from "../components/separator"; +import PrimaryButton from "../components/button/primary-button-component"; +import SecondaryButton from "../components/button/secondary-button-component"; +import { SubmitValue } from "../index.types"; +import { submitForm } from "./email-login-server-action"; +import { toast } from "react-toastify"; +// this page is for login via email +interface LoginProps { + login_challenge: string; +} + +const EmailLoginForm = ({ login_challenge }: LoginProps) => { + const [state, formAction] = useFormState(submitForm, { + error: null, + message: null, + }); + + if (state.error) { + toast.error(state.message); + state.error = null; + } + + return ( + + + +
+ +
+ or +
+
+ +

Sign in with phone

+ +
+
+
+ + Next + + + Cancel + +
+
+ ); +}; +export default EmailLoginForm; diff --git a/apps/consent/app/login/email-login-server-action.ts b/apps/consent/app/login/email-login-server-action.ts new file mode 100644 index 0000000000..053b77c633 --- /dev/null +++ b/apps/consent/app/login/email-login-server-action.ts @@ -0,0 +1,86 @@ +"use server"; +import { redirect } from "next/navigation"; +import { hydraClient } from "../../services/hydra"; +import { cookies } from "next/headers"; +import authApi from "@/services/galoy-auth"; +import { LoginType, SubmitValue } from "../index.types"; +import { LoginEmailResponse } from "./email-login.types"; +import { headers } from "next/headers"; +import { handleAxiosError } from "@/app/error-handler"; +// this page is for login via email + +export async function submitForm( + _prevState: unknown, + formData: FormData +): Promise { + const headersList = headers(); + const customHeaders = { + "x-real-ip": headersList.get("x-real-ip"), + "x-forwarded-for": headersList.get("x-forwarded-for"), + }; + + const login_challenge = formData.get("login_challenge"); + const submitValue = formData.get("submit"); + const email = formData.get("email"); + const remember = String(formData.get("remember") === "1"); + if ( + !login_challenge || + !submitValue || + !remember || + typeof login_challenge !== "string" || + typeof submitValue !== "string" + ) { + throw new Error("Invalid Value"); + } + + if (submitValue === SubmitValue.denyAccess) { + console.log("User denied access"); + const response = await hydraClient.rejectOAuth2LoginRequest({ + loginChallenge: login_challenge, + rejectOAuth2Request: { + error: "access_denied", + error_description: "The resource owner denied the request", + }, + }); + redirect(response.data.redirect_to); + } + + if (!email || typeof email !== "string") { + console.error("Invalid Values for email"); + throw new Error("Invalid Email Value"); + } + + let emailCodeRequest; + try { + emailCodeRequest = await authApi.requestEmailCode(email, customHeaders); + } catch (err) { + console.error("Error in requestEmailCode", err); + return handleAxiosError(err); + } + + // TODO: manage error on ip rate limit + // TODO: manage error when trying the same email too often + if (!emailCodeRequest) { + return { + error: true, + message: "Internal Server Error", + responsePayload: null, + }; + } + + cookies().set( + login_challenge, + JSON.stringify({ + loginType: LoginType.email, + loginId: emailCodeRequest, + value: email, + remember, + }), + { secure: true } + ); + + let params = new URLSearchParams({ + login_challenge, + }); + redirect(`/login/verification?${params}`); +} diff --git a/apps/consent/app/login/page.tsx b/apps/consent/app/login/page.tsx index 988f55988b..67d23df77f 100644 --- a/apps/consent/app/login/page.tsx +++ b/apps/consent/app/login/page.tsx @@ -20,7 +20,9 @@ import { LoginEmailResponse } from "./email-login.types" import authApi from "@/services/galoy-auth" -// this page is for login via email +import { OAuth2LoginRequest, OAuth2RedirectTo } from "@ory/hydra-client"; +import EmailLoginForm from "./email-login-form"; + interface LoginProps { login_challenge: string } @@ -104,6 +106,7 @@ async function submitForm(formData: FormData): Promise { const { login_challenge } = searchParams @@ -147,63 +150,7 @@ const Login = async ({ searchParams }: { searchParams: LoginProps }) => { Enter your Blink Account ID to sign in to this application. - - - -
- -
- or -
-
- -

Sign in with phone

- -
-
-
- - Next - - - Cancel - -
-
+ ) diff --git a/apps/consent/app/login/phone/form.tsx b/apps/consent/app/login/phone/form.tsx index 6b565df215..457e1c308f 100644 --- a/apps/consent/app/login/phone/form.tsx +++ b/apps/consent/app/login/phone/form.tsx @@ -28,6 +28,12 @@ import { SubmitValue } from "@/app/index.types" import "react-phone-number-input/style.css" // eslint-disable-next-line import/no-unassigned-import import "./phone-input-styles.css" +"use client"; +// @ts-ignore-next-line no-implicit-any error +import { experimental_useFormState as useFormState } from "react-dom"; +import "react-phone-number-input/style.css"; +import "./phone-input-styles.css"; +import SelectComponent from "@/app/components/select"; interface LoginFormProps { login_challenge: string @@ -51,14 +57,15 @@ const LoginForm: React.FC = ({ login_challenge, countryCodes }) login_challenge: null, phone: null, remember: null, + channel: null, }, }, }, ) if (state.error) { - toast.error(state.message) - state.error = null + toast.error(state.message); + state.error = null; } const handlePhoneNumberChange = (value?: E164Number | undefined) => { @@ -98,6 +105,12 @@ const LoginForm: React.FC = ({ login_challenge, countryCodes }) name="phone" onChange={handlePhoneNumberChange} /> +
- ); -}; + ) +} -export default InputComponent; +export default InputComponent diff --git a/apps/consent/app/components/main-container/index.tsx b/apps/consent/app/components/main-container/index.tsx index 419331ec09..cda502f690 100644 --- a/apps/consent/app/components/main-container/index.tsx +++ b/apps/consent/app/components/main-container/index.tsx @@ -9,7 +9,7 @@ const MainContent: React.FC = ({ children }) => {
{children}
- ); + ) } export default MainContent diff --git a/apps/consent/app/components/select.tsx b/apps/consent/app/components/select.tsx index ddc0760c71..cf56d517cf 100644 --- a/apps/consent/app/components/select.tsx +++ b/apps/consent/app/components/select.tsx @@ -1,9 +1,9 @@ -import React, { SelectHTMLAttributes } from "react"; +import React, { SelectHTMLAttributes } from "react" interface SelectProps extends SelectHTMLAttributes { - label?: string; - id: string; - options: string[]; + label?: string + id: string + options: string[] } const SelectComponent: React.FC = ({ @@ -41,7 +41,7 @@ const SelectComponent: React.FC = ({ ))} - ); -}; + ) +} -export default SelectComponent; +export default SelectComponent diff --git a/apps/consent/app/error-handler.ts b/apps/consent/app/error-handler.ts index bd05f59b0f..b1b47c7652 100644 --- a/apps/consent/app/error-handler.ts +++ b/apps/consent/app/error-handler.ts @@ -1,34 +1,39 @@ -import axios from "axios"; +import axios from "axios" interface ErrorResponse { - error: boolean; - message: string; - responsePayload: null; + error: boolean + message: string + responsePayload: null } const errorMessages: { [key: string]: string } = { - UserCodeAttemptIpRateLimiterExceededError: "Your rate limit exceeded", -}; + UserCodeAttemptIpRateLimiterExceededError: + "Your rate limit exceeded, please try after some time.", + UserCodeAttemptIdentifierRateLimiterExceededError: + "Your rate limit exceeded, please try after some time.", +} +/* eslint @typescript-eslint/ban-ts-comment: "off" */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export const handleAxiosError = (err: any): ErrorResponse => { if (axios.isAxiosError(err) && err.response) { - const errorCode = err.response?.data?.error?.name; + const errorCode = err.response?.data?.error?.name const errorMessage = - errorCode && errorMessages.hasOwnProperty(errorCode) + errorCode && Object.prototype.hasOwnProperty.call(errorMessages, errorCode) ? errorMessages[errorCode as keyof typeof errorMessages] - : errorCode || err?.response?.data?.error; - console.error("Error:", errorMessage); + : errorCode || err?.response?.data?.error + console.error("Error:", errorMessage) return { error: true, message: errorMessage, responsePayload: null, - }; + } } - console.error("An unknown error occurred", err); + console.error("An unknown error occurred", err) return { error: true, message: "An unknown error occurred", responsePayload: null, - }; -}; + } +} diff --git a/apps/consent/app/layout.tsx b/apps/consent/app/layout.tsx index a0437f6d9c..d418641185 100644 --- a/apps/consent/app/layout.tsx +++ b/apps/consent/app/layout.tsx @@ -1,10 +1,13 @@ -import "./globals.css"; -import "react-toastify/dist/ReactToastify.css"; -import Script from "next/script"; -import type { Metadata } from "next"; -import { Inter_Tight } from "next/font/google"; -import { ToastContainer } from "react-toastify"; -import Theme from "./components/next-themes-provider"; +// eslint-disable-next-line import/no-unassigned-import +import "./globals.css" +// eslint-disable-next-line import/no-unassigned-import +import "react-toastify/dist/ReactToastify.css" +import Script from "next/script" +import type { Metadata } from "next" +import { Inter_Tight } from "next/font/google" +import { ToastContainer } from "react-toastify" + +import Theme from "./components/next-themes-provider" const inter = Inter_Tight({ subsets: ["latin"] }) export const metadata: Metadata = { diff --git a/apps/consent/app/login/email-login-form.tsx b/apps/consent/app/login/email-login-form.tsx index 28d4df2c5b..62deff454a 100644 --- a/apps/consent/app/login/email-login-form.tsx +++ b/apps/consent/app/login/email-login-form.tsx @@ -1,30 +1,33 @@ -"use client"; -import React from "react"; -// @ts-ignore-next-line no-implicit-any error -import { experimental_useFormState as useFormState } from "react-dom"; -import InputComponent from "../components/input-component"; -import Link from "next/link"; -import FormComponent from "../components/form-component"; -import Separator from "../components/separator"; -import PrimaryButton from "../components/button/primary-button-component"; -import SecondaryButton from "../components/button/secondary-button-component"; -import { SubmitValue } from "../index.types"; -import { submitForm } from "./email-login-server-action"; -import { toast } from "react-toastify"; +"use client" +import React from "react" +/* eslint @typescript-eslint/ban-ts-comment: "off" */ +// @ts-ignore-next-line error +import { experimental_useFormState as useFormState } from "react-dom" +import Link from "next/link" +import { toast } from "react-toastify" + +import InputComponent from "../components/input-component" +import FormComponent from "../components/form-component" +import Separator from "../components/separator" +import PrimaryButton from "../components/button/primary-button-component" +import SecondaryButton from "../components/button/secondary-button-component" +import { SubmitValue } from "../index.types" + +import { submitForm } from "./email-login-server-action" // this page is for login via email interface LoginProps { - login_challenge: string; + login_challenge: string } const EmailLoginForm = ({ login_challenge }: LoginProps) => { const [state, formAction] = useFormState(submitForm, { error: null, message: null, - }); + }) if (state.error) { - toast.error(state.message); - state.error = null; + toast.error(state.message) + state.error = null } return ( @@ -85,6 +88,6 @@ const EmailLoginForm = ({ login_challenge }: LoginProps) => { - ); -}; -export default EmailLoginForm; + ) +} +export default EmailLoginForm diff --git a/apps/consent/app/login/email-login-server-action.ts b/apps/consent/app/login/email-login-server-action.ts index 053b77c633..8b83bb05f9 100644 --- a/apps/consent/app/login/email-login-server-action.ts +++ b/apps/consent/app/login/email-login-server-action.ts @@ -1,28 +1,30 @@ -"use server"; -import { redirect } from "next/navigation"; -import { hydraClient } from "../../services/hydra"; -import { cookies } from "next/headers"; -import authApi from "@/services/galoy-auth"; -import { LoginType, SubmitValue } from "../index.types"; -import { LoginEmailResponse } from "./email-login.types"; -import { headers } from "next/headers"; -import { handleAxiosError } from "@/app/error-handler"; +"use server" +import { redirect } from "next/navigation" +import { cookies, headers } from "next/headers" + +import { hydraClient } from "../../services/hydra" +import { LoginType, SubmitValue } from "../index.types" + +import { LoginEmailResponse } from "./email-login.types" + +import authApi from "@/services/galoy-auth" +import { handleAxiosError } from "@/app/error-handler" // this page is for login via email export async function submitForm( _prevState: unknown, - formData: FormData + formData: FormData, ): Promise { - const headersList = headers(); + const headersList = headers() const customHeaders = { "x-real-ip": headersList.get("x-real-ip"), "x-forwarded-for": headersList.get("x-forwarded-for"), - }; + } - const login_challenge = formData.get("login_challenge"); - const submitValue = formData.get("submit"); - const email = formData.get("email"); - const remember = String(formData.get("remember") === "1"); + const login_challenge = formData.get("login_challenge") + const submitValue = formData.get("submit") + const email = formData.get("email") + const remember = String(formData.get("remember") === "1") if ( !login_challenge || !submitValue || @@ -30,32 +32,32 @@ export async function submitForm( typeof login_challenge !== "string" || typeof submitValue !== "string" ) { - throw new Error("Invalid Value"); + throw new Error("Invalid Value") } if (submitValue === SubmitValue.denyAccess) { - console.log("User denied access"); + console.log("User denied access") const response = await hydraClient.rejectOAuth2LoginRequest({ loginChallenge: login_challenge, rejectOAuth2Request: { error: "access_denied", error_description: "The resource owner denied the request", }, - }); - redirect(response.data.redirect_to); + }) + redirect(response.data.redirect_to) } if (!email || typeof email !== "string") { - console.error("Invalid Values for email"); - throw new Error("Invalid Email Value"); + console.error("Invalid Values for email") + throw new Error("Invalid Email Value") } - let emailCodeRequest; + let emailCodeRequest try { - emailCodeRequest = await authApi.requestEmailCode(email, customHeaders); + emailCodeRequest = await authApi.requestEmailCode(email, customHeaders) } catch (err) { - console.error("Error in requestEmailCode", err); - return handleAxiosError(err); + console.error("Error in requestEmailCode", err) + return handleAxiosError(err) } // TODO: manage error on ip rate limit @@ -65,7 +67,7 @@ export async function submitForm( error: true, message: "Internal Server Error", responsePayload: null, - }; + } } cookies().set( @@ -76,11 +78,11 @@ export async function submitForm( value: email, remember, }), - { secure: true } - ); + { secure: true }, + ) - let params = new URLSearchParams({ + const params = new URLSearchParams({ login_challenge, - }); - redirect(`/login/verification?${params}`); + }) + redirect(`/login/verification?${params}`) } diff --git a/apps/consent/app/login/page.tsx b/apps/consent/app/login/page.tsx index 67d23df77f..cb5219df3c 100644 --- a/apps/consent/app/login/page.tsx +++ b/apps/consent/app/login/page.tsx @@ -1,112 +1,21 @@ import { redirect } from "next/navigation" import React from "react" -import Link from "next/link" -import { headers, cookies } from "next/headers" +import { cookies } from "next/headers" import { hydraClient } from "../../services/hydra" -import InputComponent from "../components/input-component" -import Card from "../components/card" import MainContent from "../components/main-container" import Logo from "../components/logo" import Heading from "../components/heading" import SubHeading from "../components/sub-heading" -import FormComponent from "../components/form-component" -import Separator from "../components/separator" -import PrimaryButton from "../components/button/primary-button-component" -import SecondaryButton from "../components/button/secondary-button-component" -import { LoginType, SubmitValue } from "../index.types" - -import { LoginEmailResponse } from "./email-login.types" -import authApi from "@/services/galoy-auth" +import Card from "../components/card" -import { OAuth2LoginRequest, OAuth2RedirectTo } from "@ory/hydra-client"; -import EmailLoginForm from "./email-login-form"; +import EmailLoginForm from "./email-login-form" interface LoginProps { login_challenge: string } -async function submitForm(formData: FormData): Promise { - "use server" - - const headersList = headers() - const customHeaders = { - "x-real-ip": headersList.get("x-real-ip"), - "x-forwarded-for": headersList.get("x-forwarded-for"), - } - - const login_challenge = formData.get("login_challenge") - const submitValue = formData.get("submit") - const email = formData.get("email") - const remember = String(formData.get("remember") === "1") - - if ( - !login_challenge || - !submitValue || - !remember || - typeof login_challenge !== "string" || - typeof submitValue !== "string" - ) { - throw new Error("Invalid Value") - } - - if (submitValue === SubmitValue.denyAccess) { - console.log("User denied access") - const response = await hydraClient.rejectOAuth2LoginRequest( - { - loginChallenge: login_challenge, - rejectOAuth2Request: { - error: "access_denied", - error_description: "The resource owner denied the request", - }, - }, - { - headers: { - Cookie: cookies().toString(), - }, - }, - ) - redirect(response.data.redirect_to) - } - - if (!email || typeof email !== "string") { - console.error("Invalid Values for email") - throw new Error("Invalid Email Value") - } - - let emailCodeRequest - try { - emailCodeRequest = await authApi.requestEmailCode(email, customHeaders) - } catch (err) { - console.error("error while calling emailRequest Code", err) - } - - if (!emailCodeRequest) { - throw new Error("Request failed to get email code") - } - - // TODO: manage error on ip rate limit - // TODO: manage error when trying the same email too often - - cookies().set( - login_challenge, - JSON.stringify({ - loginType: LoginType.email, - loginId: emailCodeRequest, - value: email, - remember, - }), - { secure: true }, - ) - - const params = new URLSearchParams({ - login_challenge, - }) - redirect(`/login/verification?${params}`) -} - - const Login = async ({ searchParams }: { searchParams: LoginProps }) => { const { login_challenge } = searchParams diff --git a/apps/consent/app/login/phone/form.tsx b/apps/consent/app/login/phone/form.tsx index 457e1c308f..80710dd2e6 100644 --- a/apps/consent/app/login/phone/form.tsx +++ b/apps/consent/app/login/phone/form.tsx @@ -28,12 +28,8 @@ import { SubmitValue } from "@/app/index.types" import "react-phone-number-input/style.css" // eslint-disable-next-line import/no-unassigned-import import "./phone-input-styles.css" -"use client"; -// @ts-ignore-next-line no-implicit-any error -import { experimental_useFormState as useFormState } from "react-dom"; -import "react-phone-number-input/style.css"; -import "./phone-input-styles.css"; -import SelectComponent from "@/app/components/select"; + +import SelectComponent from "@/app/components/select" interface LoginFormProps { login_challenge: string @@ -64,8 +60,8 @@ const LoginForm: React.FC = ({ login_challenge, countryCodes }) ) if (state.error) { - toast.error(state.message); - state.error = null; + toast.error(state.message) + state.error = null } const handlePhoneNumberChange = (value?: E164Number | undefined) => { diff --git a/apps/consent/app/login/verification/form.tsx b/apps/consent/app/login/verification/form.tsx index e707323fc5..06411536cd 100644 --- a/apps/consent/app/login/verification/form.tsx +++ b/apps/consent/app/login/verification/form.tsx @@ -38,14 +38,13 @@ const VerificationForm: React.FC = ({ }) if (stateVerificationCode.error) { - toast.error(stateVerificationCode.message); + toast.error(stateVerificationCode.message) stateVerificationCode.message = null } if (stateTwoFA.error) { - toast.error(stateTwoFA.message); - stateTwoFA.message = null; - + toast.error(stateTwoFA.message) + stateTwoFA.message = null } return ( diff --git a/apps/consent/app/login/verification/server-actions.ts b/apps/consent/app/login/verification/server-actions.ts index 76ab8d1983..942caea404 100644 --- a/apps/consent/app/login/verification/server-actions.ts +++ b/apps/consent/app/login/verification/server-actions.ts @@ -1,11 +1,13 @@ -"use server"; -import { handleAxiosError } from "@/app/error-handler"; -import { getUserId } from "@/app/graphql/queries/me-query"; -import { LoginType } from "@/app/index.types"; -import authApi from "@/services/galoy-auth"; -import { hydraClient } from "@/services/hydra"; -import { headers } from "next/headers"; -import { redirect } from "next/navigation"; +"use server" +import { headers } from "next/headers" + +import { redirect } from "next/navigation" + +import { handleAxiosError } from "@/app/error-handler" +import { getUserId } from "@/app/graphql/queries/me-query" +import { LoginType } from "@/app/index.types" +import authApi from "@/services/galoy-auth" +import { hydraClient } from "@/services/hydra" export const submitFormTotp = async (_prevState: unknown, form: FormData) => { const headersList = headers() @@ -33,8 +35,8 @@ export const submitFormTotp = async (_prevState: unknown, form: FormData) => { try { await authApi.validateTotp(totpCode, authToken, customHeaders) } catch (err) { - console.error("error in 'totp/validate' ", err); - return handleAxiosError(err); + console.error("error in 'totp/validate' ", err) + return handleAxiosError(err) } const userId = await getUserId(authToken) @@ -99,8 +101,8 @@ export const submitForm = async (_prevState: unknown, form: FormData) => { totpRequired = loginResponse.totpRequired userId = loginResponse.id } catch (err) { - console.error("error in 'phone/login' ", err); - return handleAxiosError(err); + console.error("error in 'phone/login' ", err) + return handleAxiosError(err) } } else if (loginType === LoginType.email) { try { @@ -109,8 +111,8 @@ export const submitForm = async (_prevState: unknown, form: FormData) => { totpRequired = loginResponse.totpRequired userId = loginResponse.id } catch (err) { - console.error("error in 'email/login' ", err); - return handleAxiosError(err); + console.error("error in 'email/login' ", err) + return handleAxiosError(err) } } else { throw new Error("Invalid Value") From a9d07c8fa9f309b96d6dcb47ac7109ff0b673a8c Mon Sep 17 00:00:00 2001 From: Siddharth Date: Tue, 24 Oct 2023 12:30:58 +0530 Subject: [PATCH 04/12] fix: lint errors, cookie forwarding --- .../app/login/email-login-server-action.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/consent/app/login/email-login-server-action.ts b/apps/consent/app/login/email-login-server-action.ts index 8b83bb05f9..22437043bd 100644 --- a/apps/consent/app/login/email-login-server-action.ts +++ b/apps/consent/app/login/email-login-server-action.ts @@ -34,16 +34,23 @@ export async function submitForm( ) { throw new Error("Invalid Value") } - + if (submitValue === SubmitValue.denyAccess) { console.log("User denied access") - const response = await hydraClient.rejectOAuth2LoginRequest({ - loginChallenge: login_challenge, - rejectOAuth2Request: { - error: "access_denied", - error_description: "The resource owner denied the request", + const response = await hydraClient.rejectOAuth2LoginRequest( + { + loginChallenge: login_challenge, + rejectOAuth2Request: { + error: "access_denied", + error_description: "The resource owner denied the request", + }, + }, + { + headers: { + Cookie: cookies().toString(), + }, }, - }) + ) redirect(response.data.redirect_to) } From 42fb3021170c4f7aac0e7dec524be580d7d347e2 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Tue, 24 Oct 2023 12:31:26 +0530 Subject: [PATCH 05/12] fix: lint errors, cookie forwarding --- apps/consent/app/login/email-login-server-action.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/consent/app/login/email-login-server-action.ts b/apps/consent/app/login/email-login-server-action.ts index 22437043bd..b48921dda6 100644 --- a/apps/consent/app/login/email-login-server-action.ts +++ b/apps/consent/app/login/email-login-server-action.ts @@ -34,7 +34,7 @@ export async function submitForm( ) { throw new Error("Invalid Value") } - + if (submitValue === SubmitValue.denyAccess) { console.log("User denied access") const response = await hydraClient.rejectOAuth2LoginRequest( From b693f0146e696444ae9ce3337e75bfbff4322106 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Tue, 24 Oct 2023 13:04:04 +0530 Subject: [PATCH 06/12] fix: lint errors --- apps/consent/services/galoy-auth/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/consent/services/galoy-auth/index.ts b/apps/consent/services/galoy-auth/index.ts index 6afe04f7d2..090db52812 100644 --- a/apps/consent/services/galoy-auth/index.ts +++ b/apps/consent/services/galoy-auth/index.ts @@ -72,8 +72,8 @@ const authApi = { validationCode: string, secCode: string, channel: string, - customHeaders?: object - ): Promise => { + customHeaders?: object, + ) => { const response = await axiosInstance.post( "/phone/code", { From f0a2f2bfbd69b4b4d5b8607389973a331b28557a Mon Sep 17 00:00:00 2001 From: Siddharth Date: Tue, 24 Oct 2023 15:40:13 +0530 Subject: [PATCH 07/12] chore: captcha dev mode changes rebase --- apps/consent/app/login/phone/server-actions.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/consent/app/login/phone/server-actions.ts b/apps/consent/app/login/phone/server-actions.ts index ad4098ad6a..d790ff180f 100644 --- a/apps/consent/app/login/phone/server-actions.ts +++ b/apps/consent/app/login/phone/server-actions.ts @@ -12,6 +12,7 @@ import { env } from "@/env" ;("use server") import { handleAxiosError } from "@/app/error-handler" +import { env } from "@/env" export const getCaptchaChallenge = async ( _prevState: unknown, From 44a92981dc3b2b625439ecfdb986504df5761235 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Tue, 24 Oct 2023 17:20:01 +0530 Subject: [PATCH 08/12] chore: remove unnecessary comments --- apps/consent/app/login/email-login-form.tsx | 1 - apps/consent/app/login/email-login-server-action.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/apps/consent/app/login/email-login-form.tsx b/apps/consent/app/login/email-login-form.tsx index 62deff454a..34632f2130 100644 --- a/apps/consent/app/login/email-login-form.tsx +++ b/apps/consent/app/login/email-login-form.tsx @@ -14,7 +14,6 @@ import SecondaryButton from "../components/button/secondary-button-component" import { SubmitValue } from "../index.types" import { submitForm } from "./email-login-server-action" -// this page is for login via email interface LoginProps { login_challenge: string } diff --git a/apps/consent/app/login/email-login-server-action.ts b/apps/consent/app/login/email-login-server-action.ts index b48921dda6..cb46f6fe1b 100644 --- a/apps/consent/app/login/email-login-server-action.ts +++ b/apps/consent/app/login/email-login-server-action.ts @@ -9,7 +9,6 @@ import { LoginEmailResponse } from "./email-login.types" import authApi from "@/services/galoy-auth" import { handleAxiosError } from "@/app/error-handler" -// this page is for login via email export async function submitForm( _prevState: unknown, From c5114fb8238fff1dbef0260b9897b63807cbeb10 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Thu, 26 Oct 2023 20:44:40 +0530 Subject: [PATCH 09/12] chore: addressing comments rebase --- apps/consent/app/error-handler.ts | 4 +--- .../consent/app/login/email-login-server-action.ts | 2 +- apps/consent/app/login/phone/server-actions.ts | 14 +++++++++++--- .../app/login/verification/server-actions.ts | 6 +++--- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/apps/consent/app/error-handler.ts b/apps/consent/app/error-handler.ts index b1b47c7652..db1a4574db 100644 --- a/apps/consent/app/error-handler.ts +++ b/apps/consent/app/error-handler.ts @@ -13,9 +13,7 @@ const errorMessages: { [key: string]: string } = { "Your rate limit exceeded, please try after some time.", } -/* eslint @typescript-eslint/ban-ts-comment: "off" */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const handleAxiosError = (err: any): ErrorResponse => { +export const handleAxiosError = (err: unknown): ErrorResponse => { if (axios.isAxiosError(err) && err.response) { const errorCode = err.response?.data?.error?.name const errorMessage = diff --git a/apps/consent/app/login/email-login-server-action.ts b/apps/consent/app/login/email-login-server-action.ts index cb46f6fe1b..3d0adf0fbb 100644 --- a/apps/consent/app/login/email-login-server-action.ts +++ b/apps/consent/app/login/email-login-server-action.ts @@ -58,7 +58,7 @@ export async function submitForm( throw new Error("Invalid Email Value") } - let emailCodeRequest + let emailCodeRequest: string | null try { emailCodeRequest = await authApi.requestEmailCode(email, customHeaders) } catch (err) { diff --git a/apps/consent/app/login/phone/server-actions.ts b/apps/consent/app/login/phone/server-actions.ts index d790ff180f..b066e3bf3b 100644 --- a/apps/consent/app/login/phone/server-actions.ts +++ b/apps/consent/app/login/phone/server-actions.ts @@ -72,14 +72,16 @@ export const getCaptchaChallenge = async ( } } - let res + let res: { + id: string + challengeCode: string + } | null try { res = await authApi.requestPhoneCaptcha(customHeaders) } catch (err) { console.error("error in requestPhoneCaptcha", err) return handleAxiosError(err) } - if (!res) { return { error: true, @@ -144,8 +146,14 @@ export const sendPhoneCode = async ( const phone = formData.phone const remember = String(formData.remember) === "true" const channel = formData.channel ?? "SMS" - let res + let res: { + data?: { + success?: boolean + } + status?: number + } | null + try { res = await authApi.requestPhoneCode( phone, diff --git a/apps/consent/app/login/verification/server-actions.ts b/apps/consent/app/login/verification/server-actions.ts index 942caea404..e3b3c6180f 100644 --- a/apps/consent/app/login/verification/server-actions.ts +++ b/apps/consent/app/login/verification/server-actions.ts @@ -75,9 +75,9 @@ export const submitForm = async (_prevState: unknown, form: FormData) => { const value = form.get("value") const loginId = form.get("loginId") - let authToken - let totpRequired - let userId + let authToken: string | null + let totpRequired: boolean | null + let userId: string | null if ((loginType === LoginType.email && !loginId) || typeof loginId !== "string") { throw new Error("Invalid Values") From dab0b33e2806658c77939c071a2b04bc34afd4d6 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Thu, 26 Oct 2023 22:08:12 +0530 Subject: [PATCH 10/12] chore: remove default val from NODE_ENV, misc changes --- apps/consent/app/login/phone/server-actions.ts | 1 - apps/dashboard/.env | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/consent/app/login/phone/server-actions.ts b/apps/consent/app/login/phone/server-actions.ts index b066e3bf3b..0f7a7d330f 100644 --- a/apps/consent/app/login/phone/server-actions.ts +++ b/apps/consent/app/login/phone/server-actions.ts @@ -153,7 +153,6 @@ export const sendPhoneCode = async ( } status?: number } | null - try { res = await authApi.requestPhoneCode( phone, diff --git a/apps/dashboard/.env b/apps/dashboard/.env index 5a044b62cf..987663c4b4 100644 --- a/apps/dashboard/.env +++ b/apps/dashboard/.env @@ -1,5 +1,5 @@ # REPLACE THIS IT IS FOR TESTING -NEXTAUTH_URL=https://39a0-2405-201-301c-5b67-8cea-1030-d56-e0b3.ngrok-free.app +NEXTAUTH_URL=http://localhost:3001 NEXTAUTH_SECRET="thisismysecret" # 2db7666c39074da4b399e8b5116ef2c6 # 2cc1869e52ad47df848a6519b63bb4f4 \ No newline at end of file From 33b532ce1fe461ca66092279b4f87867f3ca1919 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Fri, 27 Oct 2023 14:32:39 +0530 Subject: [PATCH 11/12] chore: misc changes --- apps/dashboard/.env | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 apps/dashboard/.env diff --git a/apps/dashboard/.env b/apps/dashboard/.env deleted file mode 100644 index 987663c4b4..0000000000 --- a/apps/dashboard/.env +++ /dev/null @@ -1,5 +0,0 @@ -# REPLACE THIS IT IS FOR TESTING -NEXTAUTH_URL=http://localhost:3001 -NEXTAUTH_SECRET="thisismysecret" -# 2db7666c39074da4b399e8b5116ef2c6 -# 2cc1869e52ad47df848a6519b63bb4f4 \ No newline at end of file From 5db3f44d7b9c1bc70358024e9f1e96ec5fec7623 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Sat, 28 Oct 2023 10:04:47 +0530 Subject: [PATCH 12/12] fix: dublicate imports --- apps/consent/app/login/phone/server-actions.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/consent/app/login/phone/server-actions.ts b/apps/consent/app/login/phone/server-actions.ts index 0f7a7d330f..017d81d57b 100644 --- a/apps/consent/app/login/phone/server-actions.ts +++ b/apps/consent/app/login/phone/server-actions.ts @@ -8,9 +8,6 @@ import { GetCaptchaChallengeResponse, SendPhoneCodeResponse } from "./phone-logi import { LoginType, SubmitValue } from "@/app/index.types" import authApi from "@/services/galoy-auth" import { hydraClient } from "@/services/hydra" -import { env } from "@/env" -;("use server") - import { handleAxiosError } from "@/app/error-handler" import { env } from "@/env"