204 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import http from "http";
 | |
| import encrypt from "../../package-shared/functions/dsql/encrypt";
 | |
| import grabHostNames from "../../package-shared/utils/grab-host-names";
 | |
| import apiGoogleLogin from "../../package-shared/functions/api/users/social/api-google-login";
 | |
| import getAuthCookieNames from "../../package-shared/functions/backend/cookies/get-auth-cookie-names";
 | |
| import { writeAuthFile } from "../../package-shared/functions/backend/auth/write-auth-files";
 | |
| import { APILoginFunctionReturn } from "../../package-shared/types";
 | |
| 
 | |
| type Param = {
 | |
|     key?: string;
 | |
|     token: string;
 | |
|     database?: string;
 | |
|     response?: http.ServerResponse;
 | |
|     encryptionKey?: string;
 | |
|     encryptionSalt?: string;
 | |
|     additionalFields?: string[];
 | |
|     additionalData?: { [s: string]: string | number };
 | |
|     apiUserID?: string | number;
 | |
|     useLocal?: boolean;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * # SERVER FUNCTION: Login with google Function
 | |
|  */
 | |
| export default async function googleAuth({
 | |
|     key,
 | |
|     token,
 | |
|     database,
 | |
|     response,
 | |
|     encryptionKey,
 | |
|     encryptionSalt,
 | |
|     additionalFields,
 | |
|     additionalData,
 | |
|     apiUserID,
 | |
|     useLocal,
 | |
| }: Param): Promise<APILoginFunctionReturn> {
 | |
|     const grabedHostNames = grabHostNames();
 | |
|     const { host, port, scheme } = grabedHostNames;
 | |
| 
 | |
|     const finalEncryptionKey =
 | |
|         encryptionKey || process.env.DSQL_ENCRYPTION_PASSWORD;
 | |
|     const finalEncryptionSalt =
 | |
|         encryptionSalt || process.env.DSQL_ENCRYPTION_SALT;
 | |
| 
 | |
|     if (!finalEncryptionKey?.match(/.{8,}/)) {
 | |
|         console.log("Encryption key is invalid");
 | |
|         return {
 | |
|             success: false,
 | |
|             payload: null,
 | |
|             msg: "Encryption key is invalid",
 | |
|         };
 | |
|     }
 | |
|     if (!finalEncryptionSalt?.match(/.{8,}/)) {
 | |
|         console.log("Encryption salt is invalid");
 | |
|         return {
 | |
|             success: false,
 | |
|             payload: null,
 | |
|             msg: "Encryption salt is invalid",
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Check inputs
 | |
|      *
 | |
|      * @description Check inputs
 | |
|      */
 | |
| 
 | |
|     if (!token || token?.match(/ /)) {
 | |
|         return {
 | |
|             success: false,
 | |
|             payload: null,
 | |
|             msg: "Please enter Google Access Token",
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Initialize HTTP response variable
 | |
|      */
 | |
| 
 | |
|     /** @type {import("../../package-shared/types").APILoginFunctionReturn} */
 | |
|     let httpResponse: import("../../package-shared/types").APILoginFunctionReturn =
 | |
|         {
 | |
|             success: false,
 | |
|         };
 | |
| 
 | |
|     /**
 | |
|      * Check for local DB settings
 | |
|      *
 | |
|      * @description Look for local db settings in `.env` file and by pass the http request if available
 | |
|      */
 | |
|     const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
 | |
|         process.env;
 | |
| 
 | |
|     if (
 | |
|         DSQL_DB_HOST?.match(/./) &&
 | |
|         DSQL_DB_USERNAME?.match(/./) &&
 | |
|         DSQL_DB_PASSWORD?.match(/./) &&
 | |
|         DSQL_DB_NAME?.match(/./) &&
 | |
|         useLocal
 | |
|     ) {
 | |
|         httpResponse = await apiGoogleLogin({
 | |
|             token,
 | |
|             additionalFields,
 | |
|             database: DSQL_DB_NAME,
 | |
|             additionalData,
 | |
|         });
 | |
|     } else {
 | |
|         /**
 | |
|          * Make https request
 | |
|          *
 | |
|          * @description make a request to datasquirel.com
 | |
|          * @type {{ success: boolean, user: import("../../package-shared/types").DATASQUIREL_LoggedInUser | null, msg?: string, dsqlUserId?: number } | null } - Https response object
 | |
|          */
 | |
|         httpResponse = await new Promise((resolve, reject) => {
 | |
|             const reqPayload = JSON.stringify({
 | |
|                 token,
 | |
|                 database,
 | |
|                 additionalFields,
 | |
|                 additionalData,
 | |
|             });
 | |
| 
 | |
|             const httpsRequest = scheme.request(
 | |
|                 {
 | |
|                     method: "POST",
 | |
|                     headers: {
 | |
|                         "Content-Type": "application/json",
 | |
|                         "Content-Length": Buffer.from(reqPayload).length,
 | |
|                         Authorization:
 | |
|                             key ||
 | |
|                             process.env.DSQL_FULL_ACCESS_API_KEY ||
 | |
|                             process.env.DSQL_API_KEY,
 | |
|                     },
 | |
|                     port,
 | |
|                     hostname: host,
 | |
|                     path: `/api/user/${
 | |
|                         apiUserID || grabedHostNames.user_id
 | |
|                     }/google-login`,
 | |
|                 },
 | |
| 
 | |
|                 /**
 | |
|                  * Callback Function
 | |
|                  *
 | |
|                  * @description https request callback
 | |
|                  */
 | |
|                 (response) => {
 | |
|                     var str = "";
 | |
| 
 | |
|                     response.on("data", function (chunk) {
 | |
|                         str += chunk;
 | |
|                     });
 | |
| 
 | |
|                     response.on("end", function () {
 | |
|                         resolve(JSON.parse(str));
 | |
|                     });
 | |
| 
 | |
|                     response.on("error", (err) => {
 | |
|                         reject(err);
 | |
|                     });
 | |
|                 }
 | |
|             );
 | |
|             httpsRequest.write(reqPayload);
 | |
|             httpsRequest.end();
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Make https request
 | |
|      *
 | |
|      * @description make a request to datasquirel.com
 | |
|      */
 | |
|     if (httpResponse?.success && httpResponse?.payload) {
 | |
|         let encryptedPayload = encrypt({
 | |
|             data: JSON.stringify(httpResponse.payload),
 | |
|             encryptionKey: finalEncryptionKey,
 | |
|             encryptionSalt: finalEncryptionSalt,
 | |
|         });
 | |
| 
 | |
|         const cookieNames = getAuthCookieNames({
 | |
|             database,
 | |
|             userId: apiUserID || process.env.DSQL_API_USER_ID,
 | |
|         });
 | |
| 
 | |
|         if (httpResponse.csrf) {
 | |
|             writeAuthFile(
 | |
|                 httpResponse.csrf,
 | |
|                 JSON.stringify(httpResponse.payload)
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         httpResponse["cookieNames"] = cookieNames;
 | |
|         httpResponse["key"] = String(encryptedPayload);
 | |
| 
 | |
|         const authKeyName = cookieNames.keyCookieName;
 | |
|         const csrfName = cookieNames.csrfCookieName;
 | |
| 
 | |
|         response?.setHeader("Set-Cookie", [
 | |
|             `${authKeyName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`,
 | |
|             `${csrfName}=${httpResponse.payload?.csrf_k};samesite=strict;path=/;HttpOnly=true`,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     return httpResponse;
 | |
| }
 | 
