Updates
This commit is contained in:
@@ -0,0 +1,447 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* ==============================================================================
|
||||
* Imports
|
||||
* ==============================================================================
|
||||
*/
|
||||
const fs = require("fs");
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
const addAdminUserOnLogin = require("../../backend/addAdminUserOnLogin");
|
||||
const handleNodemailer = require("../../backend/handleNodemailer");
|
||||
const { ServerResponse } = require("http");
|
||||
const path = require("path");
|
||||
const addMariadbUser = require("../../backend/addMariadbUser");
|
||||
const varDatabaseDbHandler = require("../../backend/varDatabaseDbHandler");
|
||||
const encrypt = require("../../dsql/encrypt");
|
||||
const addDbEntry = require("../../backend/db/addDbEntry");
|
||||
const getAuthCookieNames = require("../../backend/cookies/get-auth-cookie-names");
|
||||
const LOCAL_DB_HANDLER = require("../../../utils/backend/global-db/LOCAL_DB_HANDLER");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @typedef {object} FunctionReturn
|
||||
* @property {boolean} success - Did the operation complete successfully or not?
|
||||
* @property {{
|
||||
* id: number,
|
||||
* first_name: string,
|
||||
* last_name: string,
|
||||
* }|null} user - User payload object: or "null"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {import("../../../types").HandleSocialDbFunction}
|
||||
*/
|
||||
module.exports = async function handleSocialDb({
|
||||
database,
|
||||
social_id,
|
||||
email,
|
||||
social_platform,
|
||||
payload,
|
||||
res,
|
||||
invitation,
|
||||
supEmail,
|
||||
additionalFields,
|
||||
useLocal,
|
||||
}) {
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
try {
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
const existingSocialIdUserQuery = `SELECT * FROM users WHERE social_id = ? AND social_login='1' AND social_platform = ? `;
|
||||
const existingSocialIdUserValues = [
|
||||
social_id.toString(),
|
||||
social_platform,
|
||||
];
|
||||
|
||||
let existingSocialIdUser = useLocal
|
||||
? await LOCAL_DB_HANDLER(
|
||||
existingSocialIdUserQuery,
|
||||
existingSocialIdUserValues
|
||||
)
|
||||
: await varDatabaseDbHandler({
|
||||
database: database ? database : "datasquirel",
|
||||
queryString: existingSocialIdUserQuery,
|
||||
queryValuesArray: existingSocialIdUserValues,
|
||||
});
|
||||
|
||||
if (existingSocialIdUser && existingSocialIdUser[0]) {
|
||||
return await loginSocialUser({
|
||||
user: existingSocialIdUser[0],
|
||||
social_platform,
|
||||
res,
|
||||
invitation,
|
||||
database,
|
||||
additionalFields,
|
||||
useLocal,
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
const finalEmail = email ? email : supEmail ? supEmail : null;
|
||||
|
||||
if (!finalEmail) {
|
||||
return {
|
||||
success: false,
|
||||
user: null,
|
||||
msg: "No Email Present",
|
||||
social_id,
|
||||
social_platform,
|
||||
payload,
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
const existingEmailOnlyQuery = `SELECT * FROM users WHERE email='${finalEmail}'`;
|
||||
|
||||
let existingEmailOnly = useLocal
|
||||
? await LOCAL_DB_HANDLER(existingEmailOnlyQuery)
|
||||
: await varDatabaseDbHandler({
|
||||
database: database ? database : "datasquirel",
|
||||
queryString: existingEmailOnlyQuery,
|
||||
});
|
||||
|
||||
if (existingEmailOnly && existingEmailOnly[0]) {
|
||||
return {
|
||||
success: false,
|
||||
user: null,
|
||||
msg: "This Email is already taken",
|
||||
alert: true,
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
const foundUserQuery = `SELECT * FROM users WHERE email='${finalEmail}' AND social_login='1' AND social_platform='${social_platform}' AND social_id='${social_id}'`;
|
||||
|
||||
const foundUser = useLocal
|
||||
? await LOCAL_DB_HANDLER(foundUserQuery)
|
||||
: await varDatabaseDbHandler({
|
||||
database: database ? database : "datasquirel",
|
||||
queryString: foundUserQuery,
|
||||
});
|
||||
|
||||
if (foundUser && foundUser[0]) {
|
||||
return await loginSocialUser({
|
||||
user: payload,
|
||||
social_platform,
|
||||
res,
|
||||
invitation,
|
||||
database,
|
||||
additionalFields,
|
||||
useLocal,
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
const socialHashedPassword = encrypt({
|
||||
data: social_id.toString(),
|
||||
});
|
||||
|
||||
/** @type {any} */
|
||||
const data = {
|
||||
social_login: "1",
|
||||
verification_status: supEmail ? "0" : "1",
|
||||
password: socialHashedPassword,
|
||||
};
|
||||
|
||||
Object.keys(payload).forEach((key) => {
|
||||
data[key] = payload[key];
|
||||
});
|
||||
|
||||
/** @type {any} */
|
||||
const newUser = await addDbEntry({
|
||||
dbContext: database ? "Dsql User" : undefined,
|
||||
paradigm: database ? "Full Access" : undefined,
|
||||
dbFullName: database ? database : "datasquirel",
|
||||
tableName: "users",
|
||||
duplicateColumnName: "email",
|
||||
duplicateColumnValue: finalEmail,
|
||||
data: {
|
||||
...data,
|
||||
email: finalEmail,
|
||||
},
|
||||
useLocal,
|
||||
});
|
||||
|
||||
if (newUser?.insertId) {
|
||||
if (!database) {
|
||||
/**
|
||||
* Add a Mariadb User for this User
|
||||
*/
|
||||
await addMariadbUser({ userId: newUser.insertId, useLocal });
|
||||
}
|
||||
|
||||
const newUserQueriedQuery = `SELECT * FROM users WHERE id='${newUser.insertId}'`;
|
||||
|
||||
const newUserQueried = useLocal
|
||||
? await LOCAL_DB_HANDLER(newUserQueriedQuery)
|
||||
: await varDatabaseDbHandler({
|
||||
database: database ? database : "datasquirel",
|
||||
queryString: newUserQueriedQuery,
|
||||
});
|
||||
|
||||
if (!newUserQueried || !newUserQueried[0])
|
||||
return {
|
||||
success: false,
|
||||
user: null,
|
||||
msg: "User Insertion Failed!",
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
if (supEmail && database?.match(/^datasquirel$/)) {
|
||||
/**
|
||||
* Send email Verification
|
||||
*
|
||||
* @description Send verification email to newly created agent
|
||||
*/
|
||||
let generatedToken = encrypt({
|
||||
data: JSON.stringify({
|
||||
id: newUser.insertId,
|
||||
email: supEmail,
|
||||
dateCode: Date.now(),
|
||||
}),
|
||||
});
|
||||
|
||||
handleNodemailer({
|
||||
to: supEmail,
|
||||
subject: "Verify Email Address",
|
||||
text: "Please click the link to verify your email address",
|
||||
html: fs
|
||||
.readFileSync(
|
||||
"./email/send-email-verification-link.html",
|
||||
"utf8"
|
||||
)
|
||||
.replace(/{{host}}/, process.env.DSQL_HOST || "")
|
||||
.replace(/{{token}}/, generatedToken || ""),
|
||||
}).then((mail) => {});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
const STATIC_ROOT = process.env.DSQL_STATIC_SERVER_DIR;
|
||||
|
||||
if (!STATIC_ROOT) {
|
||||
console.log("Static File ENV not Found!");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new user folder and file
|
||||
*
|
||||
* @description Create new user folder and file
|
||||
*/
|
||||
if (!database || database?.match(/^datasquirel$/)) {
|
||||
let newUserSchemaFolderPath = `${process.env.DSQL_USER_DB_SCHEMA_PATH}/user-${newUser.insertId}`;
|
||||
|
||||
let newUserMediaFolderPath = path.join(
|
||||
STATIC_ROOT,
|
||||
`images/user-images/user-${newUser.insertId}`
|
||||
);
|
||||
|
||||
fs.mkdirSync(newUserSchemaFolderPath);
|
||||
fs.mkdirSync(newUserMediaFolderPath);
|
||||
|
||||
fs.writeFileSync(
|
||||
`${newUserSchemaFolderPath}/main.json`,
|
||||
JSON.stringify([]),
|
||||
"utf8"
|
||||
);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
return await loginSocialUser({
|
||||
user: newUserQueried[0],
|
||||
social_platform,
|
||||
res,
|
||||
invitation,
|
||||
database,
|
||||
additionalFields,
|
||||
useLocal,
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
} else {
|
||||
console.log(
|
||||
"Social User Failed to insert in 'handleSocialDb.js' backend function =>",
|
||||
newUser
|
||||
);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
user: null,
|
||||
msg: "Social User Failed to insert in 'handleSocialDb.js' backend function => ",
|
||||
newUser: newUser,
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
} catch (/** @type {any} */ error) {
|
||||
console.log(
|
||||
"ERROR in 'handleSocialDb.js' backend function =>",
|
||||
error.message
|
||||
);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
user: null,
|
||||
error: error.message,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Function to login social user
|
||||
* ==============================================================================
|
||||
* @description This function logs in the user after 'handleSocialDb' function finishes
|
||||
* the user creation or confirmation process
|
||||
*
|
||||
* @async
|
||||
*
|
||||
* @param {object} params - function parameters inside an object
|
||||
* @param {{
|
||||
* first_name: string,
|
||||
* last_name: string,
|
||||
* email: string,
|
||||
* social_id: string|number,
|
||||
* }} params.user - user object
|
||||
* @param {string} params.social_platform - Whether its "google" or "facebook" or "github"
|
||||
* @param {ServerResponse} [params.res] - Https response object
|
||||
* @param {any} [params.invitation] - A query object if user was invited
|
||||
* @param {string} [params.database] - Target Database
|
||||
* @param {object} [params.additionalFields] - Additional fields to be added to the user payload
|
||||
* @param {boolean} [params.useLocal]
|
||||
*
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
async function loginSocialUser({
|
||||
user,
|
||||
social_platform,
|
||||
res,
|
||||
invitation,
|
||||
database,
|
||||
additionalFields,
|
||||
useLocal,
|
||||
}) {
|
||||
const foundUserQuery = `SELECT * FROM users WHERE email='${user.email}' AND social_id='${user.social_id}' AND social_platform='${social_platform}'`;
|
||||
|
||||
const foundUser = useLocal
|
||||
? await LOCAL_DB_HANDLER(foundUserQuery)
|
||||
: await varDatabaseDbHandler({
|
||||
database: database ? database : "datasquirel",
|
||||
queryString: foundUserQuery,
|
||||
});
|
||||
|
||||
if (!foundUser?.[0])
|
||||
return {
|
||||
success: false,
|
||||
user: null,
|
||||
};
|
||||
|
||||
let csrfKey =
|
||||
Math.random().toString(36).substring(2) +
|
||||
"-" +
|
||||
Math.random().toString(36).substring(2);
|
||||
|
||||
/** @type {any} */
|
||||
let userPayload = {
|
||||
id: foundUser[0].id,
|
||||
type: foundUser[0].type || "",
|
||||
stripe_id: foundUser[0].stripe_id || "",
|
||||
first_name: foundUser[0].first_name,
|
||||
last_name: foundUser[0].last_name,
|
||||
username: foundUser[0].username,
|
||||
email: foundUser[0].email,
|
||||
social_id: foundUser[0].social_id,
|
||||
image: foundUser[0].image,
|
||||
image_thumbnail: foundUser[0].image_thumbnail,
|
||||
verification_status: foundUser[0].verification_status,
|
||||
social_login: foundUser[0].social_login,
|
||||
social_platform: foundUser[0].social_platform,
|
||||
csrf_k: csrfKey,
|
||||
logged_in_status: true,
|
||||
date: Date.now(),
|
||||
};
|
||||
|
||||
if (additionalFields && Object.keys(additionalFields).length > 0) {
|
||||
Object.keys(additionalFields).forEach((key) => {
|
||||
userPayload[key] = foundUser[0][key];
|
||||
});
|
||||
}
|
||||
|
||||
let encryptedPayload = encrypt({ data: JSON.stringify(userPayload) });
|
||||
|
||||
const { keyCookieName, csrfCookieName } = getAuthCookieNames();
|
||||
|
||||
if (res?.setHeader) {
|
||||
res.setHeader("Set-Cookie", [
|
||||
`${keyCookieName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`,
|
||||
`${csrfCookieName}=${csrfKey};samesite=strict;path=/;HttpOnly=true`,
|
||||
]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
if (invitation && (!database || database?.match(/^datasquirel$/))) {
|
||||
addAdminUserOnLogin({
|
||||
query: invitation,
|
||||
user: userPayload,
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
return {
|
||||
success: true,
|
||||
user: userPayload,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user