Updates
This commit is contained in:
+191
@@ -0,0 +1,191 @@
|
||||
// @ts-check
|
||||
|
||||
const serverError = require("./serverError");
|
||||
const DB_HANDLER = require("../../utils/backend/global-db/DB_HANDLER");
|
||||
const addDbEntry = require("./db/addDbEntry");
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
|
||||
/**
|
||||
* Add Admin User on Login
|
||||
* ==============================================================================
|
||||
*
|
||||
* @description this function handles admin users that have been invited by another
|
||||
* admin user. This fires when the invited user has been logged in or a new account
|
||||
* has been created for the invited user
|
||||
*
|
||||
* @param {object} params - parameters object
|
||||
*
|
||||
* @param {object} params.query - query object
|
||||
* @param {number} params.query.invite - Invitation user id
|
||||
* @param {string} params.query.database_access - String containing authorized databases
|
||||
* @param {string} params.query.priviledge - String containing databases priviledges
|
||||
* @param {string} params.query.email - Inviting user email address
|
||||
*
|
||||
* @param {import("../../types").UserType} params.user - invited user object
|
||||
*
|
||||
* @returns {Promise<any>} new user auth object payload
|
||||
*/
|
||||
module.exports = async function addAdminUserOnLogin({ query, user }) {
|
||||
try {
|
||||
/**
|
||||
* Fetch user
|
||||
*
|
||||
* @description Fetch user from db
|
||||
*/ // @ts-ignore
|
||||
const { invite, database_access, priviledge, email } = query;
|
||||
|
||||
const lastInviteTimeArray = await DB_HANDLER(
|
||||
`SELECT date_created_code FROM invitations WHERE inviting_user_id=? AND invited_user_email=?`,
|
||||
[invite, email]
|
||||
);
|
||||
|
||||
// if (lastInviteTimeArray && lastInviteTimeArray[0]?.date_created_code) {
|
||||
// const timeSinceLastInvite = Date.now() - parseInt(lastInviteTimeArray[0].date_created_code);
|
||||
// if (timeSinceLastInvite > 21600000) {
|
||||
// throw new Error("Invitation expired");
|
||||
// }
|
||||
// } else if (!lastInviteTimeArray || !lastInviteTimeArray[0]) {
|
||||
// throw new Error("No Invitation Found");
|
||||
// }
|
||||
|
||||
if (!lastInviteTimeArray || !lastInviteTimeArray[0]) {
|
||||
throw new Error("No Invitation Found");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
// @ts-ignore
|
||||
const invitingUserDb = await DB_HANDLER(
|
||||
`SELECT first_name,last_name,email FROM users WHERE id=?`,
|
||||
[invite]
|
||||
);
|
||||
|
||||
if (invitingUserDb?.[0]) {
|
||||
const existingUserUser = await DB_HANDLER(
|
||||
`SELECT email FROM user_users WHERE user_id=? AND invited_user_id=? AND user_type='admin' AND email=?`,
|
||||
[invite, user.id, email]
|
||||
);
|
||||
|
||||
if (existingUserUser?.[0]) {
|
||||
console.log("User already added");
|
||||
} else {
|
||||
// const newUserUser = await DB_HANDLER(
|
||||
// `INSERT IGNORE INTO user_users
|
||||
// (user_id, invited_user_id, database_access, first_name, last_name, phone, email, username, user_type, user_priviledge)
|
||||
// VALUES
|
||||
// (?,?,?,?,?,?,?,?,?,?)
|
||||
// )`,
|
||||
// [
|
||||
// invite,
|
||||
// user.id,
|
||||
// database_access,
|
||||
// user.first_name,
|
||||
// user.last_name,
|
||||
// user.phone,
|
||||
// user.email,
|
||||
// user.username,
|
||||
// "admin",
|
||||
// priviledge,
|
||||
// ]
|
||||
// );
|
||||
addDbEntry({
|
||||
dbFullName: "datasquirel",
|
||||
tableName: "user_users",
|
||||
data: {
|
||||
user_id: invite,
|
||||
invited_user_id: user.id,
|
||||
database_access: database_access,
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
phone: user.phone,
|
||||
email: user.email,
|
||||
username: user.username,
|
||||
user_type: "admin",
|
||||
user_priviledge: priviledge,
|
||||
image: user.image,
|
||||
image_thumbnail: user.image_thumbnail,
|
||||
},
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
// @ts-ignore
|
||||
const dbTableData = await DB_HANDLER(
|
||||
`SELECT db_tables_data FROM invitations WHERE inviting_user_id=? AND invited_user_email=?`,
|
||||
[invite, email]
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
const clearEntries = await DB_HANDLER(
|
||||
`DELETE FROM delegated_user_tables WHERE root_user_id=? AND delegated_user_id=?`,
|
||||
[invite, user.id]
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
if (dbTableData && dbTableData[0]) {
|
||||
const dbTableEntries =
|
||||
dbTableData[0].db_tables_data.split("|");
|
||||
|
||||
for (let i = 0; i < dbTableEntries.length; i++) {
|
||||
const dbTableEntry = dbTableEntries[i];
|
||||
const dbTableEntryArray = dbTableEntry.split("-");
|
||||
const [db_slug, table_slug] = dbTableEntryArray;
|
||||
|
||||
const newEntry = await addDbEntry({
|
||||
dbFullName: "datasquirel",
|
||||
tableName: "delegated_user_tables",
|
||||
data: {
|
||||
delegated_user_id: user.id,
|
||||
root_user_id: invite,
|
||||
database: db_slug,
|
||||
table: table_slug,
|
||||
priviledge: priviledge,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const inviteAccepted = await DB_HANDLER(
|
||||
`UPDATE invitations SET invitation_status='Accepted' WHERE inviting_user_id=? AND invited_user_email=?`,
|
||||
[invite, email]
|
||||
);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
} catch (/** @type {any} */ error) {
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
serverError({
|
||||
component: "addAdminUserOnLogin",
|
||||
message: error.message,
|
||||
user: user,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
@@ -3,8 +3,8 @@
|
||||
const generator = require("generate-password");
|
||||
const DB_HANDLER = require("../../utils/backend/global-db/DB_HANDLER");
|
||||
const NO_DB_HANDLER = require("../../utils/backend/global-db/NO_DB_HANDLER");
|
||||
const encrypt = require("./encrypt");
|
||||
const addDbEntry = require("./db/addDbEntry");
|
||||
const encrypt = require("../dsql/encrypt");
|
||||
|
||||
/**
|
||||
* # Add Mariadb User
|
||||
@@ -28,7 +28,7 @@ module.exports = async function addMariadbUser({ userId }) {
|
||||
uppercase: true,
|
||||
exclude: "*#.'`\"",
|
||||
});
|
||||
const encryptedPassword = encrypt(password);
|
||||
const encryptedPassword = encrypt({ data: password });
|
||||
|
||||
await NO_DB_HANDLER(
|
||||
`CREATE USER IF NOT EXISTS '${username}'@'127.0.0.1' IDENTIFIED BY '${password}' REQUIRE SSL`
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
// @ts-check
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { execSync } = require("child_process");
|
||||
const serverError = require("./serverError");
|
||||
const DB_HANDLER = require("../../utils/backend/global-db/DB_HANDLER");
|
||||
const { default: grabUserSchemaData } = require("./grabUserSchemaData");
|
||||
const { default: setUserSchemaData } = require("./setUserSchemaData");
|
||||
const addDbEntry = require("./db/addDbEntry");
|
||||
const createDbFromSchema = require("../../shell/createDbFromSchema");
|
||||
|
||||
/**
|
||||
* # Add User Table to Database
|
||||
*
|
||||
* @param {object} params
|
||||
* @param {number} params.userId - user id
|
||||
* @param {string} params.database
|
||||
*
|
||||
* @returns {Promise<any>} new user auth object payload
|
||||
*/
|
||||
module.exports = async function addUsersTableToDb({ userId, database }) {
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* @description Initialize
|
||||
*/
|
||||
const dbFullName = `datasquirel_user_${userId}_${database}`;
|
||||
/** @type {import("../../types").DSQL_TableSchemaType} */
|
||||
const userPreset = require("../../data/presets/users.json");
|
||||
|
||||
try {
|
||||
/**
|
||||
* Fetch user
|
||||
*
|
||||
* @description Fetch user from db
|
||||
*/
|
||||
const userSchemaData = grabUserSchemaData({ userId });
|
||||
if (!userSchemaData) throw new Error("User schema data not found!");
|
||||
|
||||
let targetDatabase = userSchemaData.filter(
|
||||
(db) => db.dbSlug === database
|
||||
)[0];
|
||||
|
||||
let existingTableIndex;
|
||||
// @ts-ignore
|
||||
let existingTable = targetDatabase.tables.filter((table, index) => {
|
||||
if (table.tableName === "users") {
|
||||
existingTableIndex = index;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (existingTable && existingTable[0] && existingTableIndex) {
|
||||
targetDatabase.tables[existingTableIndex] = userPreset;
|
||||
} else {
|
||||
targetDatabase.tables.push(userPreset);
|
||||
}
|
||||
|
||||
setUserSchemaData({ schemaData: userSchemaData, userId });
|
||||
|
||||
const targetDb = await DB_HANDLER(
|
||||
`SELECT id FROM user_databases WHERE user_id=? AND db_slug=?`,
|
||||
[userId, database]
|
||||
);
|
||||
|
||||
if (targetDb && targetDb[0]) {
|
||||
const newTableEntry = await addDbEntry({
|
||||
dbFullName: "datasquirel",
|
||||
tableName: "user_database_tables",
|
||||
data: {
|
||||
user_id: userId,
|
||||
db_id: targetDb[0].id,
|
||||
db_slug: database,
|
||||
table_name: "Users",
|
||||
table_slug: "users",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const dbShellUpdate = await createDbFromSchema({
|
||||
userId,
|
||||
targetDatabase: dbFullName,
|
||||
});
|
||||
|
||||
return `Done!`;
|
||||
} catch (/** @type {any} */ error) {
|
||||
serverError({
|
||||
component: "addUsersTableToDb",
|
||||
message: error.message,
|
||||
user: { id: userId },
|
||||
});
|
||||
return error.message;
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
// @ts-check
|
||||
|
||||
const fs = require("fs");
|
||||
const decrypt = require("./decrypt");
|
||||
const decrypt = require("../dsql/decrypt");
|
||||
|
||||
/** @type {import("../../types").CheckApiCredentialsFn} */
|
||||
const grabApiCred = ({ key, database, table, user_id }) => {
|
||||
@@ -16,7 +16,7 @@ const grabApiCred = ({ key, database, table, user_id }) => {
|
||||
"process.env.DSQL_API_KEYS_PATH variable not found"
|
||||
);
|
||||
|
||||
const ApiJSON = decrypt(key);
|
||||
const ApiJSON = decrypt({ encryptedString: key });
|
||||
/** @type {import("../../types").ApiKeyObject} */
|
||||
const ApiObject = JSON.parse(ApiJSON || "");
|
||||
const isApiKeyValid = fs.existsSync(
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
module.exports = function getAuthCookieNames() {
|
||||
const cookiesPrefix = process.env.DSQL_COOKIES_PREFIX || "dsql_";
|
||||
const cookiesKeyName = process.env.DSQL_COOKIES_KEY_NAME || "key";
|
||||
const cookiesCSRFName = process.env.DSQL_COOKIES_CSRF_NAME || "csrf";
|
||||
|
||||
const keyCookieName = cookiesPrefix + cookiesKeyName;
|
||||
const csrfCookieName = cookiesPrefix + cookiesCSRFName;
|
||||
|
||||
return {
|
||||
keyCookieName,
|
||||
csrfCookieName,
|
||||
};
|
||||
};
|
||||
@@ -1,9 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* Imports: Handle imports
|
||||
*/
|
||||
const encrypt = require("../encrypt");
|
||||
const sanitizeHtml = require("sanitize-html");
|
||||
const sanitizeHtmlOptions = require("../html/sanitizeHtmlOptions");
|
||||
const updateDb = require("./updateDbEntry");
|
||||
@@ -11,6 +7,7 @@ const updateDbEntry = require("./updateDbEntry");
|
||||
const _ = require("lodash");
|
||||
const DB_HANDLER = require("../../../utils/backend/global-db/DB_HANDLER");
|
||||
const DSQL_USER_DB_HANDLER = require("../../../utils/backend/global-db/DSQL_USER_DB_HANDLER");
|
||||
const encrypt = require("../../dsql/encrypt");
|
||||
|
||||
/**
|
||||
* Add a db Entry Function
|
||||
@@ -146,7 +143,11 @@ async function addDbEntry({
|
||||
continue;
|
||||
|
||||
if (targetFieldSchema?.encrypted) {
|
||||
value = encrypt(value, encryptionKey, encryptionSalt);
|
||||
value = encrypt({
|
||||
data: value,
|
||||
encryptionKey,
|
||||
encryptionSalt,
|
||||
});
|
||||
console.log("DSQL: Encrypted value =>", value);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
export = runQuery;
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/**
|
||||
* Run DSQL users queries
|
||||
* ==============================================================================
|
||||
* @param {object} params - An object containing the function parameters.
|
||||
* @param {string} params.dbFullName - Database full name. Eg. "datasquire_user_2_test"
|
||||
* @param {string | any} params.query - Query string or object
|
||||
* @param {boolean} [params.readOnly] - Is this operation read only?
|
||||
* @param {boolean} [params.local] - Is this operation read only?
|
||||
* @param {import("../../../types").DSQL_DatabaseSchemaType} [params.dbSchema] - Database schema
|
||||
* @param {string[]} [params.queryValuesArray] - An optional array of query values if "?" is used in the query string
|
||||
* @param {string} [params.tableName] - Table Name
|
||||
*
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
declare function runQuery({ dbFullName, query, readOnly, dbSchema, queryValuesArray, tableName, local, }: {
|
||||
dbFullName: string;
|
||||
query: string | any;
|
||||
readOnly?: boolean;
|
||||
local?: boolean;
|
||||
dbSchema?: import("../../../types").DSQL_DatabaseSchemaType;
|
||||
queryValuesArray?: string[];
|
||||
tableName?: string;
|
||||
}): Promise<any>;
|
||||
@@ -38,7 +38,7 @@ const trimSql = require("../../../utils/trim-sql");
|
||||
* @param {boolean} [params.readOnly] - Is this operation read only?
|
||||
* @param {boolean} [params.local] - Is this operation read only?
|
||||
* @param {import("../../../types").DSQL_DatabaseSchemaType} [params.dbSchema] - Database schema
|
||||
* @param {string[]} [params.queryValuesArray] - An optional array of query values if "?" is used in the query string
|
||||
* @param {(string | number)[]} [params.queryValuesArray] - An optional array of query values if "?" is used in the query string
|
||||
* @param {string} [params.tableName] - Table Name
|
||||
*
|
||||
* @return {Promise<any>}
|
||||
@@ -120,14 +120,14 @@ async function runQuery({
|
||||
} else if (readOnly) {
|
||||
result = await varReadOnlyDatabaseDbHandler({
|
||||
queryString: formattedQuery,
|
||||
queryValuesArray,
|
||||
queryValuesArray: queryValuesArray?.map((vl) => String(vl)),
|
||||
database: dbFullName,
|
||||
tableSchema,
|
||||
});
|
||||
} else {
|
||||
result = await fullAccessDbHandler({
|
||||
queryString: formattedQuery,
|
||||
queryValuesArray,
|
||||
queryValuesArray: queryValuesArray?.map((vl) => String(vl)),
|
||||
database: dbFullName,
|
||||
tableSchema,
|
||||
});
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
/**
|
||||
* Imports: Handle imports
|
||||
*/
|
||||
const encrypt = require("../encrypt");
|
||||
const sanitizeHtml = require("sanitize-html");
|
||||
const sanitizeHtmlOptions = require("../html/sanitizeHtmlOptions");
|
||||
const DB_HANDLER = require("../../../utils/backend/global-db/DB_HANDLER");
|
||||
const DSQL_USER_DB_HANDLER = require("../../../utils/backend/global-db/DSQL_USER_DB_HANDLER");
|
||||
const encrypt = require("../../dsql/encrypt");
|
||||
|
||||
/**
|
||||
* Update DB Function
|
||||
@@ -94,7 +94,11 @@ async function updateDbEntry({
|
||||
}
|
||||
|
||||
if (targetFieldSchema?.encrypted) {
|
||||
value = encrypt(value, encryptionKey, encryptionSalt);
|
||||
value = encrypt({
|
||||
data: value,
|
||||
encryptionKey,
|
||||
encryptionSalt,
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof value === "object") {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export = decrypt;
|
||||
/**
|
||||
* @param {string} encryptedString
|
||||
* @returns {string | null}
|
||||
*/
|
||||
declare function decrypt(encryptedString: string): string | null;
|
||||
@@ -1,29 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const { scryptSync, createDecipheriv } = require("crypto");
|
||||
const { Buffer } = require("buffer");
|
||||
|
||||
/**
|
||||
* @param {string} encryptedString
|
||||
* @returns {string | null}
|
||||
*/
|
||||
const decrypt = (encryptedString) => {
|
||||
const algorithm = "aes-192-cbc";
|
||||
const password = process.env.DSQL_ENCRYPTION_PASSWORD || "";
|
||||
const salt = process.env.DSQL_ENCRYPTION_SALT || "";
|
||||
|
||||
let key = scryptSync(password, salt, 24);
|
||||
let iv = Buffer.alloc(16, 0);
|
||||
// @ts-ignore
|
||||
const decipher = createDecipheriv(algorithm, key, iv);
|
||||
|
||||
try {
|
||||
let decrypted = decipher.update(encryptedString, "hex", "utf8");
|
||||
decrypted += decipher.final("utf8");
|
||||
return decrypted;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = decrypt;
|
||||
@@ -1,9 +0,0 @@
|
||||
export = encrypt;
|
||||
/**
|
||||
* @async
|
||||
* @param {string} data
|
||||
* @param {string} [encryptionKey]
|
||||
* @param {string} [encryptionSalt]
|
||||
* @returns {string | null}
|
||||
*/
|
||||
declare function encrypt(data: string, encryptionKey?: string, encryptionSalt?: string): string | null;
|
||||
@@ -1,43 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const { scryptSync, createCipheriv } = require("crypto");
|
||||
const { Buffer } = require("buffer");
|
||||
const serverError = require("./serverError");
|
||||
|
||||
/**
|
||||
* @async
|
||||
* @param {string} data
|
||||
* @param {string} [encryptionKey]
|
||||
* @param {string} [encryptionSalt]
|
||||
* @returns {string | null}
|
||||
*/
|
||||
const encrypt = (data, encryptionKey, encryptionSalt) => {
|
||||
const algorithm = "aes-192-cbc";
|
||||
const password = encryptionKey
|
||||
? encryptionKey
|
||||
: process.env.DSQL_ENCRYPTION_PASSWORD || "";
|
||||
|
||||
/** ********************* Generate key */
|
||||
const salt = encryptionSalt
|
||||
? encryptionSalt
|
||||
: process.env.DSQL_ENCRYPTION_SALT || "";
|
||||
let key = scryptSync(password, salt, 24);
|
||||
let iv = Buffer.alloc(16, 0);
|
||||
// @ts-ignore
|
||||
const cipher = createCipheriv(algorithm, key, iv);
|
||||
|
||||
/** ********************* Encrypt data */
|
||||
try {
|
||||
let encrypted = cipher.update(data, "utf8", "hex");
|
||||
encrypted += cipher.final("hex");
|
||||
return encrypted;
|
||||
} catch (/** @type {any} */ error) {
|
||||
serverError({
|
||||
component: "encrypt",
|
||||
message: error.message,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = encrypt;
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// @ts-check
|
||||
|
||||
const serverError = require("./serverError");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
|
||||
/**
|
||||
* ==============================================================================
|
||||
* @param {Object} params
|
||||
* @param {string | number} params.userId
|
||||
* @returns {import("../../types").DSQL_DatabaseSchemaType[] | null}
|
||||
*/
|
||||
export default function grabUserSchemaData({ userId }) {
|
||||
try {
|
||||
const userSchemaFilePath = path.resolve(
|
||||
process.cwd(),
|
||||
`${process.env.DSQL_USER_DB_SCHEMA_PATH}/user-${userId}/main.json`
|
||||
);
|
||||
const userSchemaData = JSON.parse(
|
||||
fs.readFileSync(userSchemaFilePath, "utf-8")
|
||||
);
|
||||
|
||||
return userSchemaData;
|
||||
} catch (/** @type {any} */ error) {
|
||||
serverError({
|
||||
component: "grabUserSchemaData",
|
||||
message: error.message,
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* Imports
|
||||
* ==============================================================================
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
const nodemailer = require("nodemailer");
|
||||
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
let transporter = nodemailer.createTransport({
|
||||
host: process.env.DSQL_MAIL_HOST,
|
||||
port: 465,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: process.env.DSQL_MAIL_EMAIL,
|
||||
pass: process.env.DSQL_MAIL_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
|
||||
/**
|
||||
* # Handle mails
|
||||
* @param {object} mailObject - Mail Object with params
|
||||
* @param {string} [mailObject.to] - who is recieving this email? Comma separated for multiple recipients
|
||||
* @param {string} [mailObject.subject] - Mail Subject
|
||||
* @param {string} [mailObject.text] - Mail text
|
||||
* @param {string} [mailObject.html] - Mail HTML
|
||||
* @param {string | null} [mailObject.alias] - Sender alias: "support" or null
|
||||
*
|
||||
* @returns {Promise<any>} mail object
|
||||
*/
|
||||
module.exports = async function handleNodemailer({
|
||||
to,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
alias,
|
||||
}) {
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
if (
|
||||
!process.env.DSQL_MAIL_HOST ||
|
||||
!process.env.DSQL_MAIL_EMAIL ||
|
||||
!process.env.DSQL_MAIL_PASSWORD
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sender = (() => {
|
||||
if (alias?.match(/support/i)) return process.env.DSQL_MAIL_EMAIL;
|
||||
return process.env.DSQL_MAIL_EMAIL;
|
||||
})();
|
||||
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
let sentMessage;
|
||||
|
||||
if (!fs.existsSync("./email/index.html")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mailRoot = fs.readFileSync("./email/index.html", "utf8");
|
||||
let finalHtml = mailRoot
|
||||
.replace(/{{email_body}}/, html ? html : "")
|
||||
.replace(/{{issue_date}}/, Date().substring(0, 24));
|
||||
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
try {
|
||||
let mailObject = {};
|
||||
|
||||
mailObject["from"] = `"Datasquirel" <${sender}>`;
|
||||
mailObject["sender"] = sender;
|
||||
if (alias) mailObject["replyTo "] = sender;
|
||||
// mailObject["priority"] = "high";
|
||||
mailObject["to"] = to;
|
||||
mailObject["subject"] = subject;
|
||||
mailObject["text"] = text;
|
||||
mailObject["html"] = finalHtml;
|
||||
|
||||
// send mail with defined transport object
|
||||
let info = await transporter.sendMail(mailObject);
|
||||
|
||||
sentMessage = info;
|
||||
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
} catch (/** @type {any} */ error) {
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
|
||||
console.log("ERROR in handleNodemailer Function =>", error.message);
|
||||
// serverError({
|
||||
// component: "handleNodemailer",
|
||||
// message: error.message,
|
||||
// user: { email: to },
|
||||
// });
|
||||
}
|
||||
|
||||
return sentMessage;
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
////////////////////////////////////////
|
||||
@@ -0,0 +1,141 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* Imports
|
||||
* ==============================================================================
|
||||
*/
|
||||
const https = require("https");
|
||||
const http = require("http");
|
||||
const { URL } = require("url");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Main Function
|
||||
* ==============================================================================
|
||||
* @param {{
|
||||
* scheme?: string,
|
||||
* url?: string,
|
||||
* method?: string,
|
||||
* hostname?: string,
|
||||
* path?: string,
|
||||
* port?: number | string,
|
||||
* headers?: object,
|
||||
* body?: object,
|
||||
* }} params - params
|
||||
*/
|
||||
module.exports = function httpsRequest({
|
||||
url,
|
||||
method,
|
||||
hostname,
|
||||
path,
|
||||
headers,
|
||||
body,
|
||||
port,
|
||||
scheme,
|
||||
}) {
|
||||
const reqPayloadString = body ? JSON.stringify(body) : null;
|
||||
|
||||
const PARSED_URL = url ? new URL(url) : null;
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
/** @type {any} */
|
||||
let requestOptions = {
|
||||
method: method || "GET",
|
||||
hostname: PARSED_URL ? PARSED_URL.hostname : hostname,
|
||||
port: scheme?.match(/https/i)
|
||||
? 443
|
||||
: PARSED_URL
|
||||
? PARSED_URL.protocol?.match(/https/i)
|
||||
? 443
|
||||
: PARSED_URL.port
|
||||
: port
|
||||
? Number(port)
|
||||
: 80,
|
||||
headers: {},
|
||||
};
|
||||
|
||||
if (path) requestOptions.path = path;
|
||||
// if (href) requestOptions.href = href;
|
||||
|
||||
if (headers) requestOptions.headers = headers;
|
||||
if (body) {
|
||||
requestOptions.headers["Content-Type"] = "application/json";
|
||||
requestOptions.headers["Content-Length"] = reqPayloadString
|
||||
? Buffer.from(reqPayloadString).length
|
||||
: undefined;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
const httpsRequest = (
|
||||
scheme?.match(/https/i)
|
||||
? https
|
||||
: PARSED_URL?.protocol?.match(/https/i)
|
||||
? https
|
||||
: http
|
||||
).request(
|
||||
/* ====== Request Options object ====== */
|
||||
requestOptions,
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
|
||||
/* ====== Callback function ====== */
|
||||
(response) => {
|
||||
var str = "";
|
||||
|
||||
// ## another chunk of data has been received, so append it to `str`
|
||||
response.on("data", function (chunk) {
|
||||
str += chunk;
|
||||
});
|
||||
|
||||
// ## the whole response has been received, so we just print it out here
|
||||
response.on("end", function () {
|
||||
res(str);
|
||||
});
|
||||
|
||||
response.on("error", (error) => {
|
||||
console.log("HTTP response error =>", error.message);
|
||||
rej(`HTTP response error =>, ${error.message}`);
|
||||
});
|
||||
|
||||
response.on("close", () => {
|
||||
console.log("HTTP(S) Response Closed Successfully");
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
if (body) httpsRequest.write(reqPayloadString);
|
||||
|
||||
httpsRequest.on("error", (error) => {
|
||||
console.log("HTTPS request ERROR =>", error.message);
|
||||
rej(`HTTP request error =>, ${error.message}`);
|
||||
});
|
||||
|
||||
httpsRequest.end();
|
||||
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
});
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,6 +1,6 @@
|
||||
// @ts-check
|
||||
|
||||
const decrypt = require("./decrypt");
|
||||
const decrypt = require("../dsql/decrypt");
|
||||
const defaultFieldsRegexp = require("./defaultFieldsRegexp");
|
||||
|
||||
/**
|
||||
@@ -55,7 +55,9 @@ module.exports = async function parseDbResults({
|
||||
|
||||
if (resultFieldSchema?.encrypted) {
|
||||
if (value?.match(/./)) {
|
||||
result[resultFieldName] = decrypt(value);
|
||||
result[resultFieldName] = decrypt({
|
||||
encryptedString: value,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
declare function _exports({ user, message, component, noMail, }: {
|
||||
user?: {
|
||||
id?: number | string;
|
||||
first_name?: string;
|
||||
last_name?: string;
|
||||
email?: string;
|
||||
} & any;
|
||||
message: string;
|
||||
component?: string;
|
||||
noMail?: boolean;
|
||||
}): Promise<void>;
|
||||
export = _exports;
|
||||
Regular → Executable
+61
-13
@@ -6,7 +6,7 @@
|
||||
* ==============================================================================
|
||||
*/
|
||||
const fs = require("fs");
|
||||
// const handleNodemailer = require("./handleNodemailer");
|
||||
const { IncomingMessage } = require("http");
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
@@ -24,6 +24,7 @@ const fs = require("fs");
|
||||
* message: string,
|
||||
* component?: string,
|
||||
* noMail?: boolean,
|
||||
* req?: import("next").NextApiRequest & IncomingMessage,
|
||||
* }} params - user id
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
@@ -33,21 +34,68 @@ module.exports = async function serverError({
|
||||
message,
|
||||
component,
|
||||
noMail,
|
||||
req,
|
||||
}) {
|
||||
const log = `🚀 SERVER ERROR ===========================\nUser Id: ${
|
||||
user?.id
|
||||
}\nUser Name: ${user?.first_name} ${user?.last_name}\nUser Email: ${
|
||||
user?.email
|
||||
}\nError Message: ${message}\nComponent: ${component}\nDate: ${Date()}\n========================================`;
|
||||
const date = new Date();
|
||||
|
||||
if (!fs.existsSync(`./.tmp/error.log`)) {
|
||||
fs.writeFileSync(`./.tmp/error.log`, "", "utf-8");
|
||||
const reqIp = (() => {
|
||||
if (!req) return null;
|
||||
try {
|
||||
const forwarded = req.headers["x-forwarded-for"];
|
||||
const realIp = req.headers["x-real-ip"];
|
||||
const cloudflareIp = req.headers["cf-connecting-ip"];
|
||||
|
||||
// Convert forwarded IPs to string and get the first IP if multiple exist
|
||||
const forwardedIp = Array.isArray(forwarded)
|
||||
? forwarded[0]
|
||||
: forwarded?.split(",")[0];
|
||||
|
||||
const clientIp =
|
||||
cloudflareIp ||
|
||||
forwardedIp ||
|
||||
realIp ||
|
||||
req.socket.remoteAddress;
|
||||
if (!clientIp) return null;
|
||||
|
||||
return String(clientIp);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
|
||||
try {
|
||||
let log = `🚀 SERVER ERROR ===========================\nError Message: ${message}\nComponent: ${component}`;
|
||||
|
||||
if (user?.id && user?.first_name && user?.last_name && user?.email) {
|
||||
log += `\nUser Id: ${user?.id}\nUser Name: ${user?.first_name} ${user?.last_name}\nUser Email: ${user?.email}`;
|
||||
}
|
||||
|
||||
if (req?.url) {
|
||||
log += `\nURL: ${req.url}`;
|
||||
}
|
||||
|
||||
if (req?.body) {
|
||||
log += `\nRequest Body: ${JSON.stringify(req.body, null, 4)}`;
|
||||
}
|
||||
|
||||
if (reqIp) {
|
||||
log += `\nIP: ${reqIp}`;
|
||||
}
|
||||
|
||||
log += `\nDate: ${date.toDateString()}`;
|
||||
log += "\n========================================";
|
||||
|
||||
if (!fs.existsSync(`./.tmp/error.log`)) {
|
||||
fs.writeFileSync(`./.tmp/error.log`, "", "utf-8");
|
||||
}
|
||||
|
||||
const initialText = fs.readFileSync(`./.tmp/error.log`, "utf-8");
|
||||
|
||||
fs.writeFileSync(`./.tmp/error.log`, log);
|
||||
fs.appendFileSync(`./.tmp/error.log`, `\n\n\n\n\n${initialText}`);
|
||||
} catch (/** @type {any} */ error) {
|
||||
console.log("Server Error Reporting Error:", error.message);
|
||||
}
|
||||
|
||||
const initialText = fs.readFileSync(`./.tmp/error.log`, "utf-8");
|
||||
|
||||
fs.writeFileSync(`./.tmp/error.log`, log);
|
||||
fs.appendFileSync(`./.tmp/error.log`, `\n\n\n\n\n${initialText}`);
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// @ts-check
|
||||
|
||||
const serverError = require("./serverError");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
|
||||
/**
|
||||
* ==============================================================================
|
||||
* @param {Object} params
|
||||
* @param {string | number} params.userId
|
||||
* @param {import("../../types").DSQL_DatabaseSchemaType[]} params.schemaData
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export default function setUserSchemaData({ userId, schemaData }) {
|
||||
try {
|
||||
const userSchemaFilePath = path.resolve(
|
||||
process.cwd(),
|
||||
`${process.env.DSQL_USER_DB_SCHEMA_PATH}/user-${userId}/main.json`
|
||||
);
|
||||
fs.writeFileSync(
|
||||
userSchemaFilePath,
|
||||
JSON.stringify(schemaData),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch (/** @type {any} */ error) {
|
||||
serverError({
|
||||
component: "/functions/backend/setUserSchemaData",
|
||||
message: error.message,
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
@@ -1,8 +1,9 @@
|
||||
// @ts-check
|
||||
|
||||
const { IncomingMessage } = require("http");
|
||||
const decrypt = require("./decrypt");
|
||||
const parseCookies = require("../../utils/backend/parseCookies");
|
||||
const decrypt = require("../dsql/decrypt");
|
||||
const getAuthCookieNames = require("./cookies/get-auth-cookie-names");
|
||||
|
||||
/**
|
||||
* @async
|
||||
@@ -11,14 +12,18 @@ const parseCookies = require("../../utils/backend/parseCookies");
|
||||
* @returns {Promise<({ email: string, password: string, authKey: string, logged_in_status: boolean, date: number } | null)>}
|
||||
*/
|
||||
module.exports = async function (req) {
|
||||
const { keyCookieName, csrfCookieName } = getAuthCookieNames();
|
||||
const suKeyName = `${keyCookieName}_su`;
|
||||
|
||||
const cookies = parseCookies({ request: req });
|
||||
/** ********************* Check for existence of required cookie */
|
||||
if (!cookies?.datasquirelSuAdminUserAuthKey) {
|
||||
if (!cookies?.[suKeyName]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** ********************* Grab the payload */
|
||||
let userPayload = decrypt(cookies.datasquirelSuAdminUserAuthKey);
|
||||
let userPayload = decrypt({
|
||||
encryptedString: cookies[suKeyName],
|
||||
});
|
||||
|
||||
/** ********************* Return if no payload */
|
||||
if (!userPayload) return null;
|
||||
|
||||
Reference in New Issue
Block a user