This commit is contained in:
Benjamin Toby 2024-11-06 07:26:23 +01:00
parent d81f38809b
commit 190598aa3f
42 changed files with 3766 additions and 298 deletions

View File

@ -3,9 +3,9 @@
* No imports found for this Module
==== MODULE TRACE END ==== */
// @ts-check
const runQuery = require("../../package-shared/functions/backend/db/runQuery");
const runQuery = require("./utils/runQuery");
// @ts-check
/**
* @typedef {Object} LocalGetReturn
@ -39,7 +39,6 @@ async function localGet({ options, dbSchema }) {
/** @type {string | undefined | any } */
const tableName = options?.tableName ? options.tableName : undefined;
const dbFullName = process.env.DSQL_DB_NAME || "";
/**
@ -71,6 +70,7 @@ async function localGet({ options, dbSchema }) {
queryValuesArray: queryValues,
dbSchema,
tableName,
local: true,
});
if (error) throw error;

View File

@ -1,6 +1,6 @@
// @ts-check
const runQuery = require("./utils/runQuery");
const runQuery = require("../../package-shared/functions/backend/db/runQuery");
/**
* Make a get request to Datasquirel API
@ -52,6 +52,7 @@ async function localPost({ options, dbSchema }) {
dbSchema: dbSchema,
queryValuesArray: queryValues,
tableName,
local: true,
});
if (error) throw error;

View File

@ -1,184 +0,0 @@
// @ts-check
/**
* Imports: Handle imports
*/
const encrypt = require("../../../functions/encrypt");
const dbHandler = require("../../engine/utils/dbHandler");
const updateDb = require("./updateDbEntry");
const updateDbEntry = require("./updateDbEntry");
/**
* Add a db Entry Function
* ==============================================================================
* @description Description
* @async
*
* @param {object} params - An object containing the function parameters.
* "Read only" or "Full Access"? Defaults to "Read Only"
* @param {string} params.dbFullName - Database full name
* @param {string} params.tableName - Table name
* @param {*} params.data - Data to add
* @param {import("../../../package-shared/types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @param {string} [params.duplicateColumnName] - Duplicate column name
* @param {string} [params.duplicateColumnValue] - Duplicate column value
* @param {boolean} [params.update] - Update this row if it exists
* @param {string} params.encryptionKey - Update this row if it exists
* @param {string} params.encryptionSalt - Update this row if it exists
*
* @returns {Promise<*>}
*/
async function addDbEntry({
dbFullName,
tableName,
data,
tableSchema,
duplicateColumnName,
duplicateColumnValue,
update,
encryptionKey,
encryptionSalt,
}) {
/**
* Initialize variables
*/
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Handle function logic
*/
if (duplicateColumnName && typeof duplicateColumnName === "string") {
const duplicateValue = await dbHandler({
database: dbFullName,
query: `SELECT * FROM \`${tableName}\` WHERE \`${duplicateColumnName}\`=?`,
values: [duplicateColumnValue || ""],
});
if (duplicateValue && duplicateValue[0] && !update) {
return null;
} else if (duplicateValue && duplicateValue[0] && update) {
return await updateDbEntry({
dbFullName,
tableName,
data,
tableSchema,
identifierColumnName: duplicateColumnName,
identifierValue: duplicateColumnValue || "",
encryptionKey,
encryptionSalt,
});
}
}
/**
* Declare variables
*
* @description Declare "results" variable
*/
const dataKeys = Object.keys(data);
let insertKeysArray = [];
let insertValuesArray = [];
for (let i = 0; i < dataKeys.length; i++) {
try {
const dataKey = dataKeys[i];
let value = data[dataKey];
const targetFieldSchemaArray = tableSchema
? tableSchema?.fields?.filter(
(field) => field.fieldName == dataKey
)
: null;
const targetFieldSchema =
targetFieldSchemaArray && targetFieldSchemaArray[0]
? targetFieldSchemaArray[0]
: null;
if (!value) continue;
if (targetFieldSchema?.encrypted) {
value = encrypt({ data: value, encryptionKey, encryptionSalt });
console.log("DSQL: Encrypted value =>", value);
}
if (targetFieldSchema?.pattern) {
const pattern = new RegExp(
targetFieldSchema.pattern,
targetFieldSchema.patternFlags || ""
);
if (!value?.toString()?.match(pattern)) {
console.log("DSQL: Pattern not matched =>", value);
value = "";
}
}
if (typeof value === "string" && !value.match(/./i)) {
value = {
toSqlString: function () {
return "NULL";
},
};
}
insertKeysArray.push("`" + dataKey + "`");
if (typeof value === "object") {
value = JSON.stringify(value);
}
insertValuesArray.push(value);
} catch (/** @type {*} */ error) {
console.log("DSQL: Error in parsing data keys =>", error.message);
continue;
}
}
////////////////////////////////////////
insertKeysArray.push("`date_created`");
insertValuesArray.push(Date());
insertKeysArray.push("`date_created_code`");
insertValuesArray.push(Date.now());
////////////////////////////////////////
insertKeysArray.push("`date_updated`");
insertValuesArray.push(Date());
insertKeysArray.push("`date_updated_code`");
insertValuesArray.push(Date.now());
////////////////////////////////////////
const query = `INSERT INTO \`${tableName}\` (${insertKeysArray.join(
","
)}) VALUES (${insertValuesArray.map(() => "?").join(",")})`;
const queryValuesArray = insertValuesArray;
const newInsert = await dbHandler({
database: dbFullName,
query: query,
values: queryValuesArray,
});
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Return statement
*/
return newInsert;
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
module.exports = addDbEntry;

View File

@ -1,10 +1,9 @@
// @ts-check
const hashPassword = require("../../functions/hashPassword");
const addDbEntry = require("../../package-shared/functions/backend/db/addDbEntry");
const addUsersTableToDb = require("../engine/addUsersTableToDb");
const varDatabaseDbHandler = require("../engine/utils/varDatabaseDbHandler");
const addDbEntry = require("../query/utils/addDbEntry");
const runQuery = require("../query/utils/runQuery");
/**
* Make a get request to Datasquirel API

View File

@ -8,8 +8,8 @@
const fs = require("fs");
const http = require("http");
const varDatabaseDbHandler = require("../../../engine/utils/varDatabaseDbHandler");
const addDbEntry = require("../../../query/utils/addDbEntry");
const encrypt = require("../../../../functions/encrypt");
const addDbEntry = require("../../../../package-shared/functions/backend/db/addDbEntry");
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////

View File

@ -1,6 +1,6 @@
// @ts-check
const updateDbEntry = require("../query/utils/updateDbEntry");
const updateDbEntry = require("../../package-shared/functions/backend/db/updateDbEntry");
/**
* @typedef {Object} LocalPostReturn

300
package-lock.json generated
View File

@ -1,32 +1,62 @@
{
"name": "datasquirel",
"version": "2.1.1",
"version": "2.3.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "datasquirel",
"version": "2.1.1",
"version": "2.3.5",
"license": "ISC",
"dependencies": {
"@types/ace": "^0.0.52",
"@types/react": "^18.3.12",
"@types/tinymce": "^4.6.9",
"dotenv": "^16.3.1",
"generate-password": "^1.7.1",
"lodash": "^4.17.21",
"mysql": "^2.18.1",
"nodemailer": "^6.9.14"
"nodemailer": "^6.9.14",
"sanitize-html": "^2.13.1",
"serverless-mysql": "^1.5.5"
},
"bin": {
"dsql-dump": "engine/dump.js",
"dsql-watch": "engine/dsql.js"
},
"devDependencies": {
"@types/lodash": "^4.17.13",
"@types/mysql": "^2.15.21",
"@types/node": "^22.7.5"
}
},
"node_modules/@types/ace": {
"version": "0.0.52",
"resolved": "https://registry.npmjs.org/@types/ace/-/ace-0.0.52.tgz",
"integrity": "sha512-YPF9S7fzpuyrxru+sG/rrTpZkC6gpHBPF14W3x70kqVOD+ks6jkYLapk4yceh36xej7K4HYxcyz9ZDQ2lTvwgQ==",
"license": "MIT"
},
"node_modules/@types/jquery": {
"version": "3.5.32",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.32.tgz",
"integrity": "sha512-b9Xbf4CkMqS02YH8zACqN1xzdxc3cO735Qe5AbSUFmyOiaWAbcpqh9Wna+Uk0vgACvoQHpWDg2rGdHkYPLmCiQ==",
"license": "MIT",
"dependencies": {
"@types/sizzle": "*"
}
},
"node_modules/@types/lodash": {
"version": "4.17.13",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz",
"integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/mysql": {
"version": "2.15.21",
"resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.21.tgz",
"integrity": "sha512-NPotx5CVful7yB+qZbWtXL2fA4e7aEHkihHLjklc6ID8aq7bhguHgeIoC1EmSNTAuCgI6ZXrjt2ZSaXnYX0EUg==",
"dev": true,
"devOptional": true,
"dependencies": {
"@types/node": "*"
}
@ -35,12 +65,43 @@
"version": "22.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.13",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.3.12",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
"integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/sizzle": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz",
"integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==",
"license": "MIT"
},
"node_modules/@types/tinymce": {
"version": "4.6.9",
"resolved": "https://registry.npmjs.org/@types/tinymce/-/tinymce-4.6.9.tgz",
"integrity": "sha512-pDxBUlV4v1jgJ97SlnVOSyf3KUy3OQ3s5Ddpfh1L9M5lXlBmX7TJ2OLSozx1WBxp91acHvYPWDwz2U/kMM1oxQ==",
"license": "MIT",
"dependencies": {
"@types/jquery": "*"
}
},
"node_modules/bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
@ -54,6 +115,76 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT"
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "BSD-2-Clause"
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
@ -65,16 +196,80 @@
"url": "https://github.com/motdotla/dotenv?sponsor=1"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/generate-password": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/generate-password/-/generate-password-1.7.1.tgz",
"integrity": "sha512-9bVYY+16m7W7GczRBDqXE+VVuCX+bWNrfYKC/2p2JkZukFb2sKxT6E3zZ3mJGz7GMe5iRK0A/WawSL3jQfJuNQ==",
"license": "MIT"
},
"node_modules/htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"license": "MIT"
},
"node_modules/mysql": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
@ -89,6 +284,24 @@
"node": ">= 0.6"
}
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/nodemailer": {
"version": "6.9.14",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz",
@ -98,6 +311,46 @@
"node": ">=6.0.0"
}
},
"node_modules/parse-srcset": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==",
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.4.47",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.0",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@ -122,6 +375,41 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/sanitize-html": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.1.tgz",
"integrity": "sha512-ZXtKq89oue4RP7abL9wp/9URJcqQNABB5GGJ2acW1sdO8JTVl92f4ygD7Yc9Ze09VAZhnt2zegeU0tbNsdcLYg==",
"license": "MIT",
"dependencies": {
"deepmerge": "^4.2.2",
"escape-string-regexp": "^4.0.0",
"htmlparser2": "^8.0.0",
"is-plain-object": "^5.0.0",
"parse-srcset": "^1.0.2",
"postcss": "^8.3.11"
}
},
"node_modules/serverless-mysql": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/serverless-mysql/-/serverless-mysql-1.5.5.tgz",
"integrity": "sha512-QwaCtswn3GKCnqyVA0whwDFMIw91iKTeTvf6F++HoGiunfyvfJ2MdU8d3MKMQdKGNOXIvmUlLq/JVjxuPQxkrw==",
"license": "MIT",
"dependencies": {
"mysql": "^2.18.1"
},
"optionalDependencies": {
"@types/mysql": "^2.15.6"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sqlstring": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
@ -142,7 +430,7 @@
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/util-deprecate": {

View File

@ -1,3 +1,7 @@
# Shared resources
This directory contains data (mostly type definitions) shared by both the datasquirel NPM package and the datasquirel web app
## Functions
## Types

View File

@ -0,0 +1,66 @@
// @ts-check
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");
/**
* # Add Mariadb User
*
* @description this function adds a Mariadb user to the database server
*
* @param {object} params - parameters object *
* @param {number | string} params.userId - invited user object
*
* @returns {Promise<any>} new user auth object payload
*/
module.exports = async function addMariadbUser({ userId }) {
try {
const defaultMariadbUserHost = process.env.DSQL_DB_HOST || "127.0.0.1";
const username = `dsql_user_${userId}`;
const password = generator.generate({
length: 16,
numbers: true,
symbols: true,
uppercase: true,
exclude: "*#.'`\"",
});
const encryptedPassword = encrypt(password);
await NO_DB_HANDLER(
`CREATE USER IF NOT EXISTS '${username}'@'127.0.0.1' IDENTIFIED BY '${password}' REQUIRE SSL`
);
const updateUser = await DB_HANDLER(
`UPDATE users SET mariadb_user = ?, mariadb_host = '127.0.0.1', mariadb_pass = ? WHERE id = ?`,
[username, encryptedPassword, userId]
);
const addMariadbUser = await addDbEntry({
tableName: "mariadb_users",
data: {
user_id: userId,
username,
host: defaultMariadbUserHost,
password: encryptedPassword,
primary: "1",
grants: '[{"database":"*","table":"*","privileges":["ALL"]}]',
},
dbContext: "Master",
});
console.log(`User ${userId} SQL credentials successfully added.`);
} catch (/** @type {any} */ error) {
console.log(
`Error in adding SQL user in 'addMariadbUser' function =>`,
error.message
);
}
};
////////////////////////////////////////////////
////////////////////////////////////////////////
////////////////////////////////////////////////

View File

@ -0,0 +1,43 @@
// @ts-check
const fs = require("fs");
const decrypt = require("./decrypt");
/** @type {import("../../types").CheckApiCredentialsFn} */
const grabApiCred = ({ key, database, table }) => {
try {
const allowedKeysPath = process.env.DSQL_API_KEYS_PATH;
if (!allowedKeysPath)
throw new Error(
"process.env.DSQL_API_KEYS_PATH variable not found"
);
const ApiJSON = decrypt(key);
/** @type {import("../../types").ApiKeyObject} */
const ApiObject = JSON.parse(ApiJSON || "");
const isApiKeyValid = fs.existsSync(
`${allowedKeysPath}/${ApiObject.sign}`
);
if (!isApiKeyValid) return null;
if (!ApiObject.target_database) return ApiObject;
if (!database && ApiObject.target_database) return null;
const isDatabaseAllowed = ApiObject.target_database
?.split(",")
.includes(String(database));
if (isDatabaseAllowed && !ApiObject.target_table) return ApiObject;
if (isDatabaseAllowed && !table && ApiObject.target_table) return null;
const isTableAllowed = ApiObject.target_table
?.split(",")
.includes(String(table));
if (isTableAllowed) return ApiObject;
return null;
} catch (/** @type {any} */ error) {
console.log(`api-cred ERROR: ${error.message}`);
return null;
}
};
module.exports = grabApiCred;

View File

@ -0,0 +1,163 @@
// @ts-check
const fs = require("fs");
const DB_HANDLER = require("../../../utils/backend/global-db/DB_HANDLER");
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* Add Database Entry
* ==============================================================================
* @param {object} params - foundUser if any
* @param {string} params.tableName - Table Name
* @param {any} params.data - Data to be added
* @param {string} [params.duplicateColumnName] - Duplicate Column Name
* @param {string | number} [params.duplicateColumnValue] - Duplicate Column Value
*/
module.exports = async function addDbEntry({
tableName,
data,
duplicateColumnName,
duplicateColumnValue,
}) {
/**
* Check Duplicate if specified
*
* @description Check Duplicate if specified
*/
if (duplicateColumnName) {
let duplicateEntry = await DB_HANDLER(
`SELECT ${duplicateColumnName} FROM ${tableName} WHERE ${duplicateColumnName}='${duplicateColumnValue}'`
);
if (duplicateEntry && duplicateEntry[0]) return null;
}
/**
* Declare variables
*
* @description Declare "results" variable
*/
const dataKeys = Object.keys(data);
let insertKeysArray = [];
let insertValuesArray = [];
for (let i = 0; i < dataKeys.length; i++) {
const dataKey = dataKeys[i];
let dataValue = data[dataKey];
// const correspondingColumnObject = dbColumns.filter((col) => col.Field === dataKey);
// const { Field, Type, Null, Key, Default, Extra } = correspondingColumnObject;
if (!dataValue) continue;
insertKeysArray.push("`" + dataKey + "`");
if (typeof dataValue === "object") {
dataValue = JSON.stringify(data[dataKey]);
}
// let parsedDataValue = dataValue.toString().replace(/\'/g, "\\'");
insertValuesArray.push(dataValue);
}
////////////////////////////////////////
// @ts-ignore
let existingDateCreatedColumn = await DB_HANDLER(
`SHOW COLUMNS FROM \`${tableName}\` WHERE Field = 'date_created'`
);
if (!existingDateCreatedColumn || !existingDateCreatedColumn[0]) {
// @ts-ignore
await DB_HANDLER(
`ALTER TABLE ${tableName} ADD COLUMN date_created VARCHAR(255) NOT NULL`
);
}
insertKeysArray.push("date_created");
insertValuesArray.push(Date());
////////////////////////////////////////
// @ts-ignore
let existingDateCreatedCodeColumn = await DB_HANDLER(
`SHOW COLUMNS FROM ${tableName} WHERE Field = 'date_created_code'`
);
if (!existingDateCreatedCodeColumn || !existingDateCreatedCodeColumn[0]) {
// @ts-ignore
await DB_HANDLER(
`ALTER TABLE ${tableName} ADD COLUMN date_created_code BIGINT NOT NULL`
);
}
insertKeysArray.push("date_created_code");
insertValuesArray.push(Date.now());
////////////////////////////////////////
// @ts-ignore
let existingDateCodeColumn = await DB_HANDLER(
`SHOW COLUMNS FROM ${tableName} WHERE Field = 'date_code'`
);
if (existingDateCodeColumn && existingDateCodeColumn[0]) {
insertKeysArray.push("date_code");
insertValuesArray.push(Date.now());
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
// @ts-ignore
let existingDateUpdatedColumn = await DB_HANDLER(
`SHOW COLUMNS FROM ${tableName} WHERE Field = 'date_updated'`
);
if (!existingDateUpdatedColumn || !existingDateUpdatedColumn[0]) {
// @ts-ignore
await DB_HANDLER(
`ALTER TABLE ${tableName} ADD COLUMN date_updated VARCHAR(255) NOT NULL`
);
}
insertKeysArray.push("date_updated");
insertValuesArray.push(Date());
////////////////////////////////////////
// @ts-ignore
let existingDateUpdatedCodeColumn = await DB_HANDLER(
`SHOW COLUMNS FROM ${tableName} WHERE Field = 'date_updated_code'`
);
if (!existingDateUpdatedCodeColumn || !existingDateUpdatedCodeColumn[0]) {
// @ts-ignore
await DB_HANDLER(
`ALTER TABLE ${tableName} ADD COLUMN date_updated_code BIGINT NOT NULL`
);
}
insertKeysArray.push("date_updated_code");
insertValuesArray.push(Date.now());
////////////////////////////////////////
const query = `INSERT INTO ${tableName} (${insertKeysArray.join(
","
)}) VALUES (${insertValuesArray.map((val) => "?").join(",")})`;
const queryValuesArray = insertValuesArray;
// @ts-ignore
const newInsert = await DB_HANDLER(query, queryValuesArray);
////////////////////////////////////////
return newInsert;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
};

View File

@ -0,0 +1,232 @@
// @ts-check
/**
* Imports: Handle imports
*/
const encrypt = require("../encrypt");
const sanitizeHtml = require("sanitize-html");
const sanitizeHtmlOptions = require("../html/sanitizeHtmlOptions");
const updateDb = require("./updateDbEntry");
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");
/**
* Add a db Entry Function
* ==============================================================================
* @description Description
* @async
*
* @param {object} params - An object containing the function parameters.
* @param {("Master" | "Dsql User")} [params.dbContext] - What is the database context? "Master"
* or "Dsql User". Defaults to "Master"
* @param {("Read Only" | "Full Access")} [params.paradigm] - What is the paradigm for "Dsql User"?
* "Read only" or "Full Access"? Defaults to "Read Only"
* @param {string} [params.dbFullName] - Database full name
* @param {string} params.tableName - Table name
* @param {any} params.data - Data to add
* @param {import("../../../types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @param {string} [params.duplicateColumnName] - Duplicate column name
* @param {string} [params.duplicateColumnValue] - Duplicate column value
* @param {boolean} [params.update] - Update this row if it exists
* @param {string} [params.encryptionKey] - Update this row if it exists
* @param {string} [params.encryptionSalt] - Update this row if it exists
*
* @returns {Promise<any>}
*/
async function addDbEntry({
dbContext,
paradigm,
dbFullName,
tableName,
data,
tableSchema,
duplicateColumnName,
duplicateColumnValue,
update,
encryptionKey,
encryptionSalt,
}) {
/**
* Initialize variables
*/
const isMaster = dbContext?.match(/dsql.user/i)
? false
: dbFullName && !dbFullName.match(/^datasquirel$/)
? false
: true;
/** @type { any } */
const dbHandler = isMaster ? DB_HANDLER : DSQL_USER_DB_HANDLER;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
if (data?.["date_created_timestamp"]) delete data["date_created_timestamp"];
if (data?.["date_updated_timestamp"]) delete data["date_updated_timestamp"];
if (data?.["date_updated"]) delete data["date_updated"];
if (data?.["date_updated_code"]) delete data["date_updated_code"];
if (data?.["date_created"]) delete data["date_created"];
if (data?.["date_created_code"]) delete data["date_created_code"];
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Handle function logic
*/
if (duplicateColumnName && typeof duplicateColumnName === "string") {
const duplicateValue = isMaster
? await dbHandler(
`SELECT * FROM \`${tableName}\` WHERE \`${duplicateColumnName}\`=?`,
[duplicateColumnValue]
)
: await dbHandler({
paradigm: "Read Only",
database: dbFullName,
queryString: `SELECT * FROM \`${tableName}\` WHERE \`${duplicateColumnName}\`=?`,
queryValues: [duplicateColumnValue],
});
if (duplicateValue?.[0] && !update) {
return null;
} else if (duplicateValue && duplicateValue[0] && update) {
return await updateDbEntry({
dbContext,
paradigm,
dbFullName,
tableName,
data,
tableSchema,
encryptionKey,
encryptionSalt,
identifierColumnName: duplicateColumnName,
identifierValue: duplicateColumnValue || "",
});
}
}
/**
* Declare variables
*
* @description Declare "results" variable
*/
const dataKeys = Object.keys(data);
let insertKeysArray = [];
let insertValuesArray = [];
for (let i = 0; i < dataKeys.length; i++) {
try {
const dataKey = dataKeys[i];
// @ts-ignore
let value = data?.[dataKey];
const targetFieldSchemaArray = tableSchema
? tableSchema?.fields?.filter(
(field) => field.fieldName == dataKey
)
: null;
const targetFieldSchema =
targetFieldSchemaArray && targetFieldSchemaArray[0]
? targetFieldSchemaArray[0]
: null;
if (value == null || value == undefined) continue;
if (targetFieldSchema?.encrypted) {
value = encrypt(value, encryptionKey, encryptionSalt);
console.log("DSQL: Encrypted value =>", value);
}
if (targetFieldSchema?.richText) {
value = sanitizeHtml(value, sanitizeHtmlOptions);
}
if (targetFieldSchema?.pattern) {
const pattern = new RegExp(
targetFieldSchema.pattern,
targetFieldSchema.patternFlags || ""
);
if (!pattern.test(value)) {
console.log("DSQL: Pattern not matched =>", value);
value = "";
}
}
insertKeysArray.push("`" + dataKey + "`");
if (typeof value === "object") {
value = JSON.stringify(value);
}
if (typeof value == "number") {
insertValuesArray.push(String(value));
} else {
insertValuesArray.push(value);
}
} catch (/** @type {any} */ error) {
console.log("DSQL: Error in parsing data keys =>", error.message);
continue;
}
}
////////////////////////////////////////
if (!data?.["date_created"]) {
insertKeysArray.push("`date_created`");
insertValuesArray.push(Date());
}
if (!data?.["date_created_code"]) {
insertKeysArray.push("`date_created_code`");
insertValuesArray.push(Date.now());
}
////////////////////////////////////////
if (!data?.["date_updated"]) {
insertKeysArray.push("`date_updated`");
insertValuesArray.push(Date());
}
if (!data?.["date_updated_code"]) {
insertKeysArray.push("`date_updated_code`");
insertValuesArray.push(Date.now());
}
////////////////////////////////////////
const query = `INSERT INTO \`${tableName}\` (${insertKeysArray.join(
","
)}) VALUES (${insertValuesArray.map(() => "?").join(",")})`;
const queryValuesArray = insertValuesArray;
const newInsert = isMaster
? await dbHandler(query, queryValuesArray)
: await dbHandler({
paradigm,
database: dbFullName,
queryString: query,
queryValues: queryValuesArray,
});
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Return statement
*/
return newInsert;
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
module.exports = addDbEntry;

View File

@ -1,6 +1,7 @@
// @ts-check
const dbHandler = require("../../engine/utils/dbHandler");
const DB_HANDLER = require("../../../utils/backend/global-db/DB_HANDLER");
const DSQL_USER_DB_HANDLER = require("../../../utils/backend/global-db/DSQL_USER_DB_HANDLER");
/**
* Imports: Handle imports
@ -19,7 +20,7 @@ const dbHandler = require("../../engine/utils/dbHandler");
* "Read only" or "Full Access"? Defaults to "Read Only"
* @param {string} params.dbFullName - Database full name
* @param {string} params.tableName - Table name
* @param {import("../../../package-shared/types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @param {import("../../../types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @param {string} params.identifierColumnName - Update row identifier column name
* @param {string|number} params.identifierValue - Update row identifier column value
*
@ -37,6 +38,14 @@ async function deleteDbEntry({
/**
* Check if data is valid
*/
const isMaster = dbContext?.match(/dsql.user/i)
? false
: dbFullName && !dbFullName.match(/^datasquirel$/)
? false
: true;
/** @type { (a1:any, a2?:any) => any } */
const dbHandler = isMaster ? DB_HANDLER : DSQL_USER_DB_HANDLER;
////////////////////////////////////////
////////////////////////////////////////
@ -49,11 +58,14 @@ async function deleteDbEntry({
*/
const query = `DELETE FROM ${tableName} WHERE \`${identifierColumnName}\`=?`;
const deletedEntry = await dbHandler({
query: query,
database: dbFullName,
values: [identifierValue],
});
const deletedEntry = isMaster
? await dbHandler(query, [identifierValue])
: await dbHandler({
paradigm,
queryString: query,
database: dbFullName,
queryValues: [identifierValue],
});
////////////////////////////////////////
////////////////////////////////////////

View File

@ -0,0 +1,41 @@
// @ts-check
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* Sanitize SQL function
* ==============================================================================
* @description this function takes in a text(or number) and returns a sanitized
* text, usually without spaces
*
* @param {string|number} text - Text or number or object
*
* @returns {string}
*/
function pathTraversalCheck(text) {
/**
* Initial Checks
*
* @description Initial Checks
*/
return text.toString().replace(/\//g, "");
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
module.exports = pathTraversalCheck;

View File

@ -1,21 +1,25 @@
/** # MODULE TRACE
======================================================================
* Detected 4 files that call this module. The files are listed below:
* Detected 3 files that call this module. The files are listed below:
======================================================================
* `require` Statement Found in [get.js](d:\GitHub\dsql\engine\query\get.js)
* `require` Statement Found in [post.js](d:\GitHub\dsql\engine\query\post.js)
* `require` Statement Found in [add-user.js](d:\GitHub\dsql\engine\user\add-user.js)
* `require` Statement Found in [update-user.js](d:\GitHub\dsql\engine\user\update-user.js)
* `import` Statement Found in [get.js] => file:///d:\GitHub\datasquirel\pages\api\query\get.js
* `import` Statement Found in [post.js] => file:///d:\GitHub\datasquirel\pages\api\query\post.js
* `import` Statement Found in [add-user.js] => file:///d:\GitHub\datasquirel\pages\api\user\add-user.js
==== MODULE TRACE END ==== */
// @ts-check
const fs = require("fs");
const fullAccessDbHandler = require("../fullAccessDbHandler");
const varReadOnlyDatabaseDbHandler = require("../varReadOnlyDatabaseDbHandler");
const serverError = require("../serverError");
const addDbEntry = require("./addDbEntry");
const updateDbEntry = require("./updateDbEntry");
const deleteDbEntry = require("./deleteDbEntry");
const varDatabaseDbHandler = require("../../engine/utils/varDatabaseDbHandler");
const DB_HANDLER = require("../../../utils/backend/global-db/DB_HANDLER");
const parseDbResults = require("../parseDbResults");
/** ****************************************************************************** */
/** ****************************************************************************** */
@ -29,13 +33,14 @@ const varDatabaseDbHandler = require("../../engine/utils/varDatabaseDbHandler");
* ==============================================================================
* @param {object} params - An object containing the function parameters.
* @param {string} params.dbFullName - Database full name. Eg. "datasquire_user_2_test"
* @param {*} params.query - Query string or object
* @param {string | any} params.query - Query string or object
* @param {boolean} [params.readOnly] - Is this operation read only?
* @param {import("../../../package-shared/types").DSQL_DatabaseSchemaType} [params.dbSchema] - Database schema
* @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<{result: *, error?: *}>}
* @return {Promise<any>}
*/
async function runQuery({
dbFullName,
@ -44,16 +49,20 @@ async function runQuery({
dbSchema,
queryValuesArray,
tableName,
local,
}) {
/**
* Declare variables
*
* @description Declare "results" variable
*/
const encryptionKey = process.env.DSQL_ENCRYPTION_KEY || "";
const encryptionSalt = process.env.DSQL_ENCRYPTION_SALT || "";
let result, error, tableSchema;
/** @type {any} */
let result;
/** @type {any} */
let error;
/** @type {import("../../../types").DSQL_TableSchemaType | undefined} */
let tableSchema;
if (dbSchema) {
try {
@ -68,7 +77,9 @@ async function runQuery({
tableSchema = dbSchema.tables.filter(
(tb) => tb?.tableName === table
)[0];
} catch (_err) {}
} catch (_err) {
// console.log("ERROR getting tableSchema: ", _err.message);
}
}
/**
@ -78,12 +89,29 @@ async function runQuery({
*/
try {
if (typeof query === "string") {
result = await varDatabaseDbHandler({
queryString: query,
queryValuesArray,
database: dbFullName,
tableSchema,
});
if (local) {
const rawResults = await DB_HANDLER(query, queryValuesArray);
result = tableSchema
? parseDbResults({
unparsedResults: rawResults,
tableSchema,
})
: rawResults;
} else if (readOnly) {
result = await varReadOnlyDatabaseDbHandler({
queryString: query,
queryValuesArray,
database: dbFullName,
tableSchema,
});
} else {
result = await fullAccessDbHandler({
queryString: query,
queryValuesArray,
database: dbFullName,
tableSchema,
});
}
} else if (typeof query === "object") {
/**
* Declare variables
@ -104,6 +132,8 @@ async function runQuery({
switch (action.toLowerCase()) {
case "insert":
result = await addDbEntry({
dbContext: local ? "Master" : "Dsql User",
paradigm: "Full Access",
dbFullName: dbFullName,
tableName: table,
data: data,
@ -111,8 +141,6 @@ async function runQuery({
duplicateColumnName,
duplicateColumnValue,
tableSchema,
encryptionKey,
encryptionSalt,
});
if (!result?.insertId) {
@ -123,7 +151,7 @@ async function runQuery({
case "update":
result = await updateDbEntry({
dbContext: "Dsql User",
dbContext: local ? "Master" : "Dsql User",
paradigm: "Full Access",
dbFullName: dbFullName,
tableName: table,
@ -131,15 +159,13 @@ async function runQuery({
identifierColumnName,
identifierValue,
tableSchema,
encryptionKey,
encryptionSalt,
});
break;
case "delete":
result = await deleteDbEntry({
dbContext: "Dsql User",
dbContext: local ? "Master" : "Dsql User",
paradigm: "Full Access",
dbFullName: dbFullName,
tableName: table,
@ -151,12 +177,7 @@ async function runQuery({
break;
default:
console.log("Unhandled Query");
console.log("Query Recieved =>", query);
result = {
result: null,
error: "Unhandled Query",
};
result = null;
break;
}
}
@ -164,14 +185,12 @@ async function runQuery({
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
} catch (/** @type {*} */ error) {
console.log("Error in Running Query =>", error.message);
console.log("Query Recieved =>", query);
result = {
result: null,
error: "Error in running Query => " + error.message,
};
} catch (/** @type {any} */ error) {
serverError({
component: "functions/backend/runQuery",
message: error.message,
});
result = null;
error = error.message;
}

View File

@ -0,0 +1,207 @@
// @ts-check
const _ = require("lodash");
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* Sanitize SQL function
* ==============================================================================
* @description this function takes in a text(or number) and returns a sanitized
* text, usually without spaces
*
* @param {any} text - Text or number or object
* @param {boolean} [spaces] - Allow spaces
* @param {RegExp?} [regex] - Regular expression, removes any match
*
* @returns {any}
*/
function sanitizeSql(text, spaces, regex) {
/**
* Initial Checks
*
* @description Initial Checks
*/
if (!text) return "";
if (typeof text == "number" || typeof text == "boolean") return text;
if (typeof text == "string" && !text?.toString()?.match(/./)) return "";
if (typeof text == "object" && !Array.isArray(text)) {
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
const newObject = sanitizeObjects(text, spaces);
return newObject;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
} else if (typeof text == "object" && Array.isArray(text)) {
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
const newArray = sanitizeArrays(text, spaces);
return newArray;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
}
// if (text?.toString()?.match(/\'|\"/)) {
// console.log("TEXT containing commas =>", text);
// return "";
// }
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Declare variables
*
* @description Declare "results" variable
*/
let finalText = text;
if (regex) {
finalText = text.toString().replace(regex, "");
}
if (spaces) {
} else {
finalText = text
.toString()
.replace(/\n|\r|\n\r|\r\n/g, "")
.replace(/ /g, "");
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
const escapeRegex =
/select |insert |drop |delete |alter |create |exec | union | or | like | concat|LOAD_FILE|ASCII| COLLATE | HAVING | information_schema|DECLARE |\#|WAITFOR |delay |BENCHMARK |\/\*.*\*\//gi;
finalText = finalText
.replace(/(?<!\\)\'/g, "\\'")
.replace(/(?<!\\)\`/g, "\\`")
// .replace(/(?<!\\)\"/g, '\\"')
.replace(/\/\*\*\//g, "")
.replace(escapeRegex, "\\$&");
// const injectionRegexp = /select .* from|\*|delete from|drop database|drop table|update .* set/i;
// if (text?.toString()?.match(injectionRegexp)) {
// console.log("ATTEMPTED INJECTION =>", text);
// return "";
// }
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
return finalText;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* Sanitize Objects Function
* ==============================================================================
* @description Sanitize objects in the form { key: "value" }
*
* @param {any} object - Database Full Name
* @param {boolean} [spaces] - Allow spaces
*
* @returns {object}
*/
function sanitizeObjects(object, spaces) {
/** @type {any} */
let objectUpdated = { ...object };
const keys = Object.keys(objectUpdated);
keys.forEach((key) => {
const value = objectUpdated[key];
if (!value) {
delete objectUpdated[key];
return;
}
if (typeof value == "string" || typeof value == "number") {
objectUpdated[key] = sanitizeSql(value, spaces);
} else if (typeof value == "object" && !Array.isArray(value)) {
objectUpdated[key] = sanitizeObjects(value, spaces);
} else if (typeof value == "object" && Array.isArray(value)) {
objectUpdated[key] = sanitizeArrays(value, spaces);
}
});
return objectUpdated;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* Sanitize Objects Function
* ==============================================================================
* @description Sanitize objects in the form { key: "value" }
*
* @param {any[]} array - Database Full Name
* @param {boolean} [spaces] - Allow spaces
*
* @returns {string[]|number[]|object[]}
*/
function sanitizeArrays(array, spaces) {
let arrayUpdated = _.cloneDeep(array);
arrayUpdated.forEach((item, index) => {
const value = item;
if (!value) {
arrayUpdated.splice(index, 1);
return;
}
if (typeof item == "string" || typeof item == "number") {
arrayUpdated[index] = sanitizeSql(value, spaces);
} else if (typeof item == "object" && !Array.isArray(value)) {
arrayUpdated[index] = sanitizeObjects(value, spaces);
} else if (typeof item == "object" && Array.isArray(value)) {
arrayUpdated[index] = sanitizeArrays(item, spaces);
}
});
return arrayUpdated;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
module.exports = sanitizeSql;

View File

@ -1,11 +1,13 @@
// @ts-check
const encrypt = require("../../../functions/encrypt");
const dbHandler = require("../../engine/utils/dbHandler");
/**
* 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");
/**
* Update DB Function
@ -18,14 +20,14 @@ const dbHandler = require("../../engine/utils/dbHandler");
* or "Dsql User". Defaults to "Master"
* @param {("Read Only" | "Full Access")} [params.paradigm] - What is the paradigm for "Dsql User"?
* "Read only" or "Full Access"? Defaults to "Read Only"
* @param {string} params.dbFullName - Database full name
* @param {string} [params.dbFullName] - Database full name
* @param {string} params.tableName - Table name
* @param {*} params.data - Data to add
* @param {import("../../../package-shared/types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @param {string} [params.encryptionKey]
* @param {string} [params.encryptionSalt]
* @param {any} params.data - Data to add
* @param {import("../../../types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @param {string} params.identifierColumnName - Update row identifier column name
* @param {string | number} params.identifierValue - Update row identifier column value
* @param {string} params.encryptionKey - Encryption key
* @param {string} params.encryptionSalt - Encryption salt
*
* @returns {Promise<object|null>}
*/
@ -46,6 +48,15 @@ async function updateDbEntry({
*/
if (!data || !Object.keys(data).length) return null;
const isMaster = dbContext?.match(/dsql.user/i)
? false
: dbFullName && !dbFullName.match(/^datasquirel$/)
? false
: true;
/** @type {(a1:any, a2?:any)=> any } */
const dbHandler = isMaster ? DB_HANDLER : DSQL_USER_DB_HANDLER;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
@ -60,14 +71,10 @@ async function updateDbEntry({
let updateKeyValueArray = [];
let updateValues = [];
/**
* Declare variables
*
* @description Declare "results" variable
*/
for (let i = 0; i < dataKeys.length; i++) {
try {
const dataKey = dataKeys[i];
// @ts-ignore
let value = data[dataKey];
const targetFieldSchemaArray = tableSchema
@ -80,22 +87,31 @@ async function updateDbEntry({
? targetFieldSchemaArray[0]
: null;
if (typeof value == "undefined") continue;
if (
typeof value !== "string" &&
typeof value !== "number" &&
!value
)
continue;
if (value == null || value == undefined) continue;
if (targetFieldSchema?.richText) {
value = sanitizeHtml(value, sanitizeHtmlOptions);
}
if (targetFieldSchema?.encrypted) {
value = encrypt({ data: value, encryptionKey, encryptionSalt });
value = encrypt(value, encryptionKey, encryptionSalt);
}
if (typeof value === "object") {
value = JSON.stringify(value);
}
if (targetFieldSchema?.pattern) {
const pattern = new RegExp(
targetFieldSchema.pattern,
targetFieldSchema.patternFlags || ""
);
if (!pattern.test(value)) {
console.log("DSQL: Pattern not matched =>", value);
value = "";
}
}
if (typeof value === "string" && value.match(/^null$/i)) {
value = {
toSqlString: function () {
@ -104,17 +120,6 @@ async function updateDbEntry({
};
}
if (targetFieldSchema?.pattern) {
const pattern = new RegExp(
targetFieldSchema.pattern,
targetFieldSchema.patternFlags || ""
);
if (!value?.toString()?.match(pattern)) {
console.log("DSQL: Pattern not matched =>", value);
value = "";
}
}
if (typeof value === "string" && !value.match(/./i)) {
value = {
toSqlString: function () {
@ -123,14 +128,17 @@ async function updateDbEntry({
};
}
if (!value && typeof value == "number" && value != 0) continue;
updateKeyValueArray.push(`\`${dataKey}\`=?`);
updateValues.push(value);
if (typeof value == "number") {
updateValues.push(String(value));
} else {
updateValues.push(value);
}
////////////////////////////////////////
////////////////////////////////////////
} catch (/** @type {*} */ error) {
} catch (/** @type {any} */ error) {
////////////////////////////////////////
////////////////////////////////////////
@ -157,11 +165,14 @@ async function updateDbEntry({
updateValues.push(identifierValue);
const updatedEntry = await dbHandler({
database: dbFullName,
query: query,
values: updateValues,
});
const updatedEntry = isMaster
? await dbHandler(query, updateValues)
: await dbHandler({
paradigm,
database: dbFullName,
queryString: query,
queryValues: updateValues,
});
////////////////////////////////////////
////////////////////////////////////////

View File

@ -0,0 +1,90 @@
// @ts-check
const fs = require("fs");
const serverError = require("./serverError");
const mysql = require("serverless-mysql");
const path = require("path");
const SSL_DIR = "/app/ssl";
const connection = mysql({
config: {
host: process.env.DSQL_DB_HOST,
user: process.env.DSQL_DB_USERNAME,
password: process.env.DSQL_DB_PASSWORD,
database: process.env.DSQL_DB_NAME,
charset: "utf8mb4",
ssl: {
ca: fs.readFileSync(`${SSL_DIR}/ca-cert.pem`),
},
},
});
/**
* Main DB Handler Function
* ==============================================================================
* @async
*
* @param {any} args
* @returns {Promise<object|null>}
*/
module.exports = async function dbHandler(...args) {
process.env.NODE_ENV?.match(/dev/) &&
fs.appendFileSync(
"./.tmp/sqlQuery.sql",
args[0] + "\n" + Date() + "\n\n\n",
"utf8"
);
/**
* Declare variables
*
* @description Declare "results" variable
*/
let results;
/**
* Fetch from db
*
* @description Fetch data from db if no cache
*/
try {
results = await new Promise((resolve, reject) => {
// @ts-ignore
connection.query(...args, (error, result, fields) => {
if (error) {
resolve({ error: error.message });
} else {
resolve(result);
}
});
});
await connection.end();
} catch (/** @type {any} */ error) {
fs.appendFileSync(
"./.tmp/dbErrorLogs.txt",
JSON.stringify(error, null, 4) + "\n" + Date() + "\n\n\n",
"utf8"
);
results = null;
serverError({
component: "dbHandler",
message: error.message,
});
}
/**
* Return results
*
* @description Return results add to cache if "req" param is passed
*/
if (results) {
return JSON.parse(JSON.stringify(results));
} else {
return null;
}
};

View File

@ -0,0 +1,29 @@
// @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;

View File

@ -0,0 +1,15 @@
// @ts-check
/**
* Regular expression to match default fields
*
* @description Regular expression to match default fields
*/
const defaultFieldsRegexp =
/^id$|^uuid$|^date_created$|^date_created_code$|^date_created_timestamp$|^date_updated$|^date_updated_code$|^date_updated_timestamp$/;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
module.exports = defaultFieldsRegexp;

View File

@ -0,0 +1,43 @@
// @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;

View File

@ -0,0 +1,78 @@
// @ts-check
const DSQL_USER_DB_HANDLER = require("../../utils/backend/global-db/DSQL_USER_DB_HANDLER");
const parseDbResults = require("./parseDbResults");
const serverError = require("./serverError");
/**
*
* @param {object} param0
* @param {string} param0.queryString
* @param {string} param0.database
* @param {boolean} [param0.local]
* @param {import("../../types").DSQL_TableSchemaType | null} [param0.tableSchema]
* @param {string[]} [param0.queryValuesArray]
* @returns
*/
module.exports = async function fullAccessDbHandler({
queryString,
database,
tableSchema,
queryValuesArray,
local,
}) {
/**
* Declare variables
*
* @description Declare "results" variable
*/
let results;
/**
* Fetch from db
*
* @description Fetch data from db if no cache
*/
try {
/** ********************* Run Query */
results = await DSQL_USER_DB_HANDLER({
paradigm: "Full Access",
database,
queryString,
queryValues: queryValuesArray,
});
////////////////////////////////////////
} catch (/** @type {any} */ error) {
////////////////////////////////////////
serverError({
component: "fullAccessDbHandler",
message: error.message,
});
/**
* Return error
*/
return error.message;
}
/**
* Return results
*
* @description Return results add to cache if "req" param is passed
*/
if (results && tableSchema) {
const unparsedResults = results;
const parsedResults = await parseDbResults({
unparsedResults: unparsedResults,
tableSchema: tableSchema,
});
return parsedResults;
} else if (results) {
return results;
} else {
return null;
}
};

View File

@ -0,0 +1,12 @@
// @ts-check
const sanitizeHtmlOptions = {
allowedTags: ["b", "i", "em", "strong", "a", "p", "span", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6", "img", "div", "button", "pre", "code", "br"],
allowedAttributes: {
a: ["href"],
img: ["src", "alt", "width", "height", "class", "style"],
"*": ["style", "class"],
},
};
module.exports = sanitizeHtmlOptions;

View File

@ -0,0 +1,59 @@
// @ts-check
const fs = require("fs");
const serverError = require("./serverError");
const NO_DB_HANDLER = require("../../../package-shared/utils/backend/global-db/NO_DB_HANDLER");
/**
* Create database from Schema Function
* ==============================================================================
* @param {string} queryString - Query String
* @returns {Promise<any>}
*/
module.exports = async function noDatabaseDbHandler(queryString) {
process.env.NODE_ENV?.match(/dev/) &&
fs.appendFileSync(
"./.tmp/sqlQuery.sql",
queryString + "\n" + Date() + "\n\n\n",
"utf8"
);
/**
* Declare variables
*
* @description Declare "results" variable
*/
let results;
/**
* Fetch from db
*
* @description Fetch data from db if no cache
*/
try {
/** ********************* Run Query */
results = await NO_DB_HANDLER(queryString);
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
} catch (/** @type {any} */ error) {
serverError({
component: "noDatabaseDbHandler",
message: error.message,
});
console.log("ERROR in noDatabaseDbHandler =>", error.message);
}
/**
* Return results
*
* @description Return results add to cache if "req" param is passed
*/
if (results) {
return results;
} else {
return null;
}
};

View File

@ -0,0 +1,76 @@
// @ts-check
const decrypt = require("./decrypt");
const defaultFieldsRegexp = require("./defaultFieldsRegexp");
/**
* Parse Database results
* ==============================================================================
* @description this function takes a database results array gotten from a DB handler
* function, decrypts encrypted fields, and returns an updated array with no encrypted
* fields
*
* @param {object} params - Single object params
* @param {any[]} params.unparsedResults - Array of data objects containing Fields(keys)
* and corresponding values of the fields(values)
* @param {import("../../types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @returns {Promise<object[]|null>}
*/
module.exports = async function parseDbResults({
unparsedResults,
tableSchema,
}) {
/**
* Declare variables
*
* @description Declare "results" variable
*/
let parsedResults = [];
try {
/**
* Declare variables
*
* @description Declare "results" variable
*/
for (let pr = 0; pr < unparsedResults.length; pr++) {
let result = unparsedResults[pr];
let resultFieldNames = Object.keys(result);
for (let i = 0; i < resultFieldNames.length; i++) {
const resultFieldName = resultFieldNames[i];
let resultFieldSchema = tableSchema?.fields[i];
if (resultFieldName?.match(defaultFieldsRegexp)) {
continue;
}
let value = result[resultFieldName];
if (typeof value !== "number" && !value) {
// parsedResults.push(result);
continue;
}
if (resultFieldSchema?.encrypted) {
if (value?.match(/./)) {
result[resultFieldName] = decrypt(value);
}
}
}
parsedResults.push(result);
}
/**
* Declare variables
*
* @description Declare "results" variable
*/
return parsedResults;
} catch (/** @type {any} */ error) {
console.log("ERROR in parseDbResults Function =>", error.message);
return unparsedResults;
}
};

View File

@ -0,0 +1,31 @@
// @ts-check
const { createHmac } = require("crypto");
//
/**
* # Password Hash function
* @param {string} password
* @returns
*/
function hashPassword(password) {
const hmac = createHmac(
"sha512",
process.env.DSQL_ENCRYPTION_PASSWORD || ""
);
hmac.update(password);
let hashed = hmac.digest("base64");
return hashed;
}
exports.hashPassword = hashPassword;
// export const comparePasswords = async (password) => {
// const hmac = createHmac("sha512", process.env.DSQL_ENCRYPTION_PASSWORD);
// hmac.update(password);
// let hashed = hmac.digest("base64");
// let dbPass = await global.DB_HANDLER(`SELECT * FROM users WHERE password = '${hashed}'`);
// console.log(dbPass);
// return dbPass;
// };

View File

@ -0,0 +1,55 @@
// @ts-check
/**
* ==============================================================================
* Imports
* ==============================================================================
*/
const fs = require("fs");
// const handleNodemailer = require("./handleNodemailer");
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* ==============================================================================
* Main Function
* ==============================================================================
* @param {{
* user?: { id?: number | string, first_name?: string, last_name?: string, email?: string } & *,
* message: string,
* component?: string,
* noMail?: boolean,
* }} params - user id
*
* @returns {Promise<void>}
*/
module.exports = async function serverError({
user,
message,
component,
noMail,
}) {
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========================================`;
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}`);
};
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////

View File

@ -0,0 +1,38 @@
// @ts-check
const { IncomingMessage } = require("http");
const decrypt = require("./decrypt");
const parseCookies = require("../../../utils/functions/parseCookies");
/**
* @async
* @param {IncomingMessage} req - https request object
*
* @returns {Promise<({ email: string, password: string, authKey: string, logged_in_status: boolean, date: number } | null)>}
*/
module.exports = async function (req) {
const cookies = parseCookies({ request: req });
/** ********************* Check for existence of required cookie */
if (!cookies?.datasquirelSuAdminUserAuthKey) {
return null;
}
/** ********************* Grab the payload */
let userPayload = decrypt(cookies.datasquirelSuAdminUserAuthKey);
/** ********************* Return if no payload */
if (!userPayload) return null;
/** ********************* Parse the payload */
let userObject = JSON.parse(userPayload);
if (userObject.password !== process.env.DSQL_USER_KEY) return null;
if (userObject.authKey !== process.env.DSQL_SPECIAL_KEY) return null;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/** ********************* return user object */
return userObject;
};

View File

@ -0,0 +1,116 @@
// @ts-check
const fs = require("fs");
const parseDbResults = require("./parseDbResults");
const serverError = require("./serverError");
const DB_HANDLER = require("../../utils/backend/global-db/DB_HANDLER");
const DSQL_USER_DB_HANDLER = require("../../utils/backend/global-db/DSQL_USER_DB_HANDLER");
/**
* DB handler for specific database
* ==============================================================================
* @async
* @param {object} params - Single object params
* @param {string} params.queryString - SQL string
* @param {*[]} [params.queryValuesArray] - Values Array
* @param {string} [params.database] - Database name
* @param {import("../../types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @returns {Promise<any>}
*/
module.exports = async function varDatabaseDbHandler({
queryString,
queryValuesArray,
database,
tableSchema,
}) {
/**
* Declare variables
*
* @description Declare "results" variable
*/
const isMaster = database?.match(/^datasquirel$/) ? true : false;
/** @type {any} */
const FINAL_DB_HANDLER = isMaster ? DB_HANDLER : DSQL_USER_DB_HANDLER;
let results;
/**
* Fetch from db
*
* @description Fetch data from db if no cache
*/
try {
if (
queryString &&
queryValuesArray &&
Array.isArray(queryValuesArray) &&
queryValuesArray[0]
) {
results = isMaster
? await FINAL_DB_HANDLER(queryString, queryValuesArray)
: await FINAL_DB_HANDLER({
paradigm: "Full Access",
database,
queryString,
queryValues: queryValuesArray,
});
} else {
results = isMaster
? await FINAL_DB_HANDLER(queryString)
: await FINAL_DB_HANDLER({
paradigm: "Full Access",
database,
queryString,
});
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
} catch (/** @type {any} */ error) {
serverError({
component: "varDatabaseDbHandler/lines-29-32",
message: error.message,
});
}
/**
* Return results
*
* @description Return results add to cache if "req" param is passed
*/
if (results && tableSchema) {
try {
const unparsedResults = results;
const parsedResults = await parseDbResults({
unparsedResults: unparsedResults,
tableSchema: tableSchema,
});
return parsedResults;
} catch (/** @type {any} */ error) {
console.log(
"\x1b[31mvarDatabaseDbHandler ERROR\x1b[0m =>",
database,
error
);
serverError({
component: "varDatabaseDbHandler/lines-52-53",
message: error.message,
});
return null;
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
} else if (results) {
return results;
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
} else {
return null;
}
};

View File

@ -0,0 +1,74 @@
// @ts-check
const fs = require("fs");
const serverError = require("./serverError");
const parseDbResults = require("./parseDbResults");
const DSQL_USER_DB_HANDLER = require("../../utils/backend/global-db/DSQL_USER_DB_HANDLER");
/**
*
* @param {object} param0
* @param {string} param0.queryString
* @param {string} param0.database
* @param {string[]} [param0.queryValuesArray]
* @param {import("../../types").DSQL_TableSchemaType} [param0.tableSchema]
* @returns
*/
module.exports = async function varReadOnlyDatabaseDbHandler({
queryString,
database,
queryValuesArray,
tableSchema,
}) {
/**
* Declare variables
*
* @description Declare "results" variable
*/
let results;
/**
* Fetch from db
*
* @description Fetch data from db if no cache
*/
try {
results = await DSQL_USER_DB_HANDLER({
paradigm: "Read Only",
database,
queryString,
queryValues: queryValuesArray,
});
////////////////////////////////////////
} catch (/** @type {any} */ error) {
////////////////////////////////////////
serverError({
component: "varReadOnlyDatabaseDbHandler",
message: error.message,
noMail: true,
});
/**
* Return error
*/
return error.message;
}
/**
* Return results
*
* @description Return results add to cache if "req" param is passed
*/
if (results) {
const unparsedResults = results;
const parsedResults = await parseDbResults({
unparsedResults: unparsedResults,
tableSchema: tableSchema,
});
return parsedResults;
} else {
return null;
}
};

View File

@ -1,5 +1,6 @@
import http from "http";
import { Editor } from "tinymce";
export type DSQL_DatabaseFullName = string;
////////////////////////////////////////////////////////////////////////////////
@ -139,6 +140,7 @@ export interface DSQL_MYSQL_FOREIGN_KEYS_Type {
////////////////////////////////////////
export interface DSQL_MYSQL_user_databases_Type {
id: number;
user_id: number;
db_full_name: string;
db_name: string;
@ -147,6 +149,17 @@ export interface DSQL_MYSQL_user_databases_Type {
db_description: string;
active_clone: number;
active_clone_parent_db: string;
remote_connected?: number;
remote_db_full_name?: string;
remote_connection_host?: string;
remote_connection_key?: string;
remote_connection_type?: string;
user_priviledge?: string;
date_created?: string;
image_thumbnail?: string;
first_name?: string;
last_name?: string;
email?: string;
}
export interface PackageUserLoginRequestBody {
@ -370,3 +383,716 @@ export interface PostInsertReturn {
protocol41: boolean;
changedRows: number;
}
export interface UserType {
id: number;
stripe_id?: string;
first_name: string;
last_name: string;
email: string;
bio?: string;
username?: string;
image: string;
image_thumbnail: string;
social_id?: string;
verification_status?: number;
social_platform?: string;
social_login?: number;
date?: number;
phone?: number | string;
csrf_k: string;
logged_in_status: boolean;
}
export interface ApiKeyDef {
name: string;
scope: string;
date_created: string;
apiKeyPayload: string;
}
export interface MetricsType {
dbCount: number;
tablesCount: number;
mediaCount: number;
apiKeysCount: number;
}
export interface DashboardContextType {
user?: UserType;
databases?: DSQL_MYSQL_user_databases_Type[];
setTargetDatabase?: React.Dispatch<
React.SetStateAction<DSQL_MYSQL_user_databases_Type>
>;
targetDatabase?: DSQL_MYSQL_user_databases_Type;
metrics?: MetricsType;
}
export interface AddDbContextType {
user?: UserType;
databases?: DSQL_MYSQL_user_databases_Type[];
dbImage?: string | null | ImageObjectType;
setDbImage?: React.Dispatch<
React.SetStateAction<string | null | ImageObjectType>
>;
query?: any;
duplicateDb?: DSQL_MYSQL_user_databases_Type;
}
export interface EditDbContextType {
user?: UserType;
database?: DSQL_MYSQL_user_databases_Type;
dbImage?: string | null | ImageObjectType;
setDbImage?: React.Dispatch<
React.SetStateAction<string | null | ImageObjectType>
>;
}
export interface RichTextEditorsRefArray {
fieldName: string;
ref: React.MutableRefObject<Editor>;
}
export interface JSONTextEditorsRefArray {
fieldName: string;
ref: React.MutableRefObject<AceAjax.Editor>;
}
export interface TableEntriesContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
dbSchemaData: DSQL_DatabaseSchemaType[];
entries: any[];
targetEntry?: any;
setTargetEntry: React.Dispatch<React.SetStateAction<any>>;
richTextEditors: React.MutableRefObject<RichTextEditorsRefArray[]>;
jsonTextEditors: React.MutableRefObject<JSONTextEditorsRefArray[]>;
query?: any;
confirmedDelegetedUser?: any;
activeEntries: any[] | null;
setActiveEntries: React.Dispatch<React.SetStateAction<any[] | null>>;
targetField: React.MutableRefObject<string>;
searchTerm: React.MutableRefObject<string | null>;
entriesCount: number;
}
export interface AddEntryContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
dbSchemaData: DSQL_DatabaseSchemaType[];
richTextEditors: React.MutableRefObject<RichTextEditorsRefArray[]>;
jsonTextEditors: React.MutableRefObject<JSONTextEditorsRefArray[]>;
query: any;
duplicateEntry?: any;
confirmedDelegetedUser: any;
}
export interface UserDatabasesContextType {
user: UserType;
users: any[];
targetUser: any;
setTargetUser: React.Dispatch<React.SetStateAction<any>>;
databases: DSQL_MYSQL_user_databases_Type[];
}
export interface SettingsPageContextType {
user: UserType;
image: any;
setImage: React.Dispatch<React.SetStateAction<any>>;
activeUser: any;
}
export interface MediaFolderPageContextType {
user: UserType;
media: any[];
targetMedia: any;
setTargetMedia: React.Dispatch<React.SetStateAction<any>>;
folders: any[];
query: any;
staticHost: string;
folder: string;
}
export interface TablesContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
tables: MYSQL_user_database_tables_table_def[];
targetTable: MYSQL_user_database_tables_table_def | null;
setTargetTable: React.Dispatch<
React.SetStateAction<MYSQL_user_database_tables_table_def | null>
>;
query: any;
confirmedDelegetedUser: any;
}
export interface EditTableContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
tableFields: DSQL_FieldSchemaType[];
setTableFields: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType[]>
>;
targetField: DSQL_FieldSchemaType | null;
setTargetField: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType | null>
>;
pageRefresh: number;
setPageRefresh: React.Dispatch<React.SetStateAction<number>>;
refreshFieldsListRef: React.MutableRefObject<
React.Dispatch<React.SetStateAction<number>> | undefined
>;
dbSchemaData: DSQL_DatabaseSchemaType[];
query: any;
confirmedDelegetedUser: any;
}
export interface SingleDatabaseContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
tables: MYSQL_user_database_tables_table_def[];
targetTable: MYSQL_user_database_tables_table_def | null;
setTargetTable: React.Dispatch<
React.SetStateAction<MYSQL_user_database_tables_table_def | null>
>;
query: any;
confirmedDelegetedUser: any;
}
export interface ApiKeysContextType {
user: UserType;
apiKeys: any[];
setApiKeys: React.Dispatch<React.SetStateAction<any[]>>;
targetApiKey: any | null;
setTargetApiKey: React.Dispatch<React.SetStateAction<any | null>>;
newApiKey: any | null;
setNewApiKey: React.Dispatch<React.SetStateAction<any | null>>;
}
export interface LoginFormContextType {
user?: UserType | null;
loading: boolean;
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
alert: string | boolean;
setAlert: React.Dispatch<React.SetStateAction<string | boolean>>;
}
export interface CreateAccountContextType {
user?: UserType | null;
query: CreateAccountQueryType;
invitingUser: any;
}
export interface CreateAccountQueryType {
invite?: number;
database_access?: string;
priviledge?: string;
email?: string;
}
export interface DocsAsidePageObject {
id: number;
title: string;
slug: string;
parent_id?: number;
level?: number;
}
export interface AllUserUsersContextType {
user: UserType;
users: MYSQL_delegated_users_table_def[];
targetUser: MYSQL_user_users_table_def | null;
setTargetUser: React.Dispatch<
React.SetStateAction<MYSQL_user_users_table_def | null>
>;
databases: DSQL_MYSQL_user_databases_Type[];
pendingInvitations: MYSQL_invitations_table_def[];
pendingInvitationsReceived: any[];
adminUsers: any[];
invitedAccounts: any[];
}
export interface AddSocialLoginContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
query: any;
socialLogins: SocialLoginObjectType[];
}
export interface DelegatedDbContextType {
user: UserType;
users: MYSQL_user_users_table_def[];
targetUser: MYSQL_user_users_table_def | null;
setTargetUser: React.Dispatch<
React.SetStateAction<MYSQL_user_users_table_def | null>
>;
database: DSQL_MYSQL_user_databases_Type;
}
export interface AddUserUserContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
query: any;
confirmedDelegetedUser: any;
}
export interface UserUsersContextType {
user: UserType;
users: MYSQL_user_users_table_def[];
targetUser: MYSQL_user_users_table_def;
setTargetUser: React.Dispatch<
React.SetStateAction<MYSQL_user_users_table_def | null>
>;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
dbSchemaData: DSQL_DatabaseSchemaType[];
query: any;
confirmedDelegetedUser: any;
}
export interface DatabaseSingleUserContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
singleUser: MYSQL_user_users_table_def;
table: DSQL_TableSchemaType;
dbSchemaData: DSQL_DatabaseSchemaType[];
query: any;
confirmedDelegetedUser: any;
}
export interface SingleUserUserContextType {
user: UserType;
singleUser: MYSQL_user_users_table_def;
}
export interface AddUserContextType {
user: UserType;
users: MYSQL_delegated_users_table_def[];
databases: DSQL_MYSQL_user_databases_Type[];
query: any;
}
export interface MediaContextType {
user: UserType;
media: MYSQL_user_media_table_def[];
targetMedia: MYSQL_user_media_table_def | null;
setTargetMedia: React.Dispatch<
React.SetStateAction<MYSQL_user_media_table_def | null>
>;
folders: string[];
staticHost: string;
}
export interface MediaSubFolderContextType {
user: UserType;
media: MYSQL_user_media_table_def[];
targetMedia: MYSQL_user_media_table_def | null;
setTargetMedia: React.Dispatch<
React.SetStateAction<MYSQL_user_media_table_def | null>
>;
folders: string[];
query: any;
folder: string;
staticHost: string;
}
export interface FieldsContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
dbSchemaData: DSQL_DatabaseSchemaType[];
targetField: DSQL_FieldSchemaType | null;
setTargetField: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType | null>
>;
refreshFieldsListRef: React.MutableRefObject<
React.Dispatch<React.SetStateAction<number>> | undefined
>;
tableFields: DSQL_FieldSchemaType[];
setTableFields: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType[]>
>;
updateTableAfterFieldsUpdateFunction: () => void;
query: any;
confirmedDelegetedUser: any;
}
export interface SingleTableContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
tableRecord: MYSQL_user_database_tables_table_def;
tableFields: DSQL_FieldSchemaType[];
setTableFields: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType[]>
>;
tableIndexes: DSQL_IndexSchemaType[];
setTableIndexes: React.Dispatch<
React.SetStateAction<DSQL_IndexSchemaType[]>
>;
dbSchemaData: DSQL_DatabaseSchemaType[];
entries: any[];
targetEntry: any;
setTargetEntry: React.Dispatch<React.SetStateAction<any>>;
richTextEditors: React.MutableRefObject<RichTextEditorsRefArray[]>;
jsonTextEditors: React.MutableRefObject<JSONTextEditorsRefArray[]>;
query: any;
confirmedDelegetedUser: any;
targetField: DSQL_FieldSchemaType | null;
setTargetField: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType | null>
>;
refreshFieldsListRef: React.MutableRefObject<
React.Dispatch<React.SetStateAction<number>>
>;
updateTableAfterFieldsUpdateFunction: () => void;
entriesCount: number;
}
export interface SingleEntryContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
table: DSQL_TableSchemaType;
dbSchemaData: DSQL_DatabaseSchemaType[];
entry: any;
targetEntry: any;
setTargetEntry: React.Dispatch<React.SetStateAction<any>>;
richTextEditors: React.MutableRefObject<RichTextEditorsRefArray[]>;
jsonTextEditors: React.MutableRefObject<JSONTextEditorsRefArray[]>;
query: any;
confirmedDelegetedUser: any;
prevEntry: any;
nextEntry: any;
}
export interface UserSchemaContextType {
user: UserType;
dbSchemaData: DSQL_DatabaseSchemaType[];
}
export interface ConnectContextType {
user: UserType;
query: any;
mariadbUserCred: MariaDBUserCredType;
mariadbUsers: MYSQL_mariadb_users_table_def[];
targetMariadbUser: MYSQL_mariadb_users_table_def | null;
setTargetMariadbUser: React.Dispatch<
React.SetStateAction<MYSQL_mariadb_users_table_def | null>
>;
refresh: number;
setRefresh: React.Dispatch<React.SetStateAction<number>>;
}
export interface MYSQL_mariadb_users_table_def {
id?: number;
user_id?: number;
username?: string;
host?: string;
password?: string;
primary?: number;
grants?: string;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
}
export interface DbContextType {
user?: UserType;
databases?: DSQL_MYSQL_user_databases_Type[];
targetDatabase?: DSQL_MYSQL_user_databases_Type;
setTargetDatabase?: React.Dispatch<
React.SetStateAction<DSQL_MYSQL_user_databases_Type>
>;
}
export interface MariaDBUserCredType {
mariadb_user?: string;
mariadb_host?: string;
mariadb_pass?: string;
}
export interface AddTableContextType {
user: UserType;
dbSchemaData: DSQL_DatabaseSchemaType[];
database: DSQL_MYSQL_user_databases_Type;
tables: DSQL_TableSchemaType[];
tableFields: DSQL_FieldSchemaType[];
setTableFields: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType[]>
>;
targetField: DSQL_FieldSchemaType | null;
setTargetField: React.Dispatch<
React.SetStateAction<DSQL_FieldSchemaType | null>
>;
pageRefresh: number | null;
setPageRefresh: React.Dispatch<React.SetStateAction<number>>;
refreshFieldsListRef: React.MutableRefObject<
React.Dispatch<React.SetStateAction<number>>
>;
query: any;
}
export interface DbSchemaContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
dbImage: string;
setDbImage: React.Dispatch<React.SetStateAction<string>>;
dbSchemaData: DSQL_DatabaseSchemaType[];
tables: any[];
}
export interface DbShellContextType {
user?: UserType;
database?: DSQL_MYSQL_user_databases_Type;
dbImage?: string;
setDbImage?: React.Dispatch<React.SetStateAction<string>>;
dbSchemaData?: DSQL_DatabaseSchemaType[];
tables?: any[];
}
export interface DbConnectContextType {
user: UserType;
database: DSQL_MYSQL_user_databases_Type;
targetDbSchema: DSQL_DatabaseSchemaType;
query: any;
}
export interface ImageObjectType {
imageName?: string;
mimeType?: string;
imageSize?: number;
private?: boolean;
imageBase64?: string;
imageBase64Full?: string;
}
export interface FileObjectType {
fileName?: string;
private?: boolean;
fileType?: string;
fileSize?: number;
fileBase64?: string;
fileBase64Full?: string;
}
export interface SocialLoginObjectType {
platform?: string;
paradigm?: string;
clientId?: string;
clientSecret?: string;
callbackUrl?: string;
domain1?: string;
domain2?: string;
domain3?: string;
}
export interface DbConnectType {
url: string;
key: string;
database: DSQL_MYSQL_user_databases_Type;
dbSchema: DSQL_DatabaseSchemaType;
type: "pull" | "push";
remoteDbs?: DSQL_DatabaseSchemaType[];
targetDb?: DSQL_DatabaseSchemaType;
}
export interface MYSQL_MediaType {
id?: number;
user_id?: number;
media_name?: string;
folder?: string;
media_url?: string;
media_thumbnail_url?: string;
media_type?: string;
width?: string;
height?: string;
size?: string;
private?: string;
}
export interface UserFileObject {
title?: string;
path?: string;
data?: string;
}
export interface UserFileObject2 {
type?: string;
name?: string;
root?: string;
content?: UserFileObject2[];
}
export interface MYSQL_user_users_table_def {
id?: number;
user_id?: number;
invited_user_id?: number;
database?: string;
database_access?: string;
first_name?: string;
last_name?: string;
email?: string;
username?: string;
password?: string;
phone?: string;
user_type?: string;
user_priviledge?: string;
image?: string;
image_thumbnail?: string;
city?: string;
state?: string;
country?: string;
zip_code?: string;
address?: string;
social_login?: number;
social_platform?: string;
social_id?: string;
verification_status?: number;
more_user_data?: string;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
inviteeFirstName?: string;
inviteeLastName?: string;
inviteeEmail?: string;
inviteeImage?: string;
}
export interface MYSQL_user_database_tables_table_def {
id?: number;
user_id?: number;
db_id?: number;
db_slug?: string;
table_name?: string;
table_slug?: string;
table_description?: string;
child_table?: number;
child_table_parent_database?: string;
child_table_parent_table?: string;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
}
export interface MYSQL_user_media_table_def {
id?: number;
user_id?: number;
media_name?: string;
folder?: string;
media_url?: string;
media_thumbnail_url?: string;
media_path?: string;
media_thumbnail_path?: string;
media_type?: string;
width?: number;
height?: number;
size?: number;
private?: number;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
}
export interface MYSQL_delegated_users_table_def {
id?: number;
user_id?: number;
delegated_user_id?: number;
permissions?: string;
permission_level_code?: number;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
}
export interface MYSQL_invitations_table_def {
id?: number;
inviting_user_id?: number;
invited_user_email?: string;
invitation_status?: string;
database_access?: string;
priviledge?: string;
db_tables_data?: string;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
}
export interface MYSQL_docs_pages_table_def {
id?: number;
title?: string;
slug?: string;
description?: string;
content?: string;
text_content?: string;
level?: number;
page_order?: number;
parent_id?: number;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
}
export interface MYSQL_delegated_user_tables_table_def {
id?: number;
delegated_user_id?: number;
root_user_id?: number;
database?: string;
table?: string;
priviledge?: string;
date_created?: string;
date_created_code?: number;
date_created_timestamp?: string;
date_updated?: string;
date_updated_code?: number;
date_updated_timestamp?: string;
}
export type ApiKeyObject = {
user_id: string | number;
full_access?: boolean;
sign: string;
date_code: number;
target_database?: string;
target_table?: string;
};
export type AddApiKeyRequestBody = {
api_key_name: string;
api_key_slug: string;
api_key_scope?: "fullAccess" | "readOnly";
target_database?: string;
target_table?: string;
};
export type CheckApiCredentialsFn = (
param: CheckApiCredentialsFnParam
) => ApiKeyObject | null | undefined;
export type CheckApiCredentialsFnParam = {
key: string;
database?: string;
table?: string;
};

View File

@ -153,6 +153,7 @@
/**
* @typedef {object} DSQL_MYSQL_user_databases_Type
* @property {number} id
* @property {number} user_id - User Id
* @property {string} db_full_name - Database full name => eg. (dataasquirel_user_2_new_database)
* @property {string} db_name - Database name with spaces => eg. (New Database)
@ -161,6 +162,15 @@
* @property {string} db_description - Database description
* @property {number} active_clone - is Database active clone => 0 or 1
* @property {string} active_clone_parent_db - Database parent db full name => eg. "datasquirel_user_7_wexculture"
* @property {number} [remote_connected]
* @property {string} [remote_db_full_name]
* @property {string} [remote_connection_host]
* @property {string} [user_priviledge]
* @property {string} [date_created]
* @property {string} [image_thumbnail]
* @property {string} [first_name]
* @property {string} [last_name]
* @property {string} [email]
*/
/**
@ -426,3 +436,731 @@ const http = require("http");
* @property {boolean} protocol41
* @property {number} changedRows
*/
// @ts-check
const { Editor } = require("tinymce");
/**
* @typedef {object} UserType
* @property {number} id - user id (number)
* @property {string} [stripe_id] - Stripe ID for payments
* @property {string} first_name - User First Name
* @property {string} last_name - User Last Name
* @property {string} email - User Email Address
* @property {string} [bio] - User Description HTML
* @property {string} [username] - User Username
* @property {string} image - User Full Image
* @property {string} image_thumbnail - User Image Thumbnail
* @property {string} [social_id] - User Social id if available
* @property {number} [verification_status] - 0 or 1 or 2
* @property {string} [social_platform] - Google or Facebook or Github
* @property {number} [social_login] - 0 or 1 => is this user a social user(1) or not(0)
* @property {number} [date] - Creation Date
* @property {number | string} [phone]
* @property {string} csrf_k - CSRF key
* @property {boolean} logged_in_status - Is user logged in or not
*/
/**
* @typedef {object} ApiKeyDef
* @property {string} name
* @property {string} scope
* @property {string} date_created
* @property {string} apiKeyPayload
*/
/**
* @typedef {object} MetricsType
* @property {number} dbCount
* @property {number} tablesCount
* @property {number} mediaCount
* @property {number} apiKeysCount
*/
/**
* @typedef {object} DashboardContextType
* @property {UserType} [user]
* @property {DSQL_MYSQL_user_databases_Type[]} [databases]
* @property {React.Dispatch<React.SetStateAction<DSQL_MYSQL_user_databases_Type>>} [setTargetDatabase]
* @property {DSQL_MYSQL_user_databases_Type} [targetDatabase]
* @property {MetricsType} [metrics]
*/
/**
* @typedef {object} AddDbContextType
* @property {UserType} [user]
* @property {DSQL_MYSQL_user_databases_Type[]} [databases]
* @property {string | null | ImageObjectType} [dbImage]
* @property {React.Dispatch<React.SetStateAction<string | null | ImageObjectType>>} [setDbImage]
* @property {*} [query]
* @property {DSQL_MYSQL_user_databases_Type} [duplicateDb]
*/
/**
* @typedef {object} EditDbContextType
* @property {UserType} [user]
* @property {DSQL_MYSQL_user_databases_Type} [database]
* @property {string | null | ImageObjectType} [dbImage]
* @property {React.Dispatch<React.SetStateAction<string | null | ImageObjectType>>} [setDbImage]
*/
/**
* @typedef {object} RichTextEditorsRefArray
* @property {string} fieldName
* @property {React.MutableRefObject<Editor>} ref
*/
/**
* @typedef {object} JSONTextEditorsRefArray
* @property {string} fieldName
* @property {React.MutableRefObject<AceAjax.Editor>} ref
*/
/**
* @typedef {object} TableEntriesContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {any[]} entries
* @property {any} [targetEntry]
* @property {React.Dispatch<React.SetStateAction<any>>} setTargetEntry
* @property {React.MutableRefObject<RichTextEditorsRefArray[]>} richTextEditors
* @property {React.MutableRefObject<JSONTextEditorsRefArray[]>} jsonTextEditors
* @property {any} [query]
* @property {any} [confirmedDelegetedUser]
* @property {any[] | null} activeEntries
* @property {React.Dispatch<React.SetStateAction<any[] | null>>} setActiveEntries
* @property {React.MutableRefObject<string>} targetField
* @property {React.MutableRefObject<string|null>} searchTerm
* @property {number} entriesCount
*/
/**
* @typedef {object} AddEntryContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {React.MutableRefObject<RichTextEditorsRefArray[]>} richTextEditors
* @property {React.MutableRefObject<JSONTextEditorsRefArray[]>} jsonTextEditors
* @property {any} query
* @property {any} [duplicateEntry]
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} UserDatabasesContextType
* @property {UserType} user
* @property {any[]} users
* @property {any} targetUser
* @property {React.Dispatch<React.SetStateAction<any>>} setTargetUser
* @property {DSQL_MYSQL_user_databases_Type[]} databases
*/
/**
* @typedef {object} SettingsPageContextType
* @property {UserType} user
* @property {any} image
* @property {React.Dispatch<React.SetStateAction<any>>} setImage
* @property {any} activeUser
*/
/**
* @typedef {object} MediaFolderPageContextType
* @property {UserType} user
* @property {any[]} media
* @property {any} targetMedia
* @property {React.Dispatch<React.SetStateAction<any>>} setTargetMedia
* @property {any[]} folders
* @property {any} query
* @property {string} staticHost
* @property {string} folder
*/
/**
* @typedef {object} TablesContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {MYSQL_user_database_tables_table_def[]} tables
* @property {MYSQL_user_database_tables_table_def | null} targetTable
* @property {React.Dispatch<React.SetStateAction<MYSQL_user_database_tables_table_def | null>>} setTargetTable
* @property {any} query
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} EditTableContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {DSQL_FieldSchemaType[]} tableFields
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType[]>>} setTableFields
* @property {DSQL_FieldSchemaType | null} targetField
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType | null>>} setTargetField
* @property {number} pageRefresh
* @property {React.Dispatch<React.SetStateAction<number>>} setPageRefresh
* @property {React.MutableRefObject<React.Dispatch<React.SetStateAction<number>> | undefined>} refreshFieldsListRef
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {any} query
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} SingleDatabaseContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {MYSQL_user_database_tables_table_def[]} tables
* @property {MYSQL_user_database_tables_table_def | null} targetTable
* @property {React.Dispatch<React.SetStateAction<MYSQL_user_database_tables_table_def | null>>} setTargetTable
* @property {any} query
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} ApiKeysContextType
* @property {UserType} user
* @property {any[]} apiKeys
* @property {React.Dispatch<React.SetStateAction<any[]>>} setApiKeys
* @property {any | null} targetApiKey
* @property {React.Dispatch<React.SetStateAction<any | null>>} setTargetApiKey
* @property {any | null} newApiKey
* @property {React.Dispatch<React.SetStateAction<any | null>>} setNewApiKey
*/
/**
* @typedef {object} LoginFormContextType
* @property {UserType | null} [user]
* @property {boolean} loading
* @property {React.Dispatch<React.SetStateAction<boolean>>} setLoading
* @property {string | boolean} alert
* @property {React.Dispatch<React.SetStateAction<string | boolean>>} setAlert
*/
/**
* @typedef {object} CreateAccountContextType
* @property {UserType | null} [user]
* @property {CreateAccountQueryType} query
* @property {any} invitingUser
*/
/**
* @typedef {object} CreateAccountQueryType
* @property {number} [invite]
* @property {string} [database_access]
* @property {string} [priviledge]
* @property {string} [email]
*/
/**
* @typedef {object} DocsAsidePageObject
* @property {number} id
* @property {string} title
* @property {string} slug
* @property {number} [parent_id]
* @property {number} [level]
*/
/**
* @typedef {object} AllUserUsersContextType
* @property {UserType} user
* @property {MYSQL_delegated_users_table_def[]} users
* @property {MYSQL_user_users_table_def | null} targetUser
* @property {React.Dispatch<React.SetStateAction<MYSQL_user_users_table_def | null>>} setTargetUser
* @property {DSQL_MYSQL_user_databases_Type[]} databases
* @property {MYSQL_invitations_table_def[]} pendingInvitations
* @property {any[]} pendingInvitationsReceived
* @property {any[]} adminUsers
* @property {any[]} invitedAccounts
*/
/**
* @typedef {object} AddSocialLoginContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {any} query
* @property {SocialLoginObjectType[]} socialLogins
*/
/**
* @typedef {object} DelegatedDbContextType
* @property {UserType} user
* @property {MYSQL_user_users_table_def[]} users
* @property {MYSQL_user_users_table_def | null} targetUser
* @property {React.Dispatch<React.SetStateAction<MYSQL_user_users_table_def | null>>} setTargetUser
* @property {DSQL_MYSQL_user_databases_Type} database
*/
/**
* @typedef {object} AddUserUserContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {any} query
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} UserUsersContextType
* @property {UserType} user
* @property {MYSQL_user_users_table_def[]} users
* @property {MYSQL_user_users_table_def} targetUser
* @property {React.Dispatch<React.SetStateAction<MYSQL_user_users_table_def | null>>} setTargetUser
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {any} query
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} DatabaseSingleUserContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {MYSQL_user_users_table_def} singleUser
* @property {DSQL_TableSchemaType} table
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {any} query
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} SingleUserUserContextType
* @property {UserType} user
* @property {MYSQL_user_users_table_def} singleUser
*/
/**
* @typedef {object} AddUserContextType
* @property {UserType} user
* @property {MYSQL_delegated_users_table_def[]} users
* @property {DSQL_MYSQL_user_databases_Type[]} databases
* @property {any} query
*/
/**
* @typedef {object} MediaContextType
* @property {UserType} user
* @property {MYSQL_user_media_table_def[]} media
* @property {MYSQL_user_media_table_def | null} targetMedia
* @property {React.Dispatch<React.SetStateAction<MYSQL_user_media_table_def | null>>} setTargetMedia
* @property {string[]} folders
* @property {string} staticHost
*/
/**
* @typedef {object} MediaSubFolderContextType
* @property {UserType} user
* @property {MYSQL_user_media_table_def[]} media
* @property {MYSQL_user_media_table_def | null} targetMedia
* @property {React.Dispatch<React.SetStateAction<MYSQL_user_media_table_def | null>>} setTargetMedia
* @property {string[]} folders
* @property {any} query
* @property {string} folder
* @property {string} staticHost
*/
/**
* @typedef {object} FieldsContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {DSQL_FieldSchemaType | null} targetField
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType | null>>} setTargetField
* @property {React.MutableRefObject<React.Dispatch<React.SetStateAction<number>> | undefined>} refreshFieldsListRef
* @property {DSQL_FieldSchemaType[]} tableFields
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType[]>>} setTableFields
* @property {()=>void} updateTableAfterFieldsUpdateFunction
* @property {any} query
* @property {any} confirmedDelegetedUser
*/
/**
* @typedef {object} SingleTableContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {MYSQL_user_database_tables_table_def} tableRecord
* @property {DSQL_FieldSchemaType[]} tableFields
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType[]>>} setTableFields
* @property {DSQL_IndexSchemaType[]} tableIndexes
* @property {React.Dispatch<React.SetStateAction<DSQL_IndexSchemaType[]>>} setTableIndexes
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {any[]} entries
* @property {any} targetEntry
* @property {React.Dispatch<React.SetStateAction<any>>} setTargetEntry
* @property {React.MutableRefObject<RichTextEditorsRefArray[]>} richTextEditors
* @property {React.MutableRefObject<JSONTextEditorsRefArray[]>} jsonTextEditors
* @property {any} query
* @property {any} confirmedDelegetedUser
* @property {DSQL_FieldSchemaType | null} targetField
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType | null>>} setTargetField
* @property {React.MutableRefObject<React.Dispatch<React.SetStateAction<number>>>} refreshFieldsListRef
* @property {()=>void} updateTableAfterFieldsUpdateFunction
* @property {number} entriesCount
*/
/**
* @typedef {object} SingleEntryContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType} table
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {any} entry
* @property {any} targetEntry
* @property {React.Dispatch<React.SetStateAction<any>>} setTargetEntry
* @property {React.MutableRefObject<RichTextEditorsRefArray[]>} richTextEditors
* @property {React.MutableRefObject<JSONTextEditorsRefArray[]>} jsonTextEditors
* @property {any} query
* @property {any} confirmedDelegetedUser
* @property {any} prevEntry
* @property {any} nextEntry
*/
/**
* @typedef {object} UserSchemaContextType
* @property {UserType} user
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
*/
/**
* @typedef {object} ConnectContextType
* @property {UserType} user
* @property {any} query
* @property {MariaDBUserCredType} mariadbUserCred
* @property {MYSQL_mariadb_users_table_def[]} mariadbUsers - All MariaDB Users including the primary User
* @property {MYSQL_mariadb_users_table_def | null} targetMariadbUser
* @property {React.Dispatch<React.SetStateAction<MYSQL_mariadb_users_table_def | null>>} setTargetMariadbUser
* @property {number} refresh
* @property {React.Dispatch<React.SetStateAction<number>>} setRefresh
*/
/**
* @typedef {object} MYSQL_mariadb_users_table_def
* @property {number} [id] - NULL=`NO` Key=`PRI` Default=`null` Extra=`auto_increment`
* @property {number} [user_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {string} [username] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [host] - NULL=`YES` Key=`` Default=`%` Extra=``
* @property {string} [password] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [primary] - NULL=`YES` Key=`` Default=`0` Extra=``
* @property {string} [grants] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_created] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [date_created_code] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_created_timestamp] - NULL=`YES` Key=`` Default=`current_timestamp()` Extra=``
* @property {string} [date_updated] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [date_updated_code] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_updated_timestamp] - NULL=`YES` Key=`` Default=`current_timestamp()` Extra=`on update current_timestamp()`
*/
/**
* @typedef {object} DbContextType
* @property {UserType} [user]
* @property {DSQL_MYSQL_user_databases_Type[]} [databases]
* @property {DSQL_MYSQL_user_databases_Type} [targetDatabase]
* @property {React.Dispatch<React.SetStateAction<DSQL_MYSQL_user_databases_Type>>} [setTargetDatabase]
*/
/**
* @typedef {object} MariaDBUserCredType
* @property {string} [mariadb_user]
* @property {string} [mariadb_host]
* @property {string} [mariadb_pass]
*/
/**
* @typedef {object} AddTableContextType
* @property {UserType} user
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_TableSchemaType[]} tables
* @property {DSQL_FieldSchemaType[]} tableFields
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType[]>>} setTableFields
* @property {DSQL_FieldSchemaType | null} targetField
* @property {React.Dispatch<React.SetStateAction<DSQL_FieldSchemaType | null>>} setTargetField
* @property {number | null} pageRefresh
* @property {React.Dispatch<React.SetStateAction<number>>} setPageRefresh
* @property {React.MutableRefObject<React.Dispatch<React.SetStateAction<number>>>} refreshFieldsListRef
* @property {any} query
*/
/**
* @typedef {object} DbSchemaContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {string} dbImage
* @property {React.Dispatch<React.SetStateAction<string>>} setDbImage
* @property {DSQL_DatabaseSchemaType[]} dbSchemaData
* @property {any[]} tables
*/
/**
* @typedef {object} DbShellContextType
* @property {UserType} [user]
* @property {DSQL_MYSQL_user_databases_Type} [database]
* @property {string} [dbImage]
* @property {React.Dispatch<React.SetStateAction<string>>} [setDbImage]
* @property {DSQL_DatabaseSchemaType[]} [dbSchemaData]
* @property {any[]} [tables]
*/
/**
* @typedef {object} DbConnectContextType
* @property {UserType} user
* @property {DSQL_MYSQL_user_databases_Type} database
* @property {DSQL_DatabaseSchemaType} targetDbSchema
* @property {any} query
*/
/**
* @typedef {object} ImageObjectType
* @property {string} [imageName]
* @property {string} [mimeType]
* @property {number} [imageSize]
* @property {boolean} [private]
* @property {string} [imageBase64]
* @property {string} [imageBase64Full]
*/
/**
* @typedef {object} FileObjectType
* @property {string} [fileName]
* @property {boolean} [private]
* @property {string} [fileType]
* @property {number} [fileSize]
* @property {string} [fileBase64]
* @property {string} [fileBase64Full]
*/
/**
* @typedef {object} SocialLoginObjectType
* @property {string} [platform]
* @property {string} [paradigm]
* @property {string} [clientId]
* @property {string} [clientSecret]
* @property {string} [callbackUrl]
* @property {string} [domain1]
* @property {string} [domain2]
* @property {string} [domain3]
*/
/**
* @typedef {object} DbConnectType
* @property {string} url - Remote URL
* @property {string} key - Full Access API key
* @property {DSQL_MYSQL_user_databases_Type} database - DSQL database entry
* @property {DSQL_DatabaseSchemaType} dbSchema - Database JSON schema
* @property {"pull" | "push"} type - Type of connection: "pull" or "push"
* @property {DSQL_DatabaseSchemaType[]} [remoteDbs] - All Databases Pulled from the remote
* @property {DSQL_DatabaseSchemaType} [targetDb] - The Target Database to be cloned
*/
/**
* @typedef {object} MYSQL_MediaType
* @property {number} [id]
* @property {number} [user_id]
* @property {string} [media_name]
* @property {string} [folder]
* @property {string} [media_url]
* @property {string} [media_thumbnail_url]
* @property {string} [media_type]
* @property {string} [width]
* @property {string} [height]
* @property {string} [size]
* @property {string} [private]
*/
/**
* @typedef {object} UserFileObject
* @property {string} [title]
* @property {string} [path]
* @property {string} [data]
*/
/**
* @typedef {object} UserFileObject2
* @property {string} [type]
* @property {string} [name]
* @property {string} [root]
* @property {UserFileObject2[]} [content]
*/
/**
* @typedef {object} MYSQL_user_users_table_def
* @property {number} [id] - NULL=`NO` Key=`PRI` Default=`null` Extra=`auto_increment`
* @property {number} [user_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {number} [invited_user_id] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [database] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [database_access] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [first_name] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [last_name] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [email] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [username] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [password] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [phone] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [user_type] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [user_priviledge] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [image] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [image_thumbnail] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [city] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [state] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [country] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [zip_code] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [address] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [social_login] - NULL=`YES` Key=`` Default=`0` Extra=``
* @property {string} [social_platform] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [social_id] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [verification_status] - NULL=`YES` Key=`` Default=`0` Extra=``
* @property {string} [more_user_data] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_created] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_created_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_created_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED`
* @property {string} [date_updated] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_updated_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_updated_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED on update CURRENT_TIMESTAMP`
* @property {string} [inviteeFirstName] - QUERY JOIN
* @property {string} [inviteeLastName] - QUERY JOIN
* @property {string} [inviteeEmail] - QUERY JOIN
* @property {string} [inviteeImage] - QUERY JOIN
*/
/**
* @typedef {object} MYSQL_user_database_tables_table_def
* @property {number} [id] - NULL=`NO` Key=`PRI` Default=`null` Extra=`auto_increment`
* @property {number} [user_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {number} [db_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {string} [db_slug] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [table_name] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [table_slug] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [table_description] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [child_table] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [child_table_parent_database] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [child_table_parent_table] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_created] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_created_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_created_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED`
* @property {string} [date_updated] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_updated_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_updated_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED on update CURRENT_TIMESTAMP`
*/
/**
* @typedef {object} MYSQL_user_media_table_def
* @property {number} [id] - NULL=`NO` Key=`PRI` Default=`null` Extra=`auto_increment`
* @property {number} [user_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {string} [media_name] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [folder] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [media_url] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [media_thumbnail_url] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [media_path] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [media_thumbnail_path] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [media_type] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [width] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [height] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [size] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [private] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_created] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_created_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_created_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED`
* @property {string} [date_updated] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_updated_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_updated_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED on update CURRENT_TIMESTAMP`
*/
/**
* @typedef {object} MYSQL_delegated_users_table_def
* @property {number} [id] - NULL=`NO` Key=`PRI` Default=`null` Extra=`auto_increment`
* @property {number} [user_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {number} [delegated_user_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {string} [permissions] - NULL=`YES` Key=`` Default=`edit` Extra=``
* @property {number} [permission_level_code] - NULL=`YES` Key=`` Default=`1` Extra=``
* @property {string} [date_created] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_created_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_created_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED`
* @property {string} [date_updated] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_updated_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_updated_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED on update CURRENT_TIMESTAMP`
*/
/**
* @typedef {object} MYSQL_invitations_table_def
* @property {number} [id] - NULL=`NO` Key=`PRI` Default=`null` Extra=`auto_increment`
* @property {number} [inviting_user_id] - NULL=`NO` Key=`MUL` Default=`null` Extra=``
* @property {string} [invited_user_email] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [invitation_status] - NULL=`YES` Key=`` Default=`Pending` Extra=``
* @property {string} [database_access] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [priviledge] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [db_tables_data] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_created] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_created_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_created_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED`
* @property {string} [date_updated] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_updated_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_updated_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED on update CURRENT_TIMESTAMP`
*/
/**
* @typedef {object} MYSQL_docs_pages_table_def
* @property {number} [id] - NULL=`NO` Key=`PRI` Default=`null` Extra=`auto_increment`
* @property {string} [title] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [slug] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [description] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [content] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [text_content] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {number} [level] - NULL=`YES` Key=`` Default=`1` Extra=``
* @property {number} [page_order] - NULL=`YES` Key=`` Default=`1` Extra=``
* @property {number} [parent_id] - NULL=`YES` Key=`` Default=`null` Extra=``
* @property {string} [date_created] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_created_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_created_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED`
* @property {string} [date_updated] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {number} [date_updated_code] - NULL=`NO` Key=`` Default=`null` Extra=``
* @property {string} [date_updated_timestamp] - NULL=`YES` Key=`` Default=`CURRENT_TIMESTAMP` Extra=`DEFAULT_GENERATED on update CURRENT_TIMESTAMP`
*/
/**
* @typedef {object} MYSQL_delegated_user_tables_table_def
* @property {number} [id]
* @property {number} [delegated_user_id]
* @property {number} [root_user_id]
* @property {string} [database]
* @property {string} [table]
* @property {string} [priviledge]
* @property {string} [date_created]
* @property {number} [date_created_code]
* @property {string} [date_created_timestamp]
* @property {string} [date_updated]
* @property {number} [date_updated_code]
* @property {string} [date_updated_timestamp]
*/
// React.Dispatch<React.SetStateAction<any>>
// React.MutableRefObject<HTMLElement | undefined>
// React.MutableRefObject<React.Dispatch<React.SetStateAction<number>>>
// React.LegacyRef<HTMLDivElement | undefined>
// /** @type {HTMLFormElement} */ // @ts-ignore
// const formEl = e.target;
// /** @type {HTMLInputElement} */ // @ts-ignore
// const inputEl = e.target;
// /** @type {HTMLSelectElement} */ // @ts-ignore
// const selectEl = e.target;
/** @type {any} */
/** @type {any} */ // @ts-ignore
// @ts-ignore
// @param {object} params
// /** @type {any} */
// const dbTablesState = React.useState(0);
// /** @type {[ state: any, dispatch: React.Dispatch<React.SetStateAction<any>> ]} */ // @ts-ignore
// const [dbTables, setDbTables] = dbTablesState;
// /** @type {import("@/package-shared/types").AddEntryContextType} */ // @ts-ignore
// const init = {};
// export const AddTableEntryContext = React.createContext(init);

View File

@ -0,0 +1,48 @@
// @ts-check
const fs = require("fs");
const path = require("path");
const mysql = require("serverless-mysql");
const SSL_DIR = "/app/ssl";
const MASTER = mysql({
config: {
host: process.env.DSQL_DB_HOST,
user: process.env.DSQL_DB_USERNAME,
password: process.env.DSQL_DB_PASSWORD,
database: process.env.DSQL_DB_NAME,
port: process.env.DB_PORT ? Number(process.env.DB_PORT) : undefined,
charset: "utf8mb4",
ssl: {
ca: fs.readFileSync(`${SSL_DIR}/ca-cert.pem`),
},
},
});
/**
* DSQL user read-only DB handler
* @param {object} params
* @param {string} params.paradigm
* @param {string} params.database
* @param {string} params.queryString
* @param {string[]} [params.queryValues]
*/ // @ts-ignore
async function DB_HANDLER(...args) {
try {
const results = await MASTER.query(...args);
/** ********************* Clean up */
await MASTER.end();
return JSON.parse(JSON.stringify(results));
} catch (/** @type {any} */ error) {
console.log("DB Error =>", error);
return {
success: false,
error: error.message,
};
}
}
module.exports = DB_HANDLER;

View File

@ -0,0 +1,129 @@
// @ts-check
const fs = require("fs");
const path = require("path");
const mysql = require("serverless-mysql");
const SSL_DIR = "/app/ssl";
let DSQL_USER = mysql({
config: {
host: process.env.DSQL_DB_HOST,
user: process.env.DSQL_DB_READ_ONLY_USERNAME,
password: process.env.DSQL_DB_READ_ONLY_PASSWORD,
charset: "utf8mb4",
ssl: {
ca: fs.readFileSync(`${SSL_DIR}/ca-cert.pem`),
},
},
});
/**
* DSQL user read-only DB handler
* @param {object} params
* @param {"Full Access" | "FA" | "Read Only"} params.paradigm
* @param {string} params.database
* @param {string} params.queryString
* @param {string[]} [params.queryValues]
*/
function DSQL_USER_DB_HANDLER({
paradigm,
database,
queryString,
queryValues,
}) {
try {
return new Promise((resolve, reject) => {
const fullAccess = paradigm?.match(/full.access|^fa$/i)
? true
: false;
try {
if (fullAccess) {
DSQL_USER = mysql({
config: {
host: process.env.DSQL_DB_HOST,
user: process.env.DSQL_DB_FULL_ACCESS_USERNAME,
password: process.env.DSQL_DB_FULL_ACCESS_PASSWORD,
database: database,
ssl: {
ca: fs.readFileSync(`${SSL_DIR}/ca-cert.pem`),
},
},
});
} else {
DSQL_USER = mysql({
config: {
host: process.env.DSQL_DB_HOST,
user: process.env.DSQL_DB_READ_ONLY_USERNAME,
password: process.env.DSQL_DB_READ_ONLY_PASSWORD,
database: database,
ssl: {
ca: fs.readFileSync(`${SSL_DIR}/ca-cert.pem`),
},
},
});
}
/**
* ### Run query Function
* @param {any} results
*/
function runQuery(results) {
DSQL_USER.end();
resolve(JSON.parse(JSON.stringify(results)));
}
/**
* ### Query Error
* @param {any} err
*/
function queryError(err) {
DSQL_USER.end();
resolve({
error: err.message,
queryStringGenerated: queryString,
queryValuesGenerated: queryValues,
sql: err.sql,
});
}
if (
queryValues &&
Array.isArray(queryValues) &&
queryValues[0]
) {
DSQL_USER.query(queryString, queryValues)
.then(runQuery)
.catch(queryError);
} else {
DSQL_USER.query(queryString)
.then(runQuery)
.catch(queryError);
}
////////////////////////////////////////
} catch (/** @type {any} */ error) {
////////////////////////////////////////
fs.appendFileSync(
"./.tmp/dbErrorLogs.txt",
error.message + "\n" + Date() + "\n\n\n",
"utf8"
);
resolve({
error: error.message,
});
}
});
} catch (/** @type {any} */ error) {
return {
success: false,
error: error.message,
};
}
}
module.exports = DSQL_USER_DB_HANDLER;

View File

@ -0,0 +1,63 @@
// @ts-check
const fs = require("fs");
const path = require("path");
// const mysql = require("mysql");
// const NO_DB = mysql.createConnection({
// host: process.env.DSQL_DB_HOST,
// user: process.env.DSQL_DB_USERNAME,
// password: process.env.DSQL_DB_PASSWORD,
// charset: "utf8mb4",
// });
const mysql = require("serverless-mysql");
const SSL_DIR = "/app/ssl";
let NO_DB = mysql({
config: {
host: process.env.DSQL_DB_HOST,
user: process.env.DSQL_DB_USERNAME,
password: process.env.DSQL_DB_PASSWORD,
charset: "utf8mb4",
ssl: {
ca: fs.readFileSync(`${SSL_DIR}/ca-cert.pem`),
},
},
});
/**
* DSQL user read-only DB handler
* @param {object} params
* @param {string} params.paradigm
* @param {string} params.database
* @param {string} params.queryString
* @param {string[]} [params.queryValues]
*/ // @ts-ignore
function NO_DB_HANDLER(...args) {
try {
return new Promise((resolve, reject) => {
NO_DB.query(...args)
.then((results) => {
NO_DB.end();
resolve(JSON.parse(JSON.stringify(results)));
})
.catch((err) => {
NO_DB.end();
resolve({
error: err.message,
sql: err.sql,
});
});
});
} catch (/** @type {any} */ error) {
return {
success: false,
error: error.message,
};
}
}
module.exports = NO_DB_HANDLER;

View File

@ -0,0 +1,54 @@
// @ts-check
const fs = require("fs");
const path = require("path");
const mysql = require("serverless-mysql");
const SSL_DIR = "/app/ssl";
let NO_DB = mysql({
config: {
host: process.env.DSQL_DB_HOST,
user: process.env.DSQL_DB_USERNAME,
password: process.env.DSQL_DB_PASSWORD,
charset: "utf8mb4",
ssl: {
ca: fs.readFileSync(`${SSL_DIR}/ca-cert.pem`),
},
},
});
/**
* DSQL user read-only DB handler
* @param {object} params
* @param {string} params.paradigm
* @param {string} params.database
* @param {string} params.queryString
* @param {string[]} [params.queryValues]
*/ // @ts-ignore
function ROOT_DB_HANDLER(...args) {
try {
return new Promise((resolve, reject) => {
NO_DB.query(...args)
.then((results) => {
NO_DB.end();
resolve(JSON.parse(JSON.stringify(results)));
})
.catch((err) => {
NO_DB.end();
resolve({
error: err.message,
sql: err.sql,
});
});
});
} catch (/** @type {any} */ error) {
return {
success: false,
error: error.message,
};
}
}
module.exports = ROOT_DB_HANDLER;

View File

@ -0,0 +1,49 @@
// @ts-check
const fs = require("fs");
const DSQL_USER_DB_HANDLER = require("./DSQL_USER_DB_HANDLER");
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
process.addListener("exit", async (code) => {
console.log("PROCESS EXITING ...");
});
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Global function
* ================================================
* @description this sets all require global variables. This only runs once.
*/
module.exports = function globalFunction() {
/**
* Main Db Handler
*/
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Main Db Handler
*/
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* DSQL user read-only DB handler
* @param {object} params
* @param {string} params.paradigm
* @param {string} params.database
* @param {string} params.queryString
* @param {string[]} [params.queryValues]
*/
DSQL_USER_DB_HANDLER;
};

View File

@ -0,0 +1,38 @@
/**
*
* @param {string | null | number} string
* @param {(this: any, key: string, value: any) => any} [reviver]
* @returns {{ [key: string]: any } | { [key: string]: any }[] | undefined}
*/
function parse(string, reviver) {
if (!string) return undefined;
if (typeof string == "object") return string;
if (typeof string !== "string") return undefined;
try {
return JSON.parse(string, reviver);
} catch (error) {
return undefined;
}
}
/**
*
* @param {any} value
* @param {(this: any, key: string, value: any) => any} [replacer]
* @param { string | number } [space]
* @returns {string | undefined}
*/
function stringify(value, replacer, space) {
try {
return JSON.stringify(value, replacer, space);
} catch (error) {
return undefined;
}
}
const EJSON = {
parse,
stringify,
};
module.exports = EJSON;

View File

@ -1,6 +1,6 @@
{
"name": "datasquirel",
"version": "2.3.4",
"version": "2.3.5",
"description": "Cloud-based SQL data management tool",
"main": "index.js",
"bin": {
@ -26,11 +26,19 @@
},
"homepage": "https://datasquirel.com/",
"dependencies": {
"@types/ace": "^0.0.52",
"@types/react": "^18.3.12",
"@types/tinymce": "^4.6.9",
"dotenv": "^16.3.1",
"generate-password": "^1.7.1",
"lodash": "^4.17.21",
"mysql": "^2.18.1",
"nodemailer": "^6.9.14"
"nodemailer": "^6.9.14",
"sanitize-html": "^2.13.1",
"serverless-mysql": "^1.5.5"
},
"devDependencies": {
"@types/lodash": "^4.17.13",
"@types/mysql": "^2.15.21",
"@types/node": "^22.7.5"
}

View File

@ -29,7 +29,7 @@
"types",
"users",
"utils",
"package-shared/types"
"package-shared"
],
"exclude": ["node_modules", "dump"]
}

View File

@ -27,7 +27,7 @@ const localUpdateUser = require("../engine/user/update-user");
* @param {object} params - API Key
* @param {String} params.key - API Key
* @param {String} params.database - Target Database
* @param {{ id: number } & Object.<string, *>} params.payload - User Object: ID is required
* @param {{ id: number } & Object.<string, any>} params.payload - User Object: ID is required
*
* @returns { Promise<import("../package-shared/types").UpdateUserFunctionReturn>}
*/

View File

@ -44,19 +44,16 @@ async function get({ key, db, query, queryValues, tableName }) {
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const {
DSQL_HOST,
DSQL_USER,
DSQL_PASS,
DSQL_DB_HOST,
DSQL_DB_USERNAME,
DSQL_MARIADB_ROOT_PASSWORD,
DSQL_DB_NAME,
DSQL_KEY,
DSQL_REF_DB_NAME,
DSQL_FULL_SYNC,
} = process.env;
if (
DSQL_HOST?.match(/./) &&
DSQL_USER?.match(/./) &&
DSQL_PASS?.match(/./) &&
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_MARIADB_ROOT_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */