Compare commits

..

25 Commits

Author SHA1 Message Date
Benjamin Toby
54b7981be4 Update Query algo 2024-11-06 10:30:00 +01:00
Benjamin Toby
6c78cae127 Add Remote API 2024-11-06 07:37:42 +01:00
Benjamin Toby
190598aa3f Updates 2024-11-06 07:26:23 +01:00
Benjamin Toby
d81f38809b Update types 2024-10-24 08:08:22 +01:00
Benjamin Toby
1b6504ab93 Update types 2024-10-23 07:08:06 +01:00
Benjamin Toby
fdb1501588 Update types 2024-10-23 06:55:53 +01:00
Benjamin Toby
adf599009c Update types 2024-10-22 18:32:02 +01:00
Benjamin Toby
c801ddfdd9 Updates 2024-10-22 18:29:50 +01:00
Benjamin Toby
b03d90026c Testing 2024-10-22 18:26:38 +01:00
Benjamin Toby
c2328116da Updates 2024-10-22 18:17:59 +01:00
Benjamin Toby
d774e8d35d Update types 2024-10-21 08:05:18 +01:00
Benjamin Toby
fabf2945d7 Update types 2024-10-19 17:59:05 +01:00
Benjamin Toby
0690b5f081 Update types 2024-10-19 17:52:12 +01:00
Benjamin Toby
d6e89b4ed8 Update version 2024-10-19 17:50:52 +01:00
Benjamin Toby
2804f85236 Update types 2024-10-19 17:50:33 +01:00
Benjamin Toby
4462ba315d Update types: Remove '@/' references 2024-10-19 17:45:42 +01:00
Benjamin Toby
bf1d7f5fcd Update Types and Bugfixes 2024-10-18 07:02:16 +01:00
Benjamin Toby
30f607ce8d Update Types 2024-10-18 06:48:45 +01:00
Benjamin Toby
bf903d3524 Update Types 2024-10-18 06:45:25 +01:00
Benjamin Toby
2f93b6a311 Update Types 2024-10-18 06:02:12 +01:00
Benjamin Toby
33283e7d0f Refactor get query serialization 2024-10-18 05:49:04 +01:00
Benjamin Toby
e2d2d00487 Update version 2024-10-18 05:20:53 +01:00
Benjamin Toby
4bbb4da274 Update types 2024-10-18 05:20:28 +01:00
Benjamin Toby
59c6f6dd40 Update types 2024-10-18 05:15:04 +01:00
Benjamin Toby
5d395fe3b5 Update package.json 2024-10-14 13:44:31 +01:00
85 changed files with 4790 additions and 813 deletions

2
.gitignore vendored
View File

@ -141,3 +141,5 @@ test/
# NPM
# .npmrc
/dump

4
.npmrc
View File

@ -1,4 +1,4 @@
# registry=https://git.tben.me/api/packages/Moduletrace/npm/
# registry=https://git.tben.me/api/packages/Moduletrace/npm/
# //git.tben.me/api/packages/Moduletrace/npm/:_authToken=${GITBEN_NPM_TOKEN}
registry=https://git.tben.me/api/packages/Moduletrace/npm/
//git.tben.me/api/packages/Moduletrace/npm/:_authToken=${GITBEN_NPM_TOKEN}

View File

@ -116,3 +116,29 @@ const postData = await datasquirel.uploadImage({
},
});
```
### Local Querying
You can query directly from an SQL database if you provide these environment variables in your `.env` file:
```conf
DSQL_DB_HOST=
DSQL_DB_PORT=
DSQL_DB_USERNAME=
DSQL_DB_PASSWORD=
DSQL_DB_NAME=
DSQL_SSL_DIR=
```
The ssl directory **_must_** contain a file named `ca-cert.pem`. `DSQL_DB_PORT` defaults to **3306** if not provided.
### Remote Querying
You can query from a self hosted installation of datasquirel. Just add these environment variables:
```conf
DSQL_API_REMOTE_HOST=
DSQL_API_REMOTE_HOST_PORT=
```
If these aren't provided it defaults to `datasquirel.com`.

View File

@ -1,22 +1,10 @@
/**
* ==============================================================================
* Imports
* ==============================================================================
*/
import imageInputFileToBase64 from "./imageInputFileToBase64";
import imageInputToBase64 from "./imageInputToBase64";
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* ==============================================================================
* ==========================
* Media Functions Object
* ==============================================================================
* ==========================
*/
const media = {
imageInputToBase64: imageInputToBase64,
@ -24,9 +12,9 @@ const media = {
};
/**
* ==============================================================================
* ==========================
* Media Functions Object
* ==============================================================================
* ==========================
*/
const auth = {
imageInputToBase64: imageInputToBase64,
@ -34,16 +22,12 @@ const auth = {
};
/**
* ==============================================================================
* ==========================
* Main Export
* ==============================================================================
* ==========================
*/
const datasquirelClient = {
media: media,
};
export default datasquirelClient;
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */

View File

@ -68,6 +68,7 @@ async function run() {
process.exit();
}
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType} */ // @ts-ignore
let fetchedDbSchemaObject = dbSchemaDataResponse.payload;
if (DSQL_DB_NAME) fetchedDbSchemaObject.dbFullName = DSQL_DB_NAME;

View File

@ -22,7 +22,7 @@ const updateApiSchemaFromLocalDb = require("../query/update-api-schema-from-loca
* ==============================================================================
*
* @param {object} params - Single object passed
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} params.dbSchema - Database Schema Object
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} params.dbSchema - Database Schema Object
*
* @returns {Promise<*>} new user auth object payload
*/
@ -33,7 +33,7 @@ module.exports = async function addUsersTableToDb({ dbSchema }) {
* @description Initialize
*/
const database = process.env.DSQL_DB_NAME || "";
/** @type {import("@/package-shared/types/database-schema.td").DSQL_TableSchemaType} */
/** @type {import("../../package-shared/types").DSQL_TableSchemaType} */
const userPreset = require("./data/presets/users.json");
try {

View File

@ -27,7 +27,7 @@ const updateTable = require("./utils/updateTable");
* runs the "dsql create" command. `NOTE`: there must be a "dsql.schema.json" file
* in the root of the project for this function to work
*
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} dbSchema - An array of database schema objects
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} dbSchema - An array of database schema objects
*/
async function createDbFromSchema(dbSchema) {
try {
@ -42,7 +42,7 @@ async function createDbFromSchema(dbSchema) {
}
for (let i = 0; i < dbSchema.length; i++) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
const database = dbSchema[i];
if (!database) {
@ -262,11 +262,11 @@ async function createDbFromSchema(dbSchema) {
*/
await varDatabaseDbHandler({
queryString: `CREATE${
indexType.match(/fullText/i)
indexType?.match(/fullText/i)
? " FULLTEXT"
: ""
} INDEX \`${alias}\` ON ${tableName}(${indexTableFields
.map((nm) => nm.value)
?.map((nm) => nm.value)
.map((nm) => `\`${nm}\``)
.join(
","

View File

@ -17,7 +17,7 @@ const supplementTable = require("./supplementTable");
* @param {string} param0.tableName
* @param {any[]} param0.tableInfoArray
* @param {(params: import("./varDatabaseDbHandler").VarDbHandlerParam)=>any} param0.varDatabaseDbHandler
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType} [param0.dbSchema]
* @param {import("../../../package-shared/types").DSQL_DatabaseSchemaType} [param0.dbSchema]
* @returns
*/
module.exports = async function createTable({

View File

@ -65,7 +65,7 @@ const connection = mysql.createConnection({
* @param {object} params - Single Param object containing params
* @param {string} params.query - Query String
* @param {(string | number)[]} [params.values] - Values
* @param {import("../../../package-shared/types/database-schema.td").DSQL_DatabaseSchemaType} [params.dbSchema] - Database Schema
* @param {import("../../../package-shared/types").DSQL_DatabaseSchemaType} [params.dbSchema] - Database Schema
* @param {string} [params.database] - Target Database
* @param {string} [params.tableName] - Target Table Name
*

View File

@ -11,7 +11,7 @@
* Generate SQL text for Field
* ==============================================================================
* @param {object} params - Single object params
* @param {import("@/package-shared/types/database-schema.td").DSQL_FieldSchemaType} params.columnData - Field object
* @param {import("../../../package-shared/types").DSQL_FieldSchemaType} params.columnData - Field object
* @param {boolean} [params.primaryKeySet] - Table Name(slug)
*
* @returns {{fieldEntryText: string, newPrimaryKeySet: boolean}}

View File

@ -14,7 +14,7 @@ const defaultFieldsRegexp = require("./defaultFieldsRegexp");
* @param {object} params - Single object params
* @param {*[]} params.unparsedResults - Array of data objects containing Fields(keys)
* and corresponding values of the fields(values)
* @param {import("../../../package-shared/types/database-schema.td").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @param {import("../../../package-shared/types").DSQL_TableSchemaType} [params.tableSchema] - Table schema
* @returns {Promise<object[]|null>}
*/
module.exports = async function parseDbResults({

View File

@ -10,7 +10,7 @@
/**
*
* @param {object} param0
* @param {import("@/package-shared/types/database-schema.td").DSQL_FieldSchemaType[]} param0.tableInfoArray
* @param {import("../../../package-shared/types").DSQL_FieldSchemaType[]} param0.tableInfoArray
* @returns
*/
module.exports = function supplementTable({ tableInfoArray }) {

View File

@ -31,9 +31,9 @@ const schemaPath = path.resolve(process.cwd(), "dsql.schema.json");
* @param {object} params - Single object params
* @param {string} params.dbFullName - Database full name => "datasquirel_user_4394_db_name"
* @param {string} params.tableName - Table Name(slug)
* @param {import("@/package-shared/types/database-schema.td").DSQL_FieldSchemaType[]} params.tableInfoArray - Table Info Array
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType[]} params.dbSchema - Single post
* @param {import("@/package-shared/types/database-schema.td").DSQL_IndexSchemaType[]} [params.tableIndexes] - Table Indexes
* @param {import("../../../package-shared/types").DSQL_FieldSchemaType[]} params.tableInfoArray - Table Info Array
* @param {import("../../../package-shared/types").DSQL_DatabaseSchemaType[]} params.dbSchema - Single post
* @param {import("../../../package-shared/types").DSQL_IndexSchemaType[]} [params.tableIndexes] - Table Indexes
* @param {boolean} [params.clone] - Is this a newly cloned table?
* @param {number} [params.tableIndex] - The number index of the table in the dbSchema array
*
@ -88,7 +88,7 @@ module.exports = async function updateTable({
////////////////////////////////////////
/**
* @type {DSQL_MYSQL_SHOW_INDEXES_Type[]}
* @type {import("../../../package-shared/types").DSQL_MYSQL_SHOW_INDEXES_Type[]}
* @description All indexes from MYSQL db
*/
const allExistingIndexes = await varDatabaseDbHandler({
@ -97,7 +97,7 @@ module.exports = async function updateTable({
});
/**
* @type {DSQL_MYSQL_SHOW_COLUMNS_Type[]}
* @type {import("../../../package-shared/types").DSQL_MYSQL_SHOW_COLUMNS_Type[]}
* @description All columns from MYSQL db
*/
const allExistingColumns = await varDatabaseDbHandler({
@ -141,7 +141,9 @@ module.exports = async function updateTable({
* @description Check if Field name has been updated
*/
if (existingEntry[0].updatedField) {
updatedColumnsArray.push(existingEntry[0].fieldName);
updatedColumnsArray.push(
String(existingEntry[0].fieldName)
);
const renameColumn = await varDatabaseDbHandler({
queryString: `ALTER TABLE ${tableName} RENAME COLUMN \`${existingEntry[0].originName}\` TO \`${existingEntry[0].fieldName}\``,
@ -293,9 +295,9 @@ module.exports = async function updateTable({
*/
await varDatabaseDbHandler({
queryString: `CREATE${
indexType.match(/fullText/i) ? " FULLTEXT" : ""
indexType?.match(/fullText/i) ? " FULLTEXT" : ""
} INDEX \`${alias}\` ON ${tableName}(${indexTableFields
.map((nm) => nm.value)
?.map((nm) => nm.value)
.map((nm) => `\`${nm}\``)
.join(",")}) COMMENT 'schema_index'`,
database: dbFullName,
@ -375,7 +377,7 @@ module.exports = async function updateTable({
/**
* @description Skip default fields
*/
if (fieldName.match(/^id$|^date_/)) continue;
if (fieldName?.match(/^id$|^date_/)) continue;
/**
* @description Skip columns that have been updated recently
*/
@ -424,7 +426,7 @@ module.exports = async function updateTable({
if (
Field === fieldName &&
!isColumnReordered &&
dataType.toUpperCase() === Type.toUpperCase()
dataType?.toUpperCase() === Type.toUpperCase()
) {
updateText += `MODIFY COLUMN ${fieldEntryText}`;
// continue;

View File

@ -24,7 +24,7 @@ const dbHandler = require("./dbHandler");
* @property {string} queryString - SQL string
* @property {string[]} [queryValuesArray] - Values Array
* @property {string} database - Database name
* @property {import("@/package-shared/types/database-schema.td").DSQL_TableSchemaType} [tableSchema] - Table schema
* @property {import("../../../package-shared/types").DSQL_TableSchemaType} [tableSchema] - Table schema
*/
/**

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
@ -29,7 +29,7 @@ const runQuery = require("./utils/runQuery");
*
* @param {Object} params - Single object passed
* @param {LocalQueryObject} params.options - SQL Query
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} [params.dbSchema] - Name of the table to query
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} [params.dbSchema] - Name of the table to query
*
* @returns { Promise<LocalGetReturn> } - Return Object
*/
@ -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,21 +1,6 @@
// @ts-check
const runQuery = require("./utils/runQuery");
/**
* @typedef {Object} LocalPostReturn
* @property {boolean} success - Did the function run successfully?
* @property {*} [payload] - GET request results
* @property {string} [msg] - Message
* @property {string} [error] - Error Message
*/
/**
* @typedef {Object} LocalPostQueryObject
* @property {string | import("../../utils/post").PostDataPayload} query - Table Name
* @property {string} [tableName] - Table Name
* @property {string[]} [queryValues] - GET request results
*/
const runQuery = require("../../package-shared/functions/backend/db/runQuery");
/**
* Make a get request to Datasquirel API
@ -23,10 +8,10 @@ const runQuery = require("./utils/runQuery");
* @async
*
* @param {Object} params - Single object passed
* @param {LocalPostQueryObject} params.options - SQL Query
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} [params.dbSchema] - Name of the table to query
* @param {import("../../package-shared/types").LocalPostQueryObject} params.options - SQL Query
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} [params.dbSchema] - Name of the table to query
*
* @returns { Promise<LocalPostReturn> } - Return Object
* @returns { Promise<import("../../package-shared/types").LocalPostReturn> } - Return Object
*/
async function localPost({ options, dbSchema }) {
try {
@ -67,6 +52,7 @@ async function localPost({ options, dbSchema }) {
dbSchema: dbSchema,
queryValuesArray: queryValues,
tableName,
local: true,
});
if (error) throw error;
@ -83,7 +69,6 @@ async function localPost({ options, dbSchema }) {
return {
success: false,
payload: null,
error: error.message,
};
}
@ -95,7 +80,6 @@ async function localPost({ options, dbSchema }) {
return {
success: false,
payload: null,
msg: "Something went wrong!",
};

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/database-schema.td").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,18 +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");
/**
* @typedef {Object} LocalPostReturn
* @property {boolean} success - Did the function run successfully?
* @property {*} [payload] - GET request results
* @property {string} [msg] - Message
* @property {string} [error] - Error Message
*/
/**
* Make a get request to Datasquirel API
@ -20,12 +11,12 @@ const runQuery = require("../query/utils/runQuery");
* @async
*
* @param {Object} params - Single object passed
* @param {import("@/types/user.td").UserDataPayload} params.payload - SQL Query
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} params.dbSchema - Name of the table to query
* @param {import("../../package-shared/types").UserDataPayload} params.payload - SQL Query
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} params.dbSchema - Name of the table to query
* @param {string} [params.encryptionKey]
* @param {string} [params.encryptionSalt]
*
* @returns { Promise<LocalPostReturn> } - Return Object
* @returns { Promise<import("../../package-shared/types").AddUserFunctionReturn> } - Return Object
*/
async function localAddUser({
payload,
@ -50,7 +41,7 @@ async function localAddUser({
if (!payload?.password) {
return {
success: false,
payload: `Password is required to create an account`,
msg: `Password is required to create an account`,
};
}
@ -79,7 +70,7 @@ async function localAddUser({
if (!fields) {
return {
success: false,
payload: "Could not create users table",
msg: "Could not create users table",
};
}
@ -100,7 +91,7 @@ async function localAddUser({
if (invalidField) {
return {
success: false,
payload: `${invalidField} is not a valid field!`,
msg: `${invalidField} is not a valid field!`,
};
}
@ -126,7 +117,7 @@ async function localAddUser({
if (existingUser && existingUser[0]) {
return {
success: false,
payload: "User Already Exists",
msg: "User Already Exists",
};
}
@ -157,7 +148,7 @@ async function localAddUser({
} else {
return {
success: false,
payload: "Could not create user",
msg: "Could not create user",
};
}
@ -168,7 +159,6 @@ async function localAddUser({
return {
success: false,
payload: null,
msg: "Something went wrong!",
};

View File

@ -7,7 +7,7 @@ const varDatabaseDbHandler = require("../engine/utils/varDatabaseDbHandler");
* @param {object} param0
* @param {number} param0.userId
* @param {string[]} param0.fields
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} [param0.dbSchema]
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} [param0.dbSchema]
* @returns
*/
async function getLocalUser({ userId, fields, dbSchema }) {

View File

@ -5,7 +5,7 @@ const varDatabaseDbHandler = require("../engine/utils/varDatabaseDbHandler");
/**
*
* @param {PackageUserLoginLocalBody} param0
* @param {import("../../package-shared/types").PackageUserLoginLocalBody} param0
* @returns
*/
async function loginLocalUser({

View File

@ -7,7 +7,7 @@ const varDatabaseDbHandler = require("../engine/utils/varDatabaseDbHandler");
* @param {object} param0
* @param {*} param0.existingUser
* @param {string[]} [param0.additionalFields]
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} [param0.dbSchema]
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} [param0.dbSchema]
* @returns
*/
async function localReauthUser({ existingUser, additionalFields, dbSchema }) {

View File

@ -10,7 +10,7 @@ const path = require("path");
*
* @param {object} param0
* @param {string} param0.email
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} [param0.dbSchema]
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} [param0.dbSchema]
* @param {string} param0.email_login_field
* @param {string} [param0.mail_domain]
* @param {string} [param0.mail_username]
@ -77,15 +77,6 @@ async function localSendEmailCode({
msg: "No user found",
};
function generateCode() {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let code = "";
for (let i = 0; i < 8; i++) {
code += chars[Math.floor(Math.random() * chars.length)];
}
return code;
}
if (foundUser && foundUser[0] && email_login_field) {
const tempCode = generateCode();
@ -150,4 +141,13 @@ async function localSendEmailCode({
}
}
function generateCode() {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let code = "";
for (let i = 0; i < 8; i++) {
code += chars[Math.floor(Math.random() * chars.length)];
}
return code;
}
module.exports = localSendEmailCode;

View File

@ -36,7 +36,7 @@ const encryptionSalt = process.env.DSQL_ENCRYPTION_SALT || "";
* @param {string} params.clientId
* @param {string} params.clientSecret
* @param {object} [params.additionalFields]
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType} params.dbSchema
* @param {import("../../../package-shared/types").DSQL_DatabaseSchemaType} params.dbSchema
*/
async function localGithubAuth({
res,

View File

@ -44,7 +44,7 @@ const encryptionSalt = process.env.DSQL_ENCRYPTION_SALT || "";
* @param {string} params.clientId - Google client id
* @param {http.ServerResponse} params.response - HTTPS response object
* @param {object} [params.additionalFields] - Additional Fields to be added to the user object
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType} [params.dbSchema] - Database Schema
* @param {import("../../../package-shared/types").DSQL_DatabaseSchemaType} [params.dbSchema] - Database Schema
*
* @returns { Promise<FunctionReturn> }
*/

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");
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
@ -74,7 +74,7 @@ const encryptionSalt = process.env.DSQL_ENCRYPTION_SALT || "";
* res: http.ServerResponse,
* supEmail?: string | null,
* additionalFields?: object,
* dbSchema: import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined
* dbSchema: import("../../../../package-shared/types").DSQL_DatabaseSchemaType | undefined
* }} params - function parameters inside an object
*
* @returns {Promise<FunctionReturn>} - Response object

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
@ -17,7 +17,7 @@ const updateDbEntry = require("../query/utils/updateDbEntry");
*
* @param {Object} params - Single object passed
* @param {*} params.payload - SQL Query
* @param {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} params.dbSchema - Name of the table to query
* @param {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined} params.dbSchema - Name of the table to query
*
* @returns { Promise<LocalPostReturn> } - Return Object
*/

View File

@ -31,6 +31,7 @@ const decrypt = ({ encryptedString, encryptionKey, encryptionSalt }) => {
let key = scryptSync(encryptionKey, encryptionSalt, 24);
let iv = Buffer.alloc(16, 0);
// @ts-ignore
const decipher = createDecipheriv(algorithm, key, iv);
try {

View File

@ -30,6 +30,7 @@ const encrypt = ({ data, encryptionKey, encryptionSalt }) => {
let key = scryptSync(password, encryptionSalt, 24);
let iv = Buffer.alloc(16, 0);
// @ts-ignore
const cipher = createCipheriv(algorithm, key, iv);
try {

300
package-lock.json generated
View File

@ -1,32 +1,62 @@
{
"name": "datasquirel",
"version": "2.0.0",
"version": "2.3.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "datasquirel",
"version": "2.0.0",
"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/database-schema.td").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/database-schema.td").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/database-schema.td").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,91 @@
// @ts-check
const fs = require("fs");
const serverError = require("./serverError");
const mysql = require("serverless-mysql");
const path = require("path");
const SSL_DIR =
process.env.DSQL_SSL_DIR || path.resolve(__dirname, "../../../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,95 +0,0 @@
/**
* @typedef {string} DSQL_DatabaseFullName - Database full name(slug) including datasquirel data => "datasquirel_user_7_new_database"
*/
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* @typedef {object} DSQL_DatabaseSchemaType
* @property {string} dbName - Database Full name with spaces => "New Database"
* @property {string} dbSlug - Database Slug => "new_database"
* @property {string} dbFullName - Database full name(slug) including datasquirel data => "datasquirel_user_7_new_database"
* @property {string} [dbDescription] - Database brief description
* @property {string} [dbImage] - Database image - Defaults to "/images/default.png"
* @property {DSQL_TableSchemaType[]} tables - List of database tables
* @property {{ dbFullName: string }[]} [childrenDatabases] - List of children databases for current database which is parent
* @property {boolean} [childDatabase] - If current database is a child of a different parent database
* @property {string} [childDatabaseDbFullName] - Parent database full name => "datasquirel_user_7_new_database"
*/
////////////////////////////////////////
/**
* @typedef {object} DSQL_TableSchemaType
* @property {string} tableName - Table slug (blog_posts)
* @property {string} tableFullName - Table full name with spaces => "Blog Posts"
* @property {string} [tableDescription] - Brief description of table
* @property {DSQL_FieldSchemaType[]} fields - List of table Fields
* @property {DSQL_IndexSchemaType[]} [indexes] - List of table indexes, if available
* @property {DSQL_ChildrenTablesType[]} [childrenTables] - List of children tables
* @property {boolean} [childTable] -If current table is a child clone
* @property {string} [childTableName] - Table slug of parent table => "blog_posts"
* @property {string} [childTableDbFullName] - Database full name(slug) including datasquirel data => "datasquirel_user_7_new_database"
* @property {string} [tableNameOld] - Old table name, incase of renaming table
*/
/**
* @typedef {object} DSQL_ChildrenTablesType
* @property {string} dbNameFull - Database full name(slug) including datasquirel data => "datasquirel_user_7_new_database"
* @property {string} tableName - Table slug => "blog_posts"
*/
////////////////////////////////////////
/**
* @typedef {object} DSQL_FieldSchemaType
* @property {string} fieldName - Field Name(slug) => "long_description"
* @property {string} [originName] - Field origin name(optional)
* @property {boolean} [updatedField] - Has this field been renamed?
* @property {string} dataType - Field Data type => "BIGIN" | "LONGTEXT" | "VARCHAR(***)" | ...
* @property {boolean} [nullValue] - Is this a null value or not?
* @property {boolean} [notNullValue] - Is this NOT a null value?
* @property {boolean} [primaryKey] - Is this the primary key for table?
* @property {boolean} [encrypted] - Is this field value encrypted?
* @property {boolean} [autoIncrement] - Does this table primary key increment automatically?
* @property {string|number} [defaultValue] - Value of field by default
* @property {string} [defaultValueLiteral] - SQL key word which generates value automatically => "CURRENT_TIMESTAMP"
* @property {DSQL_ForeignKeyType} [foreignKey] - Field foreign key reference object
* @property {boolean} [richText] - Rich text field
* @property {string | RegExp} [pattern] - Field pattern for validation. Can be a string or a regular expression. Example: "^[a-zA-Z0-9_]*$"
* @property {string} [patternFlags] - Field pattern flags for validation. Example: "i"
*/
/**
* @typedef {object} DSQL_ForeignKeyType
* @property {string} foreignKeyName - Unique Name of foreign key
* @property {string} destinationTableName - Reference table name(slug) => "blog_posts"
* @property {string} destinationTableColumnName - Reference column name(slug) => "id"
* @property {string} destinationTableColumnType - Reference table field type => "BIGINT" | "VARCHAR(***)" | ...
* @property {boolean} [cascadeDelete] - Does the reference table entry delete when this key is deleted?
* @property {boolean} [cascadeUpdate] - Does the reference table entry update when this key is updated?
*/
////////////////////////////////////////
/**
* @typedef {object} DSQL_IndexSchemaType
* @property {string} indexName - Unique Name of index => "blog_text_index"
* @property {string} indexType - "regular" or "fullText"
* @property {DSQL_IndexTableFieldType[]} indexTableFields - List of Index table fields
* @property {string} [alias] - List of Index table fields
*/
/**
* @typedef {object} DSQL_IndexTableFieldType
* @property {string} value - Table Field Name
* @property {string} dataType - Table Field data type "VARCHAR(***)" | "BIGINT" | ...
*/
////////////////////////////////////////
exports.DSQL_TableSchemaType = DSQL_TableSchemaType;

1098
package-shared/types/index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +0,0 @@
// @ts-check
/**
* @typedef {object} PackageUserLoginRequestBody
* @property {string} encryptionKey
* @property {any} payload
* @property {string} database
* @property {string[]} [additionalFields]
* @property {boolean} [email_login]
* @property {string} [email_login_code]
* @property {string} [email_login_field]
* @property {boolean} [token]
* @property {boolean} [social]
* @property {import("./database-schema.td").DSQL_DatabaseSchemaType} [dbSchema]
*/
/**
* @typedef {object} PackageUserLoginLocalBody
* @property {any} payload
* @property {string[]} [additionalFields]
* @property {boolean} [email_login]
* @property {string} [email_login_code]
* @property {string} [email_login_field]
* @property {boolean} [token]
* @property {boolean} [social]
* @property {import("./database-schema.td").DSQL_DatabaseSchemaType} [dbSchema]
*/

View File

@ -0,0 +1,51 @@
// @ts-check
const fs = require("fs");
const path = require("path");
const mysql = require("serverless-mysql");
const SSL_DIR =
process.env.DSQL_SSL_DIR || path.resolve(__dirname, "../../../../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.DSQL_DB_PORT
? Number(process.env.DSQL_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,130 @@
// @ts-check
const fs = require("fs");
const path = require("path");
const mysql = require("serverless-mysql");
const SSL_DIR =
process.env.DSQL_SSL_DIR || path.resolve(__dirname, "../../../../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,64 @@
// @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 =
process.env.DSQL_SSL_DIR || path.resolve(__dirname, "../../../../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,55 @@
// @ts-check
const fs = require("fs");
const path = require("path");
const mysql = require("serverless-mysql");
const SSL_DIR =
process.env.DSQL_SSL_DIR || path.resolve(__dirname, "../../../../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.1.1",
"version": "2.3.7",
"description": "Cloud-based SQL data management tool",
"main": "index.js",
"bin": {
@ -9,7 +9,7 @@
},
"repository": {
"type": "git",
"url": "git+https://git.tben.me/Moduletrace/datasquirel.git"
"url": "git+https://github.com/BenjaminToby/dsql.git"
},
"keywords": [
"SQL",
@ -22,15 +22,23 @@
"author": "Benjamin Toby",
"license": "ISC",
"bugs": {
"url": "https://git.tben.me/Moduletrace/datasquirel/issues"
"url": "https://github.com/BenjaminToby/dsql/issues"
},
"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

@ -2,22 +2,21 @@
"compilerOptions": {
"target": "ES2015",
"module": "commonjs",
"paths": {
"@/*": ["./*"]
},
"maxNodeModuleJsDepth": 10,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
// "skipLibCheck": true,
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"noEmit": true,
"incremental": true,
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"moduleResolution": "node",
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "./dump/tsc",
"plugins": [
{
"name": "next"
@ -30,7 +29,7 @@
"types",
"users",
"utils",
"package-shared/types"
"package-shared"
],
"exclude": ["node_modules", "dump"]
}

View File

View File

@ -1,20 +0,0 @@
const http = require("http");
/**
* @typedef {http.IncomingMessage} Request
*/
/**
* @typedef {http.ServerResponse} Response
*/
/**
* @typedef {{
* imageBase64: string,
* imageBase64Full: string,
* imageName: string,
* imageSize: number,
* }} ImageInputFileToBase64FunctionReturn
*/
module.exports = { Request, Response, ImageInputFileToBase64FunctionReturn };

View File

@ -1,48 +0,0 @@
/**
* @typedef {object} DSQL_MYSQL_SHOW_INDEXES_Type
* @property {string} Key_name - MYSQL Index Name
* @property {string} Table - Table Name(slug)
* @property {string} Column_name
* @property {string} Collation
* @property {string} Index_type - "FULL_TEXT" | ...
* @property {string} Cardinality
* @property {string} Index_comment
* @property {string} Comment
*/
////////////////////////////////////////
/**
* @typedef {object} DSQL_MYSQL_SHOW_COLUMNS_Type
* @property {string} Field - Field Name as represented in MSQL database
* @property {string} Type - varchar(***) | tinyint | bigint | ...
* @property {string} Null
* @property {string} Key
* @property {string} Default
* @property {string} Extra
*/
////////////////////////////////////////
/**
* @typedef {object} DSQL_MYSQL_FOREIGN_KEYS_Type
* @property {string} CONSTRAINT_NAME - Constraint Name => "PRIMARY" | "MUL" | null | ...
* @property {string} CONSTRAINT_SCHEMA - Database name
* @property {string} TABLE_NAME - Table name
*/
////////////////////////////////////////
/**
* @typedef {object} DSQL_MYSQL_user_databases_Type
* @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)
* @property {string} db_slug - Database slug => eg. (new_database)
* @property {string} db_image - Database image path
* @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"
*/
////////////////////////////////////////

View File

@ -1,129 +0,0 @@
/**
* @typedef {object} DATASQUIREL_LoggedInUser
* @property {number} [id]
* @property {string} first_name
* @property {string} last_name
* @property {string} email
* @property {string} [phone]
* @property {string} [user_type]
* @property {string} [username]
* @property {string} password
* @property {string} [image]
* @property {string} [image_thumbnail]
* @property {string} [address]
* @property {string} [city]
* @property {string} [state]
* @property {string} [country]
* @property {string} [zip_code]
* @property {number} [social_login]
* @property {string?} [social_platform]
* @property {string?} [social_id]
* @property {string} [more_user_data]
* @property {number} [verification_status]
* @property {number?} [loan_officer_id]
* @property {number} [is_admin]
* @property {number} [admin_level]
* @property {string} [admin_permissions]
* @property {string?} uuid
* @property {string?} [temp_login_code]
* @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]
* @property {string} [csrf_k] - CSRF key
* @property {boolean} [logged_in_status]
* @property {number} [date]
* @property {any} [more_data]
*/
/**
* @typedef {object} AuthenticatedUser
* @property {boolean} success - Did the function run successfully?
* @property {import("../types/user.td").DATASQUIREL_LoggedInUser | null} payload - Payload of the response
* @property {string} [msg] - An optional message
* @property {number} [userId] - An optional message
*/
/**
* @typedef {object} SuccessUserObject
* @property {number} id
* @property {string} first_name
* @property {string} last_name
* @property {string} email
*/
/**
* @typedef {object} AddUserFunctionReturn
* @property {boolean} success - Did the function run successfully?
* @property {SuccessUserObject | null} [payload] - Payload
* @property {string} [msg]
* @property {any} [sqlResult]
*/
/**
* @typedef {object} GoogleIdentityPromptNotification
* @property {function(): string} getMomentType - Notification moment type
* @property {function(): string} getDismissedReason - Notification get Dismissed Reason
* @property {function(): string} getNotDisplayedReason - Notification get Not Displayed Reason
* @property {function(): string} getSkippedReason - Notification get Skipped Reason
* @property {function(): boolean} isDismissedMoment - Notification is Dismissed Moment
* @property {function(): boolean} isDisplayMoment - Notification is Display Moment
* @property {function(): boolean} isDisplayed - Notification is Displayed
* @property {function(): boolean} isNotDisplayed - Notification is Not Displayed
* @property {function(): boolean} isSkippedMoment - Notification is Skipped Moment
*/
/**
* @typedef {object} UserDataPayload
* @property {string} first_name - First Name *Required
* @property {string} last_name - Last Name *Required
* @property {string} email - Email *Required
* @property {string} password - Password *Required
* @property {string?} username - Username (Optional)
*/
/**
* @typedef {object} GetUserFunctionReturn
* @property {boolean} success - Did the function run successfully?
* @property {{
* id: number,
* first_name: string,
* last_name: string,
* username: string,
* email: string,
* phone: string,
* social_id: [string],
* image: string,
* image_thumbnail: string,
* verification_status: [number=0],
* }} payload - Payload
*/
/**
* @typedef {object} ReauthUserFunctionReturn
* @property {boolean} success - Did the function run successfully?
* @property {import("../types/user.td").DATASQUIREL_LoggedInUser | null} payload - Payload
* @property {string} [msg] - Response Message
* @property {number} [userId] - user ID
* @property {string} [token] - new Token
*/
/**
* @typedef {object} UpdateUserFunctionReturn
* @property {boolean} success - Did the function run successfully?
* @property {(Object[]|string)} [payload=[]] - Payload
*/
module.exports = {
DATASQUIREL_LoggedInUser,
AuthenticatedUser,
AddUserFunctionReturn,
SuccessUserObject,
GoogleIdentityPromptNotification,
UserDataPayload,
GetUserFunctionReturn,
ReauthUserFunctionReturn,
UpdateUserFunctionReturn,
};

View File

@ -26,11 +26,11 @@ const localAddUser = require("../engine/user/add-user");
* @param {object} props - Single object passed
* @param {string} props.key - FULL ACCESS API Key
* @param {string} props.database - Database Name
* @param {import("../types/user.td").UserDataPayload} props.payload - User Data Payload
* @param {import("../package-shared/types").UserDataPayload} props.payload - User Data Payload
* @param {string} props.encryptionKey
* @param {string} [props.encryptionSalt]
*
* @returns { Promise<import("../types/user.td").AddUserFunctionReturn> }
* @returns { Promise<import("../package-shared/types").AddUserFunctionReturn> }
*/
async function addUser({
key,
@ -64,7 +64,7 @@ async function addUser({
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {

View File

@ -83,7 +83,7 @@ async function getUser({ key, userId, database, fields }) {
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {

View File

@ -41,7 +41,7 @@ const loginLocalUser = require("../engine/user/login-user");
* @param {string} [params.temp_code_field] - Database table field name for temporary code
* @param {boolean} [params.token] - Send access key as part of response body?
*
* @returns { Promise<import("../types/user.td").AuthenticatedUser>}
* @returns { Promise<import("../package-shared/types").AuthenticatedUser>}
*/
async function loginUser({
key,
@ -126,7 +126,7 @@ async function loginUser({
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {
@ -154,10 +154,10 @@ async function loginUser({
*
* @description make a request to datasquirel.com
*
* @type {{ success: boolean, payload: import("../types/user.td").DATASQUIREL_LoggedInUser | null, userId?: number, msg?: string }}
* @type {{ success: boolean, payload: import("../package-shared/types").DATASQUIREL_LoggedInUser | null, userId?: number, msg?: string }}
*/
httpResponse = await new Promise((resolve, reject) => {
/** @type {PackageUserLoginRequestBody} */
/** @type {import("../package-shared/types").PackageUserLoginRequestBody} */
const reqPayload = {
encryptionKey,
payload,

View File

@ -38,7 +38,7 @@ const localReauthUser = require("../engine/user/reauth-user");
* @param {string[]} [params.additionalFields] - Additional Fields to be added to the user object
* @param {string} [params.token] - access token to use instead of getting from cookie header
*
* @returns { Promise<import("../types/user.td").ReauthUserFunctionReturn> }
* @returns { Promise<import("../package-shared/types").ReauthUserFunctionReturn> }
*/
async function reauthUser({
key,
@ -103,7 +103,7 @@ async function reauthUser({
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {

View File

@ -114,7 +114,7 @@ async function sendEmailCode({
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {
@ -143,7 +143,7 @@ async function sendEmailCode({
*
* @description make a request to datasquirel.com
*
* @type {{ success: boolean, payload: import("../types/user.td").DATASQUIREL_LoggedInUser | null, userId?: number, msg?: string }}
* @type {{ success: boolean, payload: import("../package-shared/types").DATASQUIREL_LoggedInUser | null, userId?: number, msg?: string }}
*/
httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({

View File

@ -154,7 +154,7 @@ async function githubAuth({
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined | undefined} */
/** @type {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined | undefined} */
let dbSchema;
try {

View File

@ -150,7 +150,7 @@ async function googleAuth({
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined | undefined} */
/** @type {import("../../package-shared/types").DSQL_DatabaseSchemaType | undefined | undefined} */
let dbSchema;
try {
@ -179,7 +179,7 @@ async function googleAuth({
* Make https request
*
* @description make a request to datasquirel.com
* @type {{ success: boolean, user: import("../../types/user.td").DATASQUIREL_LoggedInUser | null, msg?: string, dsqlUserId?: number } | null } - Https response object
* @type {{ success: boolean, user: import("../../package-shared/types").DATASQUIREL_LoggedInUser | null, msg?: string, dsqlUserId?: number } | null } - Https response object
*/
httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({

View File

@ -27,9 +27,9 @@ 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("../types/user.td").UpdateUserFunctionReturn>}
* @returns { Promise<import("../package-shared/types").UpdateUserFunctionReturn>}
*/
async function updateUser({ key, payload, database }) {
/**
@ -57,7 +57,7 @@ async function updateUser({ key, payload, database }) {
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {

View File

@ -30,7 +30,7 @@ const parseCookies = require("../utils/functions/parseCookies");
* @param {string} params.database - Database Name
* @param {string} [params.token] - access token to use instead of getting from cookie header
*
* @returns { import("../types/user.td").AuthenticatedUser }
* @returns { import("../package-shared/types").AuthenticatedUser }
*/
function userAuth({
request,

View File

@ -27,7 +27,7 @@ const decrypt = require("../functions/decrypt");
* @param {("deep" | "normal")?} [params.level] - Optional. "Deep" value indicates an extra layer of security
* @param {string} params.database - Database Name
*
* @returns { import("../types/user.td").DATASQUIREL_LoggedInUser | null}
* @returns { import("../package-shared/types").DATASQUIREL_LoggedInUser | null}
*/
function validateToken({ token, encryptionKey, encryptionSalt }) {
try {

View File

@ -39,6 +39,12 @@ async function uploadImage({ key, url }) {
const scheme = process.env.DSQL_HTTP_SCHEME;
const localHost = process.env.DSQL_LOCAL_HOST;
const localHostPort = process.env.DSQL_LOCAL_HOST_PORT;
const remoteHost = process.env.DSQL_API_REMOTE_HOST?.match(/.*\..*/)
? process.env.DSQL_API_REMOTE_HOST
: undefined;
const remoteHostPort = process.env.DSQL_API_REMOTE_HOST_PORT?.match(/./)
? process.env.DSQL_API_REMOTE_HOST_PORT
: undefined;
try {
/**
@ -59,8 +65,8 @@ async function uploadImage({ key, url }) {
"Content-Length": Buffer.from(reqPayload).length,
Authorization: key,
},
port: localHostPort || 443,
hostname: localHost || "datasquirel.com",
port: remoteHostPort || localHostPort || 443,
hostname: remoteHost || localHost || "datasquirel.com",
path: `/api/query/delete-file`,
},

View File

@ -0,0 +1,18 @@
// @ts-check
/** @type {import("../../package-shared/types").SerializeQueryFnType} */
function serializeQuery({ query }) {
let str = "?";
const keys = Object.keys(query);
/** @type {string[]} */
const queryArr = [];
keys.forEach((key) => {
if (!key || !query[key]) return;
queryArr.push(`${key}=${query[key]}`);
});
str += queryArr.join("&");
return str;
}
module.exports = serializeQuery;

View File

@ -18,24 +18,25 @@ const https = require("https");
/**
* @typedef {Object} GetSchemaReturn
* @property {boolean} success - Did the function run successfully?
* @property {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType[] | import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | null} payload - Response payload
* @property {import("../package-shared/types").DSQL_DatabaseSchemaType | import("../package-shared/types").DSQL_TableSchemaType | import("../package-shared/types").DSQL_FieldSchemaType | null} payload - Response payload
*/
/**
* Make a get request to Datasquirel API
* ==============================================================================
* @async
*
* @param {Object} params - Single object passed
* @param {string} params.key - `FULL ACCESS` API Key
* @param {string} [params.database] - The database schema to get
* # Get Schema for Database, table, or field *
* @param {import("../package-shared/types").GetSchemaAPIParam} params
*
* @returns { Promise<GetSchemaReturn> } - Return Object
*/
async function getSchema({ key, database }) {
async function getSchema({ key, database, field, table }) {
const scheme = process.env.DSQL_HTTP_SCHEME;
const localHost = process.env.DSQL_LOCAL_HOST;
const localHostPort = process.env.DSQL_LOCAL_HOST_PORT;
const remoteHost = process.env.DSQL_API_REMOTE_HOST?.match(/.*\..*/)
? process.env.DSQL_API_REMOTE_HOST
: undefined;
const remoteHostPort = process.env.DSQL_API_REMOTE_HOST_PORT?.match(/./)
? process.env.DSQL_API_REMOTE_HOST_PORT
: undefined;
/**
* Make https request
@ -43,6 +44,15 @@ async function getSchema({ key, database }) {
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
/** @type {import("../package-shared/types").GetSchemaRequestQuery} */
const queryObject = { database, field, table };
let query = Object.keys(queryObject)
// @ts-ignore
.filter((k) => queryObject[k])
// @ts-ignore
.map((k) => `${k}=${queryObject[k]}`)
.join("&");
(scheme?.match(/^http$/i) ? http : https)
.request(
{
@ -51,11 +61,11 @@ async function getSchema({ key, database }) {
"Content-Type": "application/json",
Authorization: key,
},
port: localHostPort || 443,
hostname: localHost || "datasquirel.com",
port: remoteHostPort || localHostPort || 443,
hostname: remoteHost || localHost || "datasquirel.com",
path:
"/api/query/get-schema" +
(database ? `?database=${database}` : ""),
(query?.match(/./) ? `?${query}` : ""),
},
/**

View File

@ -10,6 +10,7 @@ const https = require("node:https");
const path = require("path");
const fs = require("fs");
const localGet = require("../engine/query/get");
const serializeQuery = require("./functions/serialize-query");
/** ****************************************************************************** */
/** ****************************************************************************** */
@ -18,14 +19,6 @@ const localGet = require("../engine/query/get");
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* @typedef {Object} GetReturn
* @property {boolean} success - Did the function run successfully?
* @property {*} [payload] - GET request results
* @property {string} [msg] - Message
* @property {string} [error] - Error Message
*/
/**
* Make a get request to Datasquirel API
* ==============================================================================
@ -38,35 +31,34 @@ const localGet = require("../engine/query/get");
* @param {string[]} [params.queryValues] - An array of query values if using "?" placeholders
* @param {string} [params.tableName] - Name of the table to query
*
* @returns { Promise<GetReturn> } - Return Object
* @returns { Promise<import("../package-shared/types").GetReturn> } - Return Object
*/
async function get({ key, db, query, queryValues, tableName }) {
const scheme = process.env.DSQL_HTTP_SCHEME;
const localHost = process.env.DSQL_LOCAL_HOST;
const localHostPort = process.env.DSQL_LOCAL_HOST_PORT;
const remoteHost = process.env.DSQL_API_REMOTE_HOST?.match(/.*\..*/)
? process.env.DSQL_API_REMOTE_HOST
: undefined;
const remoteHostPort = process.env.DSQL_API_REMOTE_HOST_PORT?.match(/./)
? process.env.DSQL_API_REMOTE_HOST_PORT
: undefined;
/**
* Check for local DB settings
*
* @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_NAME,
DSQL_KEY,
DSQL_REF_DB_NAME,
DSQL_FULL_SYNC,
} = process.env;
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_HOST?.match(/./) &&
DSQL_USER?.match(/./) &&
DSQL_PASS?.match(/./) &&
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {
@ -93,16 +85,22 @@ async function get({ key, db, query, queryValues, tableName }) {
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
let path = `/api/query/get?db=${db}&query=${query
.replace(/\n|\r|\n\r/g, "")
.replace(/ {2,}/g, " ")
.replace(/ /g, "+")}`;
/** @type {import("../package-shared/types").GetReqQueryObject} */
const queryObject = {
db: String(db),
query: String(
query
.replace(/\n|\r|\n\r/g, "")
.replace(/ {2,}/g, " ")
.replace(/ /g, "+")
),
queryValues: queryValues ? JSON.stringify(queryValues) : undefined,
tableName,
};
if (queryValues) {
path += `&queryValues=${JSON.stringify(queryValues)}${
tableName ? `&tableName=${tableName}` : ""
}`;
}
const queryString = serializeQuery({ query: queryObject });
let path = `/api/query/get${queryString}`;
/** @type {https.RequestOptions} */
const requestObject = {
@ -111,8 +109,8 @@ async function get({ key, db, query, queryValues, tableName }) {
"Content-Type": "application/json",
Authorization: key,
},
port: localHostPort || 443,
hostname: localHost || "datasquirel.com",
port: remoteHostPort || localHostPort || 443,
hostname: remoteHost || localHost || "datasquirel.com",
path: encodeURI(path),
};

View File

@ -16,28 +16,6 @@ const localPost = require("../engine/query/post");
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* @typedef {Object} PostReturn
* @property {boolean} success - Did the function run successfully?
* @property {(Object[]|string)} [payload=[]] - The Y Coordinate
*/
/**
* @typedef {object} PostDataPayload
* @property {"insert" | "update" | "delete"} action - The target action to take
* @property {string} table - Table name(slug) eg "blog_posts"
* @property {object} [data] - Table insert payload object => This must have keys that match
* table fields
* @property {string?} [identifierColumnName] - Table identifier field name => eg. "id" OR "email"
* @property {string?} [identifierValue] - Corresponding value of the selected field name => This
* checks identifies a the target row for "update" or "delete". Not needed for "insert"
* @property {string?} [duplicateColumnName] - Duplicate column name to check for
* @property {string?} [duplicateColumnValue] - Duplicate column value to match. If no "update" param
* provided, function will return null
* @property {boolean?} [update] - Should the "insert" action update the existing entry if indeed
* the entry with "duplicateColumnValue" exists?
*/
/**
* Make a post request to Datasquirel API
* ==============================================================================
@ -46,16 +24,22 @@ const localPost = require("../engine/query/post");
* @param {Object} params - Single object passed
* @param {string} [params.key] - FULL ACCESS API Key
* @param {string} [params.database] - Database Name
* @param {PostDataPayload | string} params.query - SQL query String or Request Object
* @param {import("../package-shared/types").PostDataPayload | string} params.query - SQL query String or Request Object
* @param {any[]} [params.queryValues] - Query Values if using "?" placeholders
* @param {string} [params.tableName] - Name of the table to query
*
* @returns { Promise<PostReturn> } - Return Object
* @returns { Promise<import("../package-shared/types").PostReturn> } - Return Object
*/
async function post({ key, query, queryValues, database, tableName }) {
const scheme = process.env.DSQL_HTTP_SCHEME;
const localHost = process.env.DSQL_LOCAL_HOST;
const localHostPort = process.env.DSQL_LOCAL_HOST_PORT;
const remoteHost = process.env.DSQL_API_REMOTE_HOST?.match(/.*\..*/)
? process.env.DSQL_API_REMOTE_HOST
: undefined;
const remoteHostPort = process.env.DSQL_API_REMOTE_HOST_PORT?.match(/./)
? process.env.DSQL_API_REMOTE_HOST_PORT
: undefined;
/**
* Check for local DB settings
@ -78,7 +62,7 @@ async function post({ key, query, queryValues, database, tableName }) {
DSQL_PASS?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("@/package-shared/types/database-schema.td").DSQL_DatabaseSchemaType | undefined} */
/** @type {import("../package-shared/types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema;
try {
@ -135,8 +119,8 @@ async function post({ key, query, queryValues, database, tableName }) {
"Content-Length": Buffer.from(reqPayload).length,
Authorization: key,
},
port: localHostPort || 443,
hostname: localHost || "datasquirel.com",
port: remoteHostPort || localHostPort || 443,
hostname: remoteHost || localHost || "datasquirel.com",
path: `/api/query/post`,
},

View File

@ -46,6 +46,12 @@ async function uploadImage({ key, payload }) {
const scheme = process.env.DSQL_HTTP_SCHEME;
const localHost = process.env.DSQL_LOCAL_HOST;
const localHostPort = process.env.DSQL_LOCAL_HOST_PORT;
const remoteHost = process.env.DSQL_API_REMOTE_HOST?.match(/.*\..*/)
? process.env.DSQL_API_REMOTE_HOST
: undefined;
const remoteHostPort = process.env.DSQL_API_REMOTE_HOST_PORT?.match(/./)
? process.env.DSQL_API_REMOTE_HOST_PORT
: undefined;
try {
/**
@ -66,8 +72,8 @@ async function uploadImage({ key, payload }) {
"Content-Length": Buffer.from(reqPayload).length,
Authorization: key,
},
port: localHostPort || 443,
hostname: localHost || "datasquirel.com",
port: remoteHostPort || localHostPort || 443,
hostname: remoteHost || localHost || "datasquirel.com",
path: `/api/query/add-file`,
},

View File

@ -48,6 +48,12 @@ async function uploadImage({ key, payload }) {
const scheme = process.env.DSQL_HTTP_SCHEME;
const localHost = process.env.DSQL_LOCAL_HOST;
const localHostPort = process.env.DSQL_LOCAL_HOST_PORT;
const remoteHost = process.env.DSQL_API_REMOTE_HOST?.match(/.*\..*/)
? process.env.DSQL_API_REMOTE_HOST
: undefined;
const remoteHostPort = process.env.DSQL_API_REMOTE_HOST_PORT?.match(/./)
? process.env.DSQL_API_REMOTE_HOST_PORT
: undefined;
try {
/**
@ -68,8 +74,8 @@ async function uploadImage({ key, payload }) {
"Content-Length": Buffer.from(reqPayload).length,
Authorization: key,
},
port: localHostPort || 443,
hostname: localHost || "datasquirel.com",
port: remoteHostPort || localHostPort || 443,
hostname: remoteHost || localHost || "datasquirel.com",
path: `/api/query/add-image`,
},