| | |
| |
|
| | import axios, { AxiosError, AxiosResponse } from 'axios'; |
| | import fs from 'fs'; |
| | import fsPromises from 'fs/promises'; |
| | import path from 'path'; |
| | import { Request, Response } from 'express'; |
| |
|
| | console.log(`[Login Module] src/login.ts file is being evaluated. __dirname is: ${__dirname}`); |
| |
|
| | interface PastebinData { |
| | link?: string; |
| | [key: string]: any; |
| | } |
| |
|
| | interface LoginClientRequestBody { |
| | user: string; |
| | pass: string; |
| | } |
| |
|
| | interface LoginApiPayload { |
| | user: string; |
| | pass: string; |
| | } |
| |
|
| | interface LoginApiResponseData { |
| | token: string; |
| | userDetails: object; |
| | message: string; |
| | status: string; |
| | } |
| |
|
| | function isLoginClientRequestBody(body: any): body is LoginClientRequestBody { |
| | if (body && typeof body === 'object' && |
| | typeof body.user === 'string' && body.user.length > 0 && |
| | typeof body.pass === 'string' && body.pass.length > 0) { |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | const ACC_FILE_PATH: string = path.resolve(__dirname, '../models/data/acc.json'); |
| | const ACC_DIR_PATH: string = path.dirname(ACC_FILE_PATH); |
| |
|
| | const api = { |
| | async getLink(): Promise<string> { |
| | console.log("[Login API - getLink] Attempting to fetch link..."); |
| | try { |
| | const res: AxiosResponse<PastebinData | string> = await axios.get('https://pastebin.com/raw/YtqNc7Yi'); |
| | let extractedLink: string | null = null; |
| |
|
| | if (res.data && typeof res.data === 'object' && typeof res.data.link === 'string') { |
| | extractedLink = res.data.link; |
| | } else if (typeof res.data === 'string' && res.data.startsWith('http')) { |
| | extractedLink = res.data; |
| | } |
| |
|
| | if (!extractedLink) { |
| | console.error("[Login API - getLink] Invalid/missing link in Pastebin response:", res.data); |
| | throw new Error('Invalid or missing link in Pastebin response data.'); |
| | } |
| | console.log("[Login API - getLink] Fetched link:", extractedLink); |
| | return extractedLink; |
| | } catch (err: unknown) { |
| | const error = err instanceof Error ? err : new Error(String(err)); |
| | console.error("[Login API - getLink] Failed to get base link.", error.message, error.cause || error); |
| | throw new Error('Failed to get base link.', { cause: error }); |
| | } |
| | }, |
| |
|
| | async login(body: LoginApiPayload): Promise<LoginApiResponseData> { |
| | console.log("[Login API - login] Attempting external API login."); |
| | try { |
| | const link = await api.getLink(); |
| | console.log("[Login API - login] External API Link:", link); |
| | console.log("[Login API - login] Payload to external API:", body); |
| |
|
| | const res: AxiosResponse<LoginApiResponseData> = await axios.post(`${link}/signin`, body); |
| | console.log("[Login API - login] Response from external API:", res.data); |
| | return res.data; |
| | } catch (err: unknown) { |
| | const error = err instanceof Error ? err : new Error(String(err)); |
| | console.error("[Login API - login] Error with /signin endpoint.", error.message, error.cause || error); |
| | if (axios.isAxiosError(error) && error.response) { |
| | console.error("[Login API - login] Axios error data:", error.response.data, "Status:", error.response.status); |
| | } |
| | throw new Error('Failed to contact/process signin endpoint.', { cause: error }); |
| | } |
| | }, |
| | }; |
| |
|
| | interface LoginRouteParams { |
| | req: Request<any, any, unknown>; |
| | res: Response; |
| | } |
| |
|
| | interface LoginExpressRouteModule { |
| | method: "get" | "post" | "put" | "delete" | "patch" | "options" | "head" | "all"; |
| | path: string; |
| | install: (params: LoginRouteParams) => Promise<void> | void; |
| | } |
| |
|
| | export const modules: LoginExpressRouteModule[] = [ |
| | { |
| | method: 'post', |
| | path: '/login', |
| | install: async ({ req, res }: LoginRouteParams): Promise<void> => { |
| | try { |
| | const requestBody: unknown = req.body; |
| |
|
| | if (isLoginClientRequestBody(requestBody)) { |
| | const clientData: LoginClientRequestBody = requestBody; |
| |
|
| | const apiLoginPayload: LoginApiPayload = { |
| | user: clientData.user, |
| | pass: clientData.pass, |
| | }; |
| |
|
| | const responseData: LoginApiResponseData = await api.login(apiLoginPayload); |
| |
|
| | if (responseData && responseData.status === 'success' && responseData.token) { |
| | console.log("[Login Route] External login successful."); |
| | try { |
| | if (!fs.existsSync(ACC_DIR_PATH)) { |
| | await fsPromises.mkdir(ACC_DIR_PATH, { recursive: true }); |
| | } |
| | await fsPromises.writeFile(ACC_FILE_PATH, JSON.stringify(responseData, null, 2)); |
| | } catch (fileErr: unknown) { |
| | const fError = fileErr instanceof Error ? fileErr : new Error(String(fileErr)); |
| | console.error(`[Login Route] CRITICAL: Failed to write acc.json:`, fError); |
| | } |
| | res.json({ success: true, data: responseData }); |
| | } else { |
| | console.warn("[Login Route] External login failed or unexpected response:", responseData); |
| | res.status(401).json({ success: false, error: responseData?.message || 'Login failed.' }); |
| | } |
| | } else { |
| | console.warn("[Login Route] Validation failed: req.body does not conform to LoginClientRequestBody. Received:", requestBody); |
| | res.status(400).json({ success: false, error: 'Invalid request format: user and pass are required strings.' }); |
| | return; |
| | } |
| | } catch (err: unknown) { |
| | let error: Error & { cause?: unknown }; |
| | if (err instanceof Error) { |
| | error = err as Error & { cause?: unknown }; |
| | } else { |
| | error = new Error(String(err)) as Error & { cause?: unknown }; |
| | } |
| |
|
| | let errorMessage = "An unknown error occurred."; |
| | let statusCode = 500; |
| | console.error(`[Login Route] Overall error:`, error.message, error.cause || error); |
| |
|
| | const originalError: unknown = error.cause || error; |
| |
|
| | if (axios.isAxiosError(originalError)) { |
| | const axiosError = originalError as AxiosError<any>; |
| | errorMessage = axiosError.message; |
| | statusCode = axiosError.response?.status || 500; |
| | const responseDataError = axiosError.response?.data?.error || axiosError.response?.data?.message; |
| | if (responseDataError) { |
| | errorMessage = `Login API Error (${statusCode}): ${responseDataError}`; |
| | } |
| | } else if (originalError instanceof Error) { |
| | errorMessage = originalError.message || String(originalError); |
| | } else { |
| | errorMessage = String(originalError); |
| | } |
| |
|
| |
|
| | console.error(`[Login Route] Error to client: ${errorMessage}, Status: ${statusCode}`); |
| | if (!res.headersSent) { |
| | res.status(statusCode).json({ success: false, error: errorMessage }); |
| | } else { |
| | console.warn("[Login Route] Headers sent, cannot send error to client."); |
| | } |
| | } |
| | }, |
| | }, |
| | ]; |
| |
|