Fix some logic handling error
This commit is contained in:
		
							parent
							
								
									da01e40550
								
							
						
					
					
						commit
						d33788e2b1
					
				| @ -23,7 +23,8 @@ class ErrorBoundary extends Component<Props, State> { | ||||
|   public componentDidCatch(error: Error, errorInfo: ErrorInfo) { | ||||
|     console.error("Uncaught error:", error, errorInfo); | ||||
| 
 | ||||
|     captureException(error); | ||||
|     const errorMessage = error.message || error; | ||||
|     captureException(errorMessage); | ||||
|   } | ||||
| 
 | ||||
|   public render() { | ||||
|  | ||||
| @ -2,12 +2,11 @@ | ||||
| const { withSentryConfig } = require("@sentry/nextjs"); | ||||
| 
 | ||||
| const nextConfig = { | ||||
|   sentry: { | ||||
|     hideSourceMaps: true, | ||||
|   }, | ||||
|   api: { | ||||
|     externalResolver: true, | ||||
|   }, | ||||
|   ...(!!process.env.NEXT_PUBLIC_SENTRY_DSN && { | ||||
|     sentry: { | ||||
|       hideSourceMaps: true, | ||||
|     }, | ||||
|   }), | ||||
|   reactStrictMode: false, | ||||
|   swcMinify: true, | ||||
|   compiler: { | ||||
|  | ||||
| @ -1,8 +1,7 @@ | ||||
| import { captureException } from "@sentry/nextjs"; | ||||
| import { withIronSessionApiRoute } from "iron-session/next"; | ||||
| import type { NextApiRequest, NextApiResponse } from "next"; | ||||
| import { ironOptions } from "../../iron.config"; | ||||
| import { IcnsVerificationResponse } from "../../types"; | ||||
| import { request } from "../../utils/url"; | ||||
| 
 | ||||
| export default withIronSessionApiRoute(async function handler( | ||||
|   req: NextApiRequest, | ||||
| @ -10,30 +9,42 @@ export default withIronSessionApiRoute(async function handler( | ||||
| ) { | ||||
|   try { | ||||
|     if (!process.env.ICNS_VERIFIER_ORIGIN_LIST) { | ||||
|       console.log(".env is not set"); | ||||
|       const errorMessage = ".env is not set"; | ||||
|       console.error(errorMessage); | ||||
|       captureException(errorMessage); | ||||
|       return res.status(500).json({ error: "Internal server error" }); | ||||
|     } | ||||
|     const verifierOriginList = process.env.ICNS_VERIFIER_ORIGIN_LIST.split(","); | ||||
| 
 | ||||
|     const verificationList = await Promise.allSettled( | ||||
|       verifierOriginList.map((verfierOrigin) => | ||||
|         request<IcnsVerificationResponse>( | ||||
|           `${verfierOrigin}/api/verify_twitter`, | ||||
|           { | ||||
|       verifierOriginList.map(async (verfierOrigin) => | ||||
|         ( | ||||
|           await fetch(`${verfierOrigin}/api/verify_twitter`, { | ||||
|             method: "post", | ||||
|             headers: { | ||||
|               "Content-Type": "application/json", | ||||
|             }, | ||||
|             body: JSON.stringify(req.body), | ||||
|           }, | ||||
|         ), | ||||
|           }) | ||||
|         ).json(), | ||||
|       ), | ||||
|     ); | ||||
| 
 | ||||
|     const errorTrimmedVerificationList = verificationList.map( | ||||
|       (verification) => ({ | ||||
|         ...verification, | ||||
|         ...(verification.status === "rejected" && { | ||||
|           reason: verification.reason.message || verification.reason, | ||||
|         }), | ||||
|       }), | ||||
|     ); | ||||
| 
 | ||||
|     res.status(200).json({ | ||||
|       verificationList, | ||||
|       verificationList: errorTrimmedVerificationList, | ||||
|     }); | ||||
|   } catch (error) { | ||||
|     console.error(error); | ||||
|     captureException(error); | ||||
|     res.status(500).json({ error: "Internal server error" }); | ||||
|   } | ||||
| }, | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| import type { NextApiRequest, NextApiResponse } from "next"; | ||||
| import { captureException } from "@sentry/nextjs"; | ||||
| import { withIronSessionApiRoute } from "iron-session/next"; | ||||
| import { request } from "../../utils/url"; | ||||
| import { ironOptions } from "../../iron.config"; | ||||
| import type { NextApiRequest, NextApiResponse } from "next"; | ||||
| import { twitterApiBaseUrl } from "../../constants/twitter"; | ||||
| import { ironOptions } from "../../iron.config"; | ||||
| 
 | ||||
| export default withIronSessionApiRoute(async function handler( | ||||
|   req: NextApiRequest, | ||||
| @ -45,53 +45,60 @@ export default withIronSessionApiRoute(async function handler( | ||||
|       params.append("code_verifier", req.session.code_verifier); | ||||
|     } | ||||
| 
 | ||||
|     const { access_token: accessToken, refresh_token } = | ||||
|       await request<TwitterOAuth2TokenResponse>( | ||||
|         `${twitterApiBaseUrl}/oauth2/token`, | ||||
|         { | ||||
|           method: "post", | ||||
|           headers: { | ||||
|             "Content-Type": "application/x-www-form-urlencoded", | ||||
|             Authorization: `Basic ${Buffer.from( | ||||
|               `${process.env.TWITTER_CLIENT_ID}:${process.env.TWITTER_CLIENT_SECRET}`, | ||||
|             ).toString("base64")}`,
 | ||||
|           }, | ||||
|           body: params, | ||||
|     const { | ||||
|       access_token: accessToken, | ||||
|       refresh_token, | ||||
|     }: TwitterOAuth2TokenResponse = await ( | ||||
|       await fetch(`${twitterApiBaseUrl}/oauth2/token`, { | ||||
|         method: "post", | ||||
|         headers: { | ||||
|           "Content-Type": "application/x-www-form-urlencoded", | ||||
|           Authorization: `Basic ${Buffer.from( | ||||
|             `${process.env.TWITTER_CLIENT_ID}:${process.env.TWITTER_CLIENT_SECRET}`, | ||||
|           ).toString("base64")}`,
 | ||||
|         }, | ||||
|       ); | ||||
|         body: params, | ||||
|       }) | ||||
|     ).json(); | ||||
| 
 | ||||
|     req.session.refresh_token = refresh_token; | ||||
|     await req.session.save(); | ||||
|     const { | ||||
|       data: { | ||||
|         id, | ||||
|         username, | ||||
|         name, | ||||
|         profile_image_url, | ||||
|         description, | ||||
|         public_metrics, | ||||
|       }, | ||||
|     } = await request<TwitterUsersMeResponse>( | ||||
|       `${twitterApiBaseUrl}/users/me?user.fields=profile_image_url,public_metrics,description`, | ||||
|       { | ||||
|         headers: { | ||||
|           Authorization: `Bearer ${accessToken}`, | ||||
|     const { data, title }: TwitterUsersMeResponse = await ( | ||||
|       await fetch( | ||||
|         `${twitterApiBaseUrl}/users/me?user.fields=profile_image_url,public_metrics,description`, | ||||
|         { | ||||
|           headers: { | ||||
|             Authorization: `Bearer ${accessToken}`, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
|     ); | ||||
|       ) | ||||
|     ).json(); | ||||
|     const { | ||||
|       id, | ||||
|       username, | ||||
|       name, | ||||
|       profile_image_url, | ||||
|       description, | ||||
|       public_metrics, | ||||
|     } = data || {}; | ||||
| 
 | ||||
|     res.status(200).json({ | ||||
|       accessToken, | ||||
|       id, | ||||
|       username, | ||||
|       name, | ||||
|       profile_image_url: profile_image_url.replace("normal.jpg", "400x400.jpg"), | ||||
|       profile_image_url: profile_image_url?.replace( | ||||
|         "normal.jpg", | ||||
|         "400x400.jpg", | ||||
|       ), | ||||
|       description, | ||||
|       public_metrics, | ||||
|       error: title, | ||||
|     }); | ||||
|   } catch (error) { | ||||
|   } catch (error: any) { | ||||
|     console.error(error); | ||||
|     res.status(500).json({ error: "Internal server error " }); | ||||
|     captureException(error); | ||||
|     res.status(500).json({ error: "Internal Server Error" }); | ||||
|   } | ||||
| }, | ||||
| ironOptions); | ||||
| @ -105,7 +112,7 @@ interface TwitterOAuth2TokenResponse { | ||||
| } | ||||
| 
 | ||||
| interface TwitterUsersMeResponse { | ||||
|   data: { | ||||
|   data?: { | ||||
|     id: string; | ||||
|     username: string; | ||||
|     name: string; | ||||
| @ -113,6 +120,11 @@ interface TwitterUsersMeResponse { | ||||
|     description: string; | ||||
|     public_metrics: TwitterPublicMetrics; | ||||
|   }; | ||||
|   // Error data
 | ||||
|   title?: string; | ||||
|   detail?: string; | ||||
|   type?: string; | ||||
|   status?: string; | ||||
| } | ||||
| 
 | ||||
| export interface TwitterPublicMetrics { | ||||
|  | ||||
| @ -1,13 +1,14 @@ | ||||
| import type { NextApiRequest, NextApiResponse } from "next"; | ||||
| import { captureException } from "@sentry/nextjs"; | ||||
| import crypto from "crypto"; | ||||
| import { withIronSessionApiRoute } from "iron-session/next"; | ||||
| import { base64URLEncode } from "../../utils/encoding"; | ||||
| import { buildQueryString } from "../../utils/url"; | ||||
| import { ironOptions } from "../../iron.config"; | ||||
| import type { NextApiRequest, NextApiResponse } from "next"; | ||||
| import { | ||||
|   twitterOAuthBaseUrl, | ||||
|   twitterOAuthScopes, | ||||
| } from "../../constants/twitter"; | ||||
| import { ironOptions } from "../../iron.config"; | ||||
| import { base64URLEncode } from "../../utils/encoding"; | ||||
| import { buildQueryString } from "../../utils/url"; | ||||
| 
 | ||||
| export default withIronSessionApiRoute(async function handler( | ||||
|   req: NextApiRequest, | ||||
| @ -46,6 +47,7 @@ export default withIronSessionApiRoute(async function handler( | ||||
|     res.status(200).json({ authUrl }); | ||||
|   } catch (error) { | ||||
|     console.error(error); | ||||
|     captureException(error); | ||||
|     res.status(500).json({ error: "Internal server error" }); | ||||
|   } | ||||
| }, | ||||
|  | ||||
| @ -239,13 +239,12 @@ export default function VerificationPage() { | ||||
|         } | ||||
|       } catch (error) { | ||||
|         if (error instanceof Error) { | ||||
|           if (error.message === TWITTER_LOGIN_ERROR) { | ||||
|             setErrorMessage({ message: TWITTER_LOGIN_ERROR, path: "/" }); | ||||
|             setErrorModalOpen(true); | ||||
|           } | ||||
|           setErrorMessage({ message: error.message, path: "/" }); | ||||
|           setErrorModalOpen(true); | ||||
|         } | ||||
| 
 | ||||
|         console.error(error); | ||||
|         captureException(error); | ||||
|       } finally { | ||||
|         setIsLoadingInit(false); | ||||
|       } | ||||
| @ -404,8 +403,7 @@ export default function VerificationPage() { | ||||
| 
 | ||||
|           if (verification.status === "rejected") { | ||||
|             if (verification.reason) { | ||||
|               const errorMessage = | ||||
|                 verification.reason.message || verification.reason; | ||||
|               const errorMessage = verification.reason; | ||||
|               captureException(errorMessage); | ||||
|             } | ||||
|           } | ||||
| @ -443,8 +441,6 @@ export default function VerificationPage() { | ||||
|           rest: REST_URL, | ||||
|         }; | ||||
| 
 | ||||
|         console.log(aminoMsgs); | ||||
| 
 | ||||
|         const simulated = await simulateMsgs( | ||||
|           chainInfo, | ||||
|           walletKey.bech32Address, | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { | ||||
|   IcnsVerificationResponse, | ||||
|   IcnsVerificationResponseOnFrontend, | ||||
|   TwitterAuthInfoResponse, | ||||
|   TwitterAuthUrlResponse, | ||||
| } from "../types"; | ||||
| @ -27,15 +27,18 @@ export const verifyTwitterAccount = async ( | ||||
|   accessToken: string, | ||||
| ) => { | ||||
|   return ( | ||||
|     await request<IcnsVerificationResponse>("/api/icns-verification", { | ||||
|       method: "post", | ||||
|       headers: { | ||||
|         "Content-Type": "application/json", | ||||
|     await request<IcnsVerificationResponseOnFrontend>( | ||||
|       "/api/icns-verification", | ||||
|       { | ||||
|         method: "post", | ||||
|         headers: { | ||||
|           "Content-Type": "application/json", | ||||
|         }, | ||||
|         body: JSON.stringify({ | ||||
|           claimer: claimer, | ||||
|           authToken: accessToken, | ||||
|         }), | ||||
|       }, | ||||
|       body: JSON.stringify({ | ||||
|         claimer: claimer, | ||||
|         authToken: accessToken, | ||||
|       }), | ||||
|     }) | ||||
|     ) | ||||
|   ).verificationList; | ||||
| }; | ||||
|  | ||||
| @ -38,6 +38,30 @@ export interface IcnsVerificationResponse { | ||||
|   )[]; | ||||
| } | ||||
| 
 | ||||
| export interface IcnsVerificationResponseOnFrontend { | ||||
|   verificationList: ( | ||||
|     | { | ||||
|         status: "fulfilled"; | ||||
|         value: { | ||||
|           errors: Error[]; | ||||
|           data: { | ||||
|             // JSON string
 | ||||
|             verifying_msg: string; | ||||
|             // Base64 encoded
 | ||||
|             public_key: string; | ||||
|             // Base64 encoded
 | ||||
|             signature: string; | ||||
|             algorithm: string; | ||||
|           }; | ||||
|         }; | ||||
|       } | ||||
|     | { | ||||
|         status: "rejected"; | ||||
|         reason: string; | ||||
|       } | ||||
|   )[]; | ||||
| } | ||||
| 
 | ||||
| export interface NameByTwitterIdQueryResponse { | ||||
|   data: { | ||||
|     name: string; | ||||
|  | ||||
							
								
								
									
										31
									
								
								utils/url.ts
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								utils/url.ts
									
									
									
									
									
								
							| @ -2,23 +2,32 @@ import { TwitterLoginSuccess } from "../types"; | ||||
| import { TWITTER_LOGIN_ERROR } from "../constants/error-message"; | ||||
| import { WALLET_INSTALL_URL } from "../constants/wallet"; | ||||
| 
 | ||||
| export function request<TResponse>( | ||||
| export async function request<TResponse>( | ||||
|   url: string, | ||||
|   config: RequestInit = {}, | ||||
|   customConfig?: { | ||||
|     isErrorIgnore?: boolean; | ||||
|   }, | ||||
| ): Promise<TResponse> { | ||||
|   return fetch(url, config) | ||||
|     .then((response) => { | ||||
|       if (!response.ok && !customConfig?.isErrorIgnore) { | ||||
|         throw new Error( | ||||
|           `This is an HTTP error: The status is ${response.status} ${response.statusText}`, | ||||
|         ); | ||||
|       } | ||||
|       return response.json(); | ||||
|     }) | ||||
|     .then((data) => data as TResponse); | ||||
|   const response = await fetch(url, config); | ||||
|   const data = await response.json(); | ||||
| 
 | ||||
|   if ( | ||||
|     (!response.ok || data.error || data.errors) && | ||||
|     !customConfig?.isErrorIgnore | ||||
|   ) { | ||||
|     const { error, errors } = data; | ||||
|     let errorMessage; | ||||
|     if (error && error.error) { | ||||
|       errorMessage = error.error_description; | ||||
|     } else { | ||||
|       errorMessage = | ||||
|         (error && error.toString()) || (errors && errors.toString()); | ||||
|     } | ||||
|     throw new Error(errorMessage); | ||||
|   } | ||||
| 
 | ||||
|   return data; | ||||
| } | ||||
| 
 | ||||
| export function buildQueryString(query: Record<string, any>): string { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user