This commit is contained in:
Benjamin Toby
2025-01-28 19:43:16 +01:00
parent 81cf010cb5
commit 35fec57590
856 changed files with 5362 additions and 2266 deletions
@@ -0,0 +1,92 @@
import grabHostNames from "../utils/grab-host-names";
interface Return {
success: boolean;
payload: {
urlPath: string;
urlThumbnailPath: string;
} | null;
msg?: string;
}
type Param = {
key: string;
url: string;
user_id?: string | number;
};
/**
* # Delete File via API
*/
export default async function deleteFile({
key,
url,
user_id,
}: Param): Promise<Return> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
try {
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({ url: url });
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/query/${
user_id || grabedHostNames.user_id
}/delete-file`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
return httpResponse as Return;
} catch (/** @type {*} */ error: any) {
console.log("Error deleting file: ", error.message);
return {
success: false,
payload: null,
msg: error.message,
};
}
}
@@ -0,0 +1,3 @@
export default function getCsrfHeaderName() {
return "x-csrf-key";
}
@@ -0,0 +1,93 @@
import grabHostNames from "../utils/grab-host-names";
import {
DSQL_DatabaseSchemaType,
DSQL_FieldSchemaType,
DSQL_TableSchemaType,
GetSchemaAPIParam,
GetSchemaRequestQuery,
} from "../types";
type GetSchemaReturn = {
success: boolean;
payload?:
| DSQL_DatabaseSchemaType
| DSQL_TableSchemaType
| DSQL_FieldSchemaType
| null;
};
/**
* # Get Schema for Database, table, or field *
*/
export default async function getSchema({
key,
database,
field,
table,
user_id,
}: GetSchemaAPIParam): Promise<GetSchemaReturn> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const queryObject: GetSchemaRequestQuery = { database, field, table };
let query = Object.keys(queryObject)
.filter((k) => queryObject[k as keyof GetSchemaRequestQuery])
.map((k) => `${k}=${queryObject[k as keyof GetSchemaRequestQuery]}`)
.join("&");
scheme
.request(
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path:
`/api/query/${
user_id || grabedHostNames.user_id
}/get-schema` + (query?.match(/./) ? `?${query}` : ""),
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(
JSON.parse(str) as
| DSQL_DatabaseSchemaType
| DSQL_TableSchemaType
| DSQL_FieldSchemaType
);
});
response.on("error", (err) => {
resolve(null);
});
}
)
.end();
});
return httpResponse as GetSchemaReturn;
}
+173
View File
@@ -0,0 +1,173 @@
import https from "node:https";
import path from "path";
import fs from "fs";
import grabHostNames from "../utils/grab-host-names";
import apiGet from "../functions/api/query/get";
import serializeQuery from "../utils/serialize-query";
import {
ApiGetQueryObject,
DSQL_DatabaseSchemaType,
GetReqQueryObject,
GetReturn,
ServerQueryParam,
} from "../types";
import apiGetGrabQueryAndValues from "../utils/grab-query-and-values";
type Param<T extends { [k: string]: any } = { [k: string]: any }> = {
key?: string;
db?: string;
query: string | ApiGetQueryObject<T>;
queryValues?: string[];
tableName?: string;
user_id?: string | number;
debug?: boolean;
};
export type ApiGetParams = Param;
/**
* # Make a get request to Datasquirel API
*/
export default async function get<
T extends { [k: string]: any } = { [k: string]: any }
>({
key,
db,
query,
queryValues,
tableName,
user_id,
debug,
}: Param<T>): Promise<GetReturn> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
let dbSchema: DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
if (debug) {
console.log("apiGet:Running Locally ...");
}
return await apiGet({
dbFullName: DSQL_DB_NAME,
query,
queryValues,
tableName,
dbSchema,
debug,
});
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const queryAndValues = apiGetGrabQueryAndValues({
query,
values: queryValues,
});
const queryObject: GetReqQueryObject = {
db: process.env.DSQL_API_DB_NAME || String(db),
query: queryAndValues.query,
queryValues: queryAndValues.valuesString,
tableName,
debug,
};
if (debug) {
console.log("apiGet:queryObject", queryObject);
}
const queryString = serializeQuery({ ...queryObject });
if (debug) {
console.log("apiGet:queryString", queryString);
}
let path = `/api/query/${
user_id || grabedHostNames.user_id
}/get${queryString}`;
if (debug) {
console.log("apiGet:path", path);
}
const requestObject: https.RequestOptions = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization:
key ||
process.env.DSQL_READ_ONLY_API_KEY ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path,
};
scheme
.request(
requestObject,
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
try {
resolve(JSON.parse(str) as GetReturn);
} catch (/** @type {any} */ error: any) {
reject({
error: error.message,
result: str,
});
}
});
response.on("error", (err) => {
console.log("DSQL get Error,", err.message);
resolve(null);
});
}
)
.end();
});
return httpResponse as GetReturn;
}
+162
View File
@@ -0,0 +1,162 @@
// @ts-check
import path from "path";
import fs from "fs";
import grabHostNames from "../utils/grab-host-names";
import apiPost from "../functions/api/query/post";
import { PostDataPayload, PostReturn } from "../types";
type Param = {
key?: string;
database?: string;
query: string | PostDataPayload;
queryValues?: any[];
tableName?: string;
user_id?: boolean;
};
/**
* # Make a post request to Datasquirel API
*/
export default async function post({
key,
query,
queryValues,
database,
tableName,
user_id,
}: Param): Promise<PostReturn> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
/** @type {import("../types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema: import("../types").DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
return await apiPost({
dbFullName: DSQL_DB_NAME,
query,
dbSchema,
queryValues,
tableName,
});
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const reqPayloadString = JSON.stringify({
query,
queryValues,
database: process.env.DSQL_API_DB_NAME || database,
tableName: tableName ? tableName : null,
}).replace(/\n|\r|\n\r/gm, "");
try {
JSON.parse(reqPayloadString);
} catch (error) {
console.log(error);
console.log(reqPayloadString);
return {
success: false,
payload: null,
error: "Query object is invalid. Please Check query data values",
};
}
const reqPayload = reqPayloadString;
const requPath = `/api/query/${
user_id || grabedHostNames.user_id
}/post`;
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: requPath,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
try {
resolve(JSON.parse(str));
} catch (/** @type {any} */ error: any) {
console.log("Route ERROR:", error.message);
resolve({
success: false,
payload: null,
error: error.message,
errPayload: str,
});
}
});
response.on("error", (err) => {
resolve({
success: false,
payload: null,
error: err.message,
});
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.on("error", (error) => {
console.log("HTTPS request ERROR =>", error);
});
httpsRequest.end();
});
return httpResponse as PostReturn;
}
@@ -0,0 +1,97 @@
import grabHostNames from "../utils/grab-host-names";
interface Return {
success: boolean;
payload: {
urlPath: string;
} | null;
msg?: string;
}
type Param = {
key: string;
payload: {
fileData: string;
fileName: string;
mimeType?: string;
folder?: string;
isPrivate?: boolean;
};
user_id?: boolean;
};
/**
* # Upload File via API
*/
export default async function uploadImage({
key,
payload,
user_id,
}: Param): Promise<Return> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
try {
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify(payload);
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/query/${
user_id || grabedHostNames.user_id
}/add-file`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
return httpResponse as Return;
} catch (error: any) {
console.log("Error in uploading file: ", error.message);
return {
success: false,
payload: null,
msg: error.message,
};
}
}
@@ -0,0 +1,101 @@
// @ts-check
import grabHostNames from "../utils/grab-host-names";
interface FunctionReturn {
success: boolean;
payload: {
urlPath: string;
urlThumbnailPath: string;
} | null;
msg?: string;
}
type Param = {
key?: string;
payload: {
imageData: string;
imageName: string;
mimeType?: string;
thumbnailSize?: number;
folder?: string;
isPrivate?: boolean;
};
user_id?: boolean;
};
/**
* # Upload Image via API
*/
export default async function uploadImage({
key,
payload,
user_id,
}: Param): Promise<FunctionReturn> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
try {
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify(payload);
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/query/${
user_id || grabedHostNames.user_id
}/add-image`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
return httpResponse as FunctionReturn;
} catch (error: any) {
console.log("Error in uploading image: ", error.message);
return {
success: false,
payload: null,
msg: error.message,
};
}
}
@@ -0,0 +1,126 @@
import path from "path";
import fs from "fs";
import grabHostNames from "../../utils/grab-host-names";
import apiCreateUser from "../../functions/api/users/api-create-user";
import { AddUserFunctionReturn, UserDataPayload } from "../../types";
type Param = {
key?: string;
database?: string;
payload: UserDataPayload;
encryptionKey?: string;
encryptionSalt?: string;
user_id?: string | number;
apiUserId?: string | number;
};
/**
* # Add User to Database
*/
export default async function addUser({
key,
payload,
database,
encryptionKey,
user_id,
apiUserId,
}: Param): Promise<AddUserFunctionReturn> {
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const {
DSQL_DB_HOST,
DSQL_DB_USERNAME,
DSQL_DB_PASSWORD,
DSQL_DB_NAME,
DSQL_API_USER_ID,
} = process.env;
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
/** @type {import("../../types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema: import("../../types").DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
return await apiCreateUser({
database: DSQL_DB_NAME,
encryptionKey,
payload,
userId: apiUserId,
});
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({
payload,
database,
encryptionKey,
});
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/user/${
user_id || grabedHostNames.user_id
}/add-user`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
return httpResponse as AddUserFunctionReturn;
}
@@ -0,0 +1,113 @@
import path from "path";
import fs from "fs";
import grabHostNames from "../../utils/grab-host-names";
import apiDeleteUser from "../../functions/api/users/api-delete-user";
import { UpdateUserFunctionReturn } from "../../types";
type Param = {
key?: string;
database?: string;
deletedUserId: string | number;
user_id?: boolean;
};
/**
* # Update User
*/
export default async function deleteUser({
key,
database,
user_id,
deletedUserId,
}: Param): Promise<UpdateUserFunctionReturn> {
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
/** @type {import("../../types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema: import("../../types").DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
return await apiDeleteUser({
dbFullName: DSQL_DB_NAME,
deletedUserId,
});
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = (await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({
database,
deletedUserId,
});
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY ||
key,
},
port,
hostname: host,
path: `/api/user/${
user_id || grabedHostNames.user_id
}/delete-user`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
})) as UpdateUserFunctionReturn;
return httpResponse;
}
@@ -0,0 +1,93 @@
import http from "http";
import decrypt from "../../functions/dsql/decrypt";
import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names";
import parseCookies from "../../utils/backend/parseCookies";
type Param = {
request?: http.IncomingMessage;
cookieString?: string;
encryptionKey: string;
encryptionSalt: string;
database: string;
};
type Return = {
key: string | undefined;
csrf: string | undefined;
};
/**
* Get just the access token for user
* ==============================================================================
* @description This Function takes in a request object and returns a user token
* string and csrf token string
*/
export default function getToken({
request,
encryptionKey,
encryptionSalt,
cookieString,
}: Param): Return {
try {
/**
* Grab the payload
*
* @description Grab the payload
*/
const cookies = parseCookies({ request, cookieString });
const keynames = getAuthCookieNames();
const authKeyName = keynames.keyCookieName;
const csrfName = keynames.csrfCookieName;
const key = cookies[authKeyName];
const csrf = cookies[csrfName];
/**
* Grab the payload
*
* @description Grab the payload
*/
let userPayload = decrypt({
encryptedString: key,
encryptionKey,
encryptionSalt,
});
/**
* Grab the payload
*
* @description Grab the payload
*/
if (!userPayload) {
return { key: undefined, csrf: undefined };
}
/**
* Grab the payload
*
* @description Grab the payload
*/
let userObject = JSON.parse(userPayload);
if (!userObject.csrf_k) {
return { key: undefined, csrf: undefined };
}
/**
* Return User Object
*
* @description Return User Object
*/
return { key, csrf };
} catch (error) {
/**
* Return User Object
*
* @description Return User Object
*/
return {
key: undefined,
csrf: undefined,
};
}
}
@@ -0,0 +1,145 @@
import path from "path";
import fs from "fs";
import grabHostNames from "../../utils/grab-host-names";
import apiGetUser from "../../functions/api/users/api-get-user";
import { GetUserFunctionReturn } from "../../types";
type Param = {
key: string;
database: string;
userId: number;
fields?: string[];
apiUserId?: boolean;
};
/**
* # Get User
*/
export default async function getUser({
key,
userId,
database,
fields,
apiUserId,
}: Param): Promise<GetUserFunctionReturn> {
/**
* Initialize
*/
const defaultFields = [
"id",
"first_name",
"last_name",
"email",
"username",
"image",
"image_thumbnail",
"verification_status",
"date_created",
"date_created_code",
"date_created_timestamp",
"date_updated",
"date_updated_code",
"date_updated_timestamp",
];
const updatedFields =
fields && fields[0] ? [...defaultFields, ...fields] : defaultFields;
const reqPayload = JSON.stringify({
userId,
database,
fields: [...new Set(updatedFields)],
});
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
/** @type {import("../../types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema: import("../../types").DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
return await apiGetUser({
userId,
fields: [...new Set(updatedFields)],
dbFullName: DSQL_DB_NAME,
});
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/user/${
apiUserId || grabedHostNames.user_id
}/get-user`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
return httpResponse as GetUserFunctionReturn;
}
@@ -0,0 +1,263 @@
import http from "http";
import fs from "fs";
import path from "path";
import encrypt from "../../functions/dsql/encrypt";
import grabHostNames from "../../utils/grab-host-names";
import apiLoginUser from "../../functions/api/users/api-login";
import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names";
import { writeAuthFile } from "../../functions/backend/auth/write-auth-files";
import {
APILoginFunctionReturn,
DSQL_DatabaseSchemaType,
PackageUserLoginRequestBody,
} from "../../types";
type Param = {
key?: string;
database: string;
payload: {
email?: string;
username?: string;
password?: string;
};
additionalFields?: string[];
response?: http.ServerResponse & { [s: string]: any };
encryptionKey?: string;
encryptionSalt?: string;
email_login?: boolean;
email_login_code?: string;
temp_code_field?: string;
token?: boolean;
user_id?: string | number;
skipPassword?: boolean;
debug?: boolean;
skipWriteAuthFile?: boolean;
apiUserID?: string | number;
dbUserId?: string | number;
};
/**
* # Login A user
*/
export default async function loginUser({
key,
payload,
database,
additionalFields,
response,
encryptionKey,
encryptionSalt,
email_login,
email_login_code,
temp_code_field,
token,
user_id,
skipPassword,
apiUserID,
skipWriteAuthFile,
dbUserId,
debug,
}: Param): Promise<APILoginFunctionReturn> {
const grabedHostNames = grabHostNames({ userId: user_id || apiUserID });
const { host, port, scheme } = grabedHostNames;
const defaultTempLoginFieldName = "temp_login_code";
const emailLoginTempCodeFieldName = email_login
? temp_code_field
? temp_code_field
: defaultTempLoginFieldName
: undefined;
const finalEncryptionKey =
encryptionKey || process.env.DSQL_ENCRYPTION_PASSWORD;
const finalEncryptionSalt =
encryptionSalt || process.env.DSQL_ENCRYPTION_SALT;
if (!finalEncryptionKey?.match(/.{8,}/)) {
console.log("Encryption key is invalid");
return {
success: false,
payload: null,
msg: "Encryption key is invalid",
};
}
if (!finalEncryptionSalt?.match(/.{8,}/)) {
console.log("Encryption salt is invalid");
return {
success: false,
payload: null,
msg: "Encryption salt is invalid",
};
}
/**
* Check required fields
*
* @description Check required fields
*/
if (!payload.email) {
return {
success: false,
payload: null,
msg: "Email Required",
};
}
/**
* Initialize HTTP response variable
*/
/** @type {import("../../types").APILoginFunctionReturn} */
let httpResponse: import("../../types").APILoginFunctionReturn = {
success: false,
};
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
let dbSchema: DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
httpResponse = await apiLoginUser({
database: process.env.DSQL_DB_NAME || "",
email: payload.email,
username: payload.username,
password: payload.password,
skipPassword,
encryptionKey: finalEncryptionKey,
additionalFields,
email_login,
email_login_code,
email_login_field: emailLoginTempCodeFieldName,
token,
dbUserId,
debug,
});
} else {
httpResponse = await new Promise((resolve, reject) => {
const reqPayload: PackageUserLoginRequestBody = {
encryptionKey: finalEncryptionKey,
payload,
database,
additionalFields,
email_login,
email_login_code,
email_login_field: emailLoginTempCodeFieldName,
token,
skipPassword: skipPassword,
dbUserId: dbUserId || 0,
};
const reqPayloadJSON = JSON.stringify(reqPayload);
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayloadJSON).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/user/${
user_id || grabedHostNames.user_id
}/login-user`,
},
(res) => {
var str = "";
res.on("data", function (chunk) {
str += chunk;
});
res.on("end", function () {
resolve(JSON.parse(str));
});
res.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayloadJSON);
httpsRequest.end();
});
}
if (debug) {
console.log(`loginUser:httpResponse:`, httpResponse);
}
if (httpResponse?.success) {
let encryptedPayload = encrypt({
data: JSON.stringify(httpResponse.payload),
encryptionKey: finalEncryptionKey,
encryptionSalt: finalEncryptionSalt,
});
try {
if (token && encryptedPayload)
httpResponse["token"] = encryptedPayload;
} catch (error) {}
const cookieNames = getAuthCookieNames({
database,
userId: grabedHostNames.user_id,
});
if (httpResponse.csrf && !skipWriteAuthFile) {
writeAuthFile(
httpResponse.csrf,
JSON.stringify(httpResponse.payload)
);
}
httpResponse["cookieNames"] = cookieNames;
httpResponse["key"] = String(encryptedPayload);
const authKeyName = cookieNames.keyCookieName;
const csrfName = cookieNames.csrfCookieName;
if (debug) {
console.log(`loginUser:authKeyName:`, authKeyName);
console.log(`loginUser:csrfName:`, csrfName);
console.log(`loginUser:encryptedPayload:`, encryptedPayload);
}
response?.setHeader("Set-Cookie", [
`${authKeyName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`,
`${csrfName}=${httpResponse.payload?.csrf_k};samesite=strict;path=/;HttpOnly=true`,
]);
if (debug) {
console.log(`loginUser:Response Sent!`);
}
}
return httpResponse;
}
@@ -0,0 +1,120 @@
import http from "http";
import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names";
import decrypt from "../../functions/dsql/decrypt";
import EJSON from "../../utils/ejson";
import { deleteAuthFile } from "../../functions/backend/auth/write-auth-files";
import parseCookies from "../../utils/backend/parseCookies";
import { DATASQUIREL_LoggedInUser } from "../../types";
import grabHostNames from "../../utils/grab-host-names";
type Param = {
encryptedUserString?: string;
request?: http.IncomingMessage & { [s: string]: any };
response?: http.ServerResponse & { [s: string]: any };
cookieString?: string;
database?: string;
dsqlUserId?: string | number;
debug?: boolean;
};
type Return = {
success: boolean;
msg: string;
cookieNames?: any;
};
/**
* # Logout user
*/
export default function logoutUser({
response,
database,
dsqlUserId,
encryptedUserString,
request,
cookieString,
debug,
}: Param): Return {
/**
* Check Encryption Keys
*
* @description Check Encryption Keys
*/
try {
const { user_id } = grabHostNames({ userId: dsqlUserId });
const cookieNames = getAuthCookieNames({
database,
userId: user_id,
});
if (debug) {
console.log("logoutUser:cookieNames", cookieNames);
}
const authKeyName = cookieNames.keyCookieName;
const csrfName = cookieNames.csrfCookieName;
const oneTimeCodeName = cookieNames.oneTimeCodeName;
const decryptedUserJSON: string | undefined = (() => {
try {
if (request) {
const cookiesObject = parseCookies({
request,
cookieString,
});
return decrypt({
encryptedString: cookiesObject[authKeyName],
});
} else if (encryptedUserString) {
return decrypt({
encryptedString: encryptedUserString,
});
} else {
return undefined;
}
} catch (/** @type {any} */ error: any) {
console.log(
"Error getting decrypted User JSON to logout:",
error.message
);
return undefined;
}
})();
if (debug) {
console.log("logoutUser:decryptedUserJSON", decryptedUserJSON);
}
if (!decryptedUserJSON) throw new Error("Invalid User");
const userObject = EJSON.parse(
decryptedUserJSON
) as DATASQUIREL_LoggedInUser;
if (!userObject?.csrf_k)
throw new Error("Invalid User. Please check key");
response?.setHeader("Set-Cookie", [
`${authKeyName}=null;max-age=0`,
`${csrfName}=null;max-age=0`,
`${oneTimeCodeName}=null;max-age=0`,
]);
const csrf = userObject.csrf_k;
deleteAuthFile(csrf);
return {
success: true,
msg: "User Logged Out",
cookieNames,
};
} catch (error: any) {
console.log("Logout Error:", error.message);
return {
success: false,
msg: "Logout Failed",
};
}
}
@@ -0,0 +1,205 @@
import http from "http";
import https from "https";
import fs from "fs";
import path from "path";
import encrypt from "../../functions/dsql/encrypt";
import userAuth from "./user-auth";
import grabHostNames from "../../utils/grab-host-names";
import apiReauthUser from "../../functions/api/users/api-reauth-user";
import {
writeAuthFile,
deleteAuthFile,
} from "../../functions/backend/auth/write-auth-files";
import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names";
import { APILoginFunctionReturn } from "../../types";
type Param = {
key?: string;
database?: string;
response?: http.ServerResponse;
request?: http.IncomingMessage;
level?: "deep" | "normal";
encryptionKey?: string;
encryptionSalt?: string;
additionalFields?: string[];
encryptedUserString?: string;
user_id?: string | number;
};
/**
* # Reauthorize User
*/
export default async function reauthUser({
key,
database,
response,
request,
level,
encryptionKey,
encryptionSalt,
additionalFields,
encryptedUserString,
user_id,
}: Param): Promise<APILoginFunctionReturn> {
/**
* Check Encryption Keys
*
* @description Check Encryption Keys
*/
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
const finalEncryptionKey =
encryptionKey || process.env.DSQL_ENCRYPTION_PASSWORD;
const finalEncryptionSalt =
encryptionSalt || process.env.DSQL_ENCRYPTION_SALT;
const existingUser = userAuth({
database,
encryptionKey: finalEncryptionKey,
encryptionSalt: finalEncryptionSalt,
level,
request,
encryptedUserString,
});
if (!existingUser?.payload?.id) {
return {
success: false,
payload: null,
msg: "Cookie Credentials Invalid",
};
}
/**
* Initialize HTTP response variable
*/
let httpResponse;
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
let dbSchema: import("../../types").DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
httpResponse = await apiReauthUser({
existingUser: existingUser.payload,
additionalFields,
});
} else {
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
httpResponse = (await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({
existingUser: existingUser.payload,
database,
additionalFields,
});
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/user/${
user_id || grabedHostNames.user_id
}/reauth-user`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
})) as APILoginFunctionReturn;
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
if (httpResponse?.success) {
let encryptedPayload = encrypt({
data: JSON.stringify(httpResponse.payload),
encryptionKey: finalEncryptionKey,
encryptionSalt: finalEncryptionSalt,
});
const cookieNames = getAuthCookieNames({
database,
userId: user_id || grabedHostNames.user_id,
});
httpResponse["cookieNames"] = cookieNames;
httpResponse["key"] = String(encryptedPayload);
const authKeyName = cookieNames.keyCookieName;
const csrfName = cookieNames.csrfCookieName;
response?.setHeader("Set-Cookie", [
`${authKeyName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`,
`${csrfName}=${httpResponse.payload?.csrf_k};samesite=strict;path=/;HttpOnly=true`,
]);
if (httpResponse.csrf) {
deleteAuthFile(String(existingUser.payload.csrf_k));
writeAuthFile(
httpResponse.csrf,
JSON.stringify(httpResponse.payload)
);
}
}
return httpResponse;
}
@@ -0,0 +1,157 @@
import http from "http";
import fs from "fs";
import path from "path";
import grabHostNames from "../../utils/grab-host-names";
import apiSendEmailCode from "../../functions/api/users/api-send-email-code";
import { SendOneTimeCodeEmailResponse } from "../../types";
type Param = {
key?: string;
database?: string;
email: string;
temp_code_field_name?: string;
response?: http.ServerResponse & { [s: string]: any };
mail_domain?: string;
mail_username?: string;
mail_password?: string;
mail_port?: number;
sender?: string;
user_id?: boolean;
extraCookies?: import("../../types").CookieObject[];
};
/**
* # Send Email Code to a User
*/
export default async function sendEmailCode({
key,
email,
database,
temp_code_field_name,
mail_domain,
mail_password,
mail_username,
mail_port,
sender,
user_id,
response,
extraCookies,
}: Param): Promise<SendOneTimeCodeEmailResponse> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
const defaultTempLoginFieldName = "temp_login_code";
const emailLoginTempCodeFieldName = temp_code_field_name
? temp_code_field_name
: defaultTempLoginFieldName;
const emailHtml = `<p>Please use this code to login</p>\n<h2>{{code}}</h2>\n<p>Please note that this code expires after 15 minutes</p>`;
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
/** @type {import("../../types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema: import("../../types").DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
return await apiSendEmailCode({
database: DSQL_DB_NAME,
email,
email_login_field: emailLoginTempCodeFieldName,
html: emailHtml,
mail_domain,
mail_password,
mail_port,
mail_username,
sender,
response,
extraCookies,
});
} else {
/**
* Make https request
*
* @description make a request to datasquirel.com
*
* @type {import("../../types").SendOneTimeCodeEmailResponse}
*/
const httpResponse: import("../../types").SendOneTimeCodeEmailResponse =
await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({
email,
database,
email_login_field: emailLoginTempCodeFieldName,
mail_domain,
mail_password,
mail_username,
mail_port,
sender,
html: emailHtml,
});
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/user/${
user_id || grabedHostNames.user_id
}/send-email-code`,
},
/**
* Callback Function
*
* @description https request callback
*/
(res) => {
var str = "";
res.on("data", function (chunk) {
str += chunk;
});
res.on("end", function () {
resolve(JSON.parse(str));
});
res.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
return httpResponse;
}
}
@@ -0,0 +1,236 @@
import http from "http";
import fs from "fs";
import path from "path";
import encrypt from "../../../functions/dsql/encrypt";
import grabHostNames from "../../../utils/grab-host-names";
import apiGithubLogin from "../../../functions/api/users/social/api-github-login";
interface FunctionReturn {
success: boolean;
user: {
id: number;
first_name: string;
last_name: string;
csrf_k: string;
social_id: string;
} | null;
dsqlUserId?: number;
msg?: string;
}
type Param = {
key: string;
code: string;
email: string | null;
database: string;
clientId: string;
clientSecret: string;
response: http.ServerResponse;
encryptionKey: string;
encryptionSalt: string;
additionalFields?: string[];
additionalData?: { [s: string]: string | number };
user_id?: boolean;
};
/**
* # SERVER FUNCTION: Login with google Function
*/
export default async function githubAuth({
key,
code,
email,
database,
clientId,
clientSecret,
response,
encryptionKey,
encryptionSalt,
additionalFields,
user_id,
additionalData,
}: Param): Promise<FunctionReturn | undefined> {
/**
* Check inputs
*
* @description Check inputs
*/
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
if (!code || code?.match(/ /)) {
return {
success: false,
user: null,
msg: "Please enter Github Access Token",
};
}
if (!database || database?.match(/ /)) {
return {
success: false,
user: null,
msg: "Please provide database slug name you want to access",
};
}
if (!clientId || clientId?.match(/ /)) {
return {
success: false,
user: null,
msg: "Please enter Github OAUTH client ID",
};
}
/**
* Initialize HTTP response variable
*/
let httpResponse;
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const {
DSQL_DB_HOST,
DSQL_DB_USERNAME,
DSQL_DB_PASSWORD,
DSQL_DB_NAME,
DSQL_KEY,
DSQL_REF_DB_NAME,
DSQL_FULL_SYNC,
} = process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./)
) {
/** @type {import("../../../types").DSQL_DatabaseSchemaType | undefined | undefined} */
let dbSchema:
| import("../../../types").DSQL_DatabaseSchemaType
| undefined
| undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
httpResponse = await apiGithubLogin({
code,
email: email || undefined,
clientId,
clientSecret,
additionalFields,
database: DSQL_DB_NAME,
additionalData,
});
} else {
/**
* Make https request
*
* @description make a request to datasquirel.com
* @type {FunctionReturn} - Https response object
*/
httpResponse = (await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({
code,
email,
clientId,
clientSecret,
database,
additionalFields,
additionalData,
});
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/user/${
user_id || grabedHostNames.user_id
}/github-login`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
try {
resolve(JSON.parse(str));
} catch (error) {
console.log(error);
resolve({
success: false,
user: null,
msg: "Something went wrong",
});
}
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
})) as any;
}
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
if (httpResponse?.success && httpResponse?.user) {
let encryptedPayload = encrypt({
data: JSON.stringify(httpResponse.user),
encryptionKey,
encryptionSalt,
});
const { user, dsqlUserId } = httpResponse;
const authKeyName = `datasquirel_${dsqlUserId}_${database}_auth_key`;
const csrfName = `datasquirel_${dsqlUserId}_${database}_csrf`;
response.setHeader("Set-Cookie", [
`${authKeyName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`,
`${csrfName}=${user.csrf_k};samesite=strict;path=/;HttpOnly=true`,
`dsqluid=${dsqlUserId};samesite=strict;path=/;HttpOnly=true`,
`datasquirel_social_id=${user.social_id};samesite=strict;path=/`,
]);
}
return httpResponse;
}
@@ -0,0 +1,205 @@
import http from "http";
import encrypt from "../../../functions/dsql/encrypt";
import grabHostNames from "../../../utils/grab-host-names";
import apiGoogleLogin from "../../../functions/api/users/social/api-google-login";
import getAuthCookieNames from "../../../functions/backend/cookies/get-auth-cookie-names";
import { writeAuthFile } from "../../../functions/backend/auth/write-auth-files";
import { APILoginFunctionReturn } from "../../../types";
type Param = {
key?: string;
token: string;
database?: string;
response?: http.ServerResponse;
encryptionKey?: string;
encryptionSalt?: string;
additionalFields?: string[];
additionalData?: { [s: string]: string | number };
apiUserID?: string | number;
debug?: boolean;
};
/**
* # SERVER FUNCTION: Login with google Function
*/
export default async function googleAuth({
key,
token,
database,
response,
encryptionKey,
encryptionSalt,
additionalFields,
additionalData,
apiUserID,
debug,
}: Param): Promise<APILoginFunctionReturn> {
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
const finalEncryptionKey =
encryptionKey || process.env.DSQL_ENCRYPTION_PASSWORD;
const finalEncryptionSalt =
encryptionSalt || process.env.DSQL_ENCRYPTION_SALT;
if (!finalEncryptionKey?.match(/.{8,}/)) {
console.log("Encryption key is invalid");
return {
success: false,
payload: null,
msg: "Encryption key is invalid",
};
}
if (!finalEncryptionSalt?.match(/.{8,}/)) {
console.log("Encryption salt is invalid");
return {
success: false,
payload: null,
msg: "Encryption salt is invalid",
};
}
/**
* Check inputs
*
* @description Check inputs
*/
if (!token || token?.match(/ /)) {
return {
success: false,
payload: null,
msg: "Please enter Google Access Token",
};
}
/**
* Initialize HTTP response variable
*/
let httpResponse: APILoginFunctionReturn = {
success: false,
};
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
if (debug) {
console.log(`Google login with Local Paradigm ...`);
}
httpResponse = await apiGoogleLogin({
token,
additionalFields,
additionalData,
debug,
});
} else {
/**
* Make https request
*
* @description make a request to datasquirel.com
* @type {{ success: boolean, user: import("../../../types").DATASQUIREL_LoggedInUser | null, msg?: string, dsqlUserId?: number } | null } - Https response object
*/
httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({
token,
database,
additionalFields,
additionalData,
});
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
key ||
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY,
},
port,
hostname: host,
path: `/api/user/${
apiUserID || grabedHostNames.user_id
}/google-login`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
if (httpResponse?.success && httpResponse?.payload) {
let encryptedPayload = encrypt({
data: JSON.stringify(httpResponse.payload),
encryptionKey: finalEncryptionKey,
encryptionSalt: finalEncryptionSalt,
});
const cookieNames = getAuthCookieNames({
database,
userId: apiUserID || process.env.DSQL_API_USER_ID,
});
if (httpResponse.csrf) {
writeAuthFile(
httpResponse.csrf,
JSON.stringify(httpResponse.payload)
);
}
httpResponse["cookieNames"] = cookieNames;
httpResponse["key"] = String(encryptedPayload);
const authKeyName = cookieNames.keyCookieName;
const csrfName = cookieNames.csrfCookieName;
response?.setHeader("Set-Cookie", [
`${authKeyName}=${encryptedPayload};samesite=strict;path=/;HttpOnly=true;Secure=true`,
`${csrfName}=${httpResponse.payload?.csrf_k};samesite=strict;path=/;HttpOnly=true`,
]);
}
return httpResponse;
}
@@ -0,0 +1,118 @@
import path from "path";
import fs from "fs";
import grabHostNames from "../../utils/grab-host-names";
import apiUpdateUser from "../../functions/api/users/api-update-user";
import { UpdateUserFunctionReturn } from "../../types";
type Param = {
key?: string;
database?: string;
updatedUserId: string | number;
payload: { [s: string]: any };
user_id?: boolean;
};
/**
* # Update User
*/
export default async function updateUser({
key,
payload,
database,
user_id,
updatedUserId,
}: Param): Promise<UpdateUserFunctionReturn> {
/**
* Check for local DB settings
*
* @description Look for local db settings in `.env` file and by pass the http request if available
*/
const { DSQL_DB_HOST, DSQL_DB_USERNAME, DSQL_DB_PASSWORD, DSQL_DB_NAME } =
process.env;
const grabedHostNames = grabHostNames();
const { host, port, scheme } = grabedHostNames;
if (
DSQL_DB_HOST?.match(/./) &&
DSQL_DB_USERNAME?.match(/./) &&
DSQL_DB_PASSWORD?.match(/./) &&
DSQL_DB_NAME?.match(/./) &&
global.DSQL_USE_LOCAL
) {
/** @type {import("../../types").DSQL_DatabaseSchemaType | undefined} */
let dbSchema: import("../../types").DSQL_DatabaseSchemaType | undefined;
try {
const localDbSchemaPath = path.resolve(
process.cwd(),
"dsql.schema.json"
);
dbSchema = JSON.parse(fs.readFileSync(localDbSchemaPath, "utf8"));
} catch (error) {}
return await apiUpdateUser({
payload: payload,
dbFullName: DSQL_DB_NAME,
updatedUserId,
dbSchema,
});
}
/**
* Make https request
*
* @description make a request to datasquirel.com
*/
const httpResponse = await new Promise((resolve, reject) => {
const reqPayload = JSON.stringify({
payload,
database,
updatedUserId,
});
const httpsRequest = scheme.request(
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.from(reqPayload).length,
Authorization:
process.env.DSQL_FULL_ACCESS_API_KEY ||
process.env.DSQL_API_KEY ||
key,
},
port,
hostname: host,
path: `/api/user/${
user_id || grabedHostNames.user_id
}/update-user`,
},
/**
* Callback Function
*
* @description https request callback
*/
(response) => {
var str = "";
response.on("data", function (chunk) {
str += chunk;
});
response.on("end", function () {
resolve(JSON.parse(str));
});
response.on("error", (err) => {
reject(err);
});
}
);
httpsRequest.write(reqPayload);
httpsRequest.end();
});
return httpResponse as UpdateUserFunctionReturn;
}
@@ -0,0 +1,207 @@
import http from "http";
import decrypt from "../../functions/dsql/decrypt";
import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names";
import { checkAuthFile } from "../../functions/backend/auth/write-auth-files";
import parseCookies from "../../utils/backend/parseCookies";
import { AuthenticatedUser } from "../../types";
import getCsrfHeaderName from "../../actions/get-csrf-header-name";
import grabHostNames from "../../utils/grab-host-names";
const minuteInMilliseconds = 60000;
const hourInMilliseconds = minuteInMilliseconds * 60;
const dayInMilliseconds = hourInMilliseconds * 24;
const weekInMilliseconds = dayInMilliseconds * 7;
const monthInMilliseconds = dayInMilliseconds * 30;
const yearInMilliseconds = dayInMilliseconds * 365;
type Param = {
request?: http.IncomingMessage & { [s: string]: any };
req?: http.IncomingMessage & { [s: string]: any };
cookieString?: string;
encryptedUserString?: string;
encryptionKey?: string;
encryptionSalt?: string;
level?: "deep" | "normal";
database?: string;
dsqlUserId?: string | number;
expiry?: number;
csrfHeaderName?: string;
debug?: boolean;
};
/**
* Authenticate User from request
* ==============================================================================
* @description This Function takes in a request object and returns a user object
* with the user's data
*/
export default function userAuth({
request,
req,
encryptionKey,
encryptionSalt,
level,
database,
dsqlUserId,
encryptedUserString,
expiry = weekInMilliseconds,
cookieString,
csrfHeaderName,
debug,
}: Param): AuthenticatedUser {
try {
const finalRequest = req || request;
const { user_id } = grabHostNames({ userId: dsqlUserId });
const cookies = parseCookies({
request: finalRequest,
cookieString,
});
if (debug) {
console.log("userAuth:cookies:", cookies);
}
const keyNames = getAuthCookieNames({
userId: user_id,
database: database || process.env.DSQL_DB_NAME,
});
if (debug) {
console.log("userAuth:keyNames:", keyNames);
}
const key = encryptedUserString
? encryptedUserString
: cookies[keyNames.keyCookieName];
if (debug) {
console.log("userAuth:key:", key);
}
/**
* Grab the payload
*
* @description Grab the payload
*/
let userPayloadJSON = decrypt({
encryptedString: key,
encryptionKey,
encryptionSalt,
});
if (debug) {
console.log("userAuth:userPayloadJSON:", userPayloadJSON);
}
/**
* Grab the payload
*
* @description Grab the payload
*/
if (!userPayloadJSON) {
return {
success: false,
payload: null,
msg: "Couldn't Decrypt cookie",
};
}
/**
* Grab the payload
*
* @description Grab the payload
*/
/** @type {import("../../types").DATASQUIREL_LoggedInUser} */
let userObject: import("../../types").DATASQUIREL_LoggedInUser =
JSON.parse(userPayloadJSON);
if (debug) {
console.log("userAuth:userObject:", userObject);
}
if (!userObject.csrf_k) {
return {
success: false,
payload: null,
msg: "No CSRF_K in decrypted payload",
};
}
if (!checkAuthFile(userObject.csrf_k)) {
return {
success: false,
payload: null,
msg: "Auth file doesn't exist",
};
}
/**
* Grab the payload
*
* @description Grab the payload
*/
if (level?.match(/deep/i) && finalRequest) {
const finalCsrfHeaderName = csrfHeaderName || getCsrfHeaderName();
if (
finalRequest.headers[finalCsrfHeaderName] !== userObject.csrf_k
) {
return {
success: false,
payload: null,
msg: "CSRF_K mismatch",
};
}
}
const payloadCreationDate = Number(userObject.date);
if (
Number.isNaN(payloadCreationDate) ||
typeof payloadCreationDate !== "number"
) {
return {
success: false,
payload: null,
msg: "Payload Creation Date is not a number",
};
}
const timeElapsed = Date.now() - payloadCreationDate;
const finalExpiry = process.env.DSQL_SESSION_EXPIRY_TIME
? Number(process.env.DSQL_SESSION_EXPIRY_TIME)
: expiry;
if (timeElapsed > finalExpiry) {
return {
success: false,
payload: null,
msg: "Session has expired",
};
}
/**
* Return User Object
*
* @description Return User Object
*/
return {
success: true,
payload: userObject,
};
} catch (error: any) {
/**
* Return User Object
*
* @description Return User Object
*/
return {
success: false,
payload: null,
msg: error.message,
};
}
}
@@ -0,0 +1,50 @@
import http from "http";
import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names";
import parseCookies from "../../utils/backend/parseCookies";
import decrypt from "../../functions/dsql/decrypt";
import EJSON from "../../utils/ejson";
import { SendOneTimeCodeEmailResponse } from "../../types";
type Param = {
request?: http.IncomingMessage & { [s: string]: any };
cookieString?: string;
email?: string;
};
/**
* # Verify the temp email code sent to the user's email address
*/
export default async function validateTempEmailCode({
request,
email,
cookieString,
}: Param): Promise<SendOneTimeCodeEmailResponse | null> {
try {
const keyNames = getAuthCookieNames();
const oneTimeCodeCookieName = keyNames.oneTimeCodeName;
const cookies = parseCookies({ request, cookieString });
const encryptedOneTimeCode = cookies[oneTimeCodeCookieName];
const encryptedPayload = decrypt({
encryptedString: encryptedOneTimeCode,
});
const payload = EJSON.parse(encryptedPayload) as
| SendOneTimeCodeEmailResponse
| undefined;
if (payload?.email && !email) {
return payload;
}
if (payload?.email && payload.email === email) {
return payload;
}
return null;
} catch (error: any) {
console.log("validateTempEmailCode error:", error.message);
return null;
}
}
@@ -0,0 +1,76 @@
import http from "http";
import decrypt from "../../functions/dsql/decrypt";
import { DATASQUIREL_LoggedInUser } from "../../types";
type Param = {
token: string;
encryptionKey: string;
encryptionSalt: string;
level?: ("deep" | "normal") | null;
database: string;
};
/**
* Validate Token
* ======================================
* @description This Function takes in a encrypted token and returns a user object
*/
export default function validateToken({
token,
encryptionKey,
encryptionSalt,
}: Param): DATASQUIREL_LoggedInUser | null {
try {
/**
* Grab the payload
*
* @description Grab the payload
*/
const key = token;
/**
* Grab the payload
*
* @description Grab the payload
*/
let userPayload = decrypt({
encryptedString: key,
encryptionKey,
encryptionSalt,
});
/**
* Grab the payload
*
* @description Grab the payload
*/
if (!userPayload) {
return null;
}
/**
* Grab the payload
*
* @description Grab the payload
*/
let userObject = JSON.parse(userPayload);
if (!userObject.csrf_k) {
return null;
}
/**
* Return User Object
*
* @description Return User Object
*/
return userObject;
} catch (error) {
/**
* Return User Object
*
* @description Return User Object
*/
return null;
}
}
+24 -6
View File
@@ -53,22 +53,40 @@
"title": "TEXT",
"name": "TEXT",
"value": "0-100",
"description": "MEDIUMTEXT is just text with max length 16,777,215",
"maxValue": 127
"description": "MEDIUMTEXT is just text with max length 16,777,215"
},
{
"title": "MEDIUMTEXT",
"name": "MEDIUMTEXT",
"value": "0-255",
"description": "MEDIUMTEXT is just text with max length 16,777,215",
"maxValue": 127
"description": "MEDIUMTEXT is just text with max length 16,777,215"
},
{
"title": "LONGTEXT",
"name": "LONGTEXT",
"value": "0-255",
"description": "LONGTEXT is just text with max length 4,294,967,295",
"maxValue": 127
"description": "LONGTEXT is just text with max length 4,294,967,295"
},
{
"title": "DECIMAL",
"name": "DECIMAL",
"description": "Numbers with decimals",
"integer": "1-100",
"decimals": "1-4"
},
{
"title": "FLOAT",
"name": "FLOAT",
"description": "Numbers with decimals",
"integer": "1-100",
"decimals": "1-4"
},
{
"title": "DOUBLE",
"name": "DOUBLE",
"description": "Numbers with decimals",
"integer": "1-100",
"decimals": "1-4"
},
{
"title": "UUID",
View File
View File
View File
@@ -2,29 +2,44 @@
import _ from "lodash";
import serverError from "../../backend/serverError";
import runQuery from "../../backend/db/runQuery";
import { DSQL_TableSchemaType, GetReturn } from "../../../types";
import runQuery, { DbContextsArray } from "../../backend/db/runQuery";
import {
ApiGetQueryObject,
DSQL_TableSchemaType,
GetReturn,
ServerQueryParam,
} from "../../../types";
import apiGetGrabQueryAndValues from "../../../utils/grab-query-and-values";
type Param = {
query: string;
type Param<T extends { [key: string]: any } = { [key: string]: any }> = {
query: string | ApiGetQueryObject<T>;
queryValues?: (string | number)[];
dbFullName: string;
tableName?: string;
dbSchema?: import("../../../types").DSQL_DatabaseSchemaType;
useLocal?: boolean;
debug?: boolean;
dbContext?: (typeof DbContextsArray)[number];
};
/**
* # Get Function FOr API
*/
export default async function apiGet({
export default async function apiGet<
T extends { [key: string]: any } = { [key: string]: any }
>({
query,
dbFullName,
queryValues,
tableName,
dbSchema,
useLocal,
}: Param): Promise<import("../../../types").GetReturn> {
debug,
dbContext,
}: Param<T>): Promise<import("../../../types").GetReturn> {
const queryAndValues = apiGetGrabQueryAndValues({
query,
values: queryValues,
});
if (
typeof query == "string" &&
query.match(/^alter|^delete|information_schema|databases|^create/i)
@@ -37,14 +52,20 @@ export default async function apiGet({
try {
let { result, error } = await runQuery({
dbFullName: dbFullName,
query: query,
queryValuesArray: queryValues,
query: queryAndValues.query,
queryValuesArray: queryAndValues.values,
readOnly: true,
dbSchema,
tableName,
local: useLocal,
dbContext,
debug,
});
if (debug && global.DSQL_USE_LOCAL) {
console.log("apiGet:result", result);
console.log("apiGet:error", error);
}
let tableSchema: DSQL_TableSchemaType | undefined;
if (dbSchema) {
@@ -83,6 +104,10 @@ export default async function apiGet({
message: error.message,
});
if (debug && global.DSQL_USE_LOCAL) {
console.log("apiGet:error", error.message);
}
return {
success: false,
payload: null,
@@ -1,6 +1,6 @@
import _ from "lodash";
import serverError from "../../backend/serverError";
import runQuery from "../../backend/db/runQuery";
import runQuery, { DbContextsArray } from "../../backend/db/runQuery";
import { DSQL_DatabaseSchemaType, PostReturn } from "../../../types";
type Param = {
@@ -9,7 +9,7 @@ type Param = {
dbFullName: string;
tableName?: string;
dbSchema?: DSQL_DatabaseSchemaType;
useLocal?: boolean;
dbContext?: (typeof DbContextsArray)[number];
};
/**
@@ -21,7 +21,7 @@ export default async function apiPost({
queryValues,
tableName,
dbSchema,
useLocal,
dbContext,
}: Param): Promise<PostReturn> {
if (typeof query === "string" && query?.match(/^create |^alter |^drop /i)) {
return { success: false, msg: "Wrong Input" };
@@ -34,7 +34,6 @@ export default async function apiPost({
return { success: false, msg: "Wrong Input" };
}
/** @type {any} */
let results: any;
/**
@@ -49,14 +48,13 @@ export default async function apiPost({
dbSchema: dbSchema,
queryValuesArray: queryValues,
tableName,
local: useLocal,
dbContext,
});
results = result;
if (error) throw error;
/** @type {import("../../../types").DSQL_TableSchemaType | undefined} */
let tableSchema:
| import("../../../types").DSQL_TableSchemaType
| undefined;
View File
View File
View File
+61 -27
View File
@@ -1,4 +1,4 @@
import fs from "fs";
import fs, { glob } from "fs";
import handleNodemailer from "../../backend/handleNodemailer";
import path from "path";
import addMariadbUser from "../../backend/addMariadbUser";
@@ -23,30 +23,55 @@ export default async function handleSocialDb({
invitation,
supEmail,
additionalFields,
useLocal,
debug,
}: HandleSocialDbFunctionParams): Promise<APILoginFunctionReturn> {
try {
const existingSocialIdUserQuery = `SELECT * FROM datasquirel.users WHERE social_id = ? AND social_login='1' AND social_platform = ? `;
const finalDbName = global.DSQL_USE_LOCAL
? undefined
: database
? database
: "datasquirel";
const dbAppend = global.DSQL_USE_LOCAL ? "" : `${finalDbName}.`;
const existingSocialIdUserQuery = `SELECT * FROM ${dbAppend}users WHERE social_id = ? AND social_login='1' AND social_platform = ? `;
const existingSocialIdUserValues = [
social_id.toString(),
social_platform,
];
if (debug) {
console.log(
"handleSocialDb:existingSocialIdUserQuery",
existingSocialIdUserQuery
);
console.log(
"handleSocialDb:existingSocialIdUserValues",
existingSocialIdUserValues
);
}
let existingSocialIdUser = await varDatabaseDbHandler({
database: database ? database : "datasquirel",
database: finalDbName,
queryString: existingSocialIdUserQuery,
queryValuesArray: existingSocialIdUserValues,
useLocal,
debug,
});
if (existingSocialIdUser && existingSocialIdUser[0]) {
if (debug) {
console.log(
"handleSocialDb:existingSocialIdUser",
existingSocialIdUser
);
}
if (existingSocialIdUser?.[0]) {
return await loginSocialUser({
user: existingSocialIdUser[0],
social_platform,
invitation,
database,
database: finalDbName,
additionalFields,
useLocal,
debug,
});
}
@@ -60,14 +85,25 @@ export default async function handleSocialDb({
};
}
const existingEmailOnlyQuery = `SELECT * FROM datasquirel.users WHERE email='${finalEmail}'`;
const existingEmailOnlyQuery = `SELECT * FROM ${dbAppend}users WHERE email='${finalEmail}'`;
if (debug) {
console.log(
"handleSocialDb:existingEmailOnlyQuery",
existingEmailOnlyQuery
);
}
let existingEmailOnly = await varDatabaseDbHandler({
database: database ? database : "datasquirel",
database: finalDbName,
queryString: existingEmailOnlyQuery,
useLocal,
debug,
});
if (debug) {
console.log("handleSocialDb:existingEmailOnly", existingEmailOnly);
}
if (existingEmailOnly && existingEmailOnly[0]) {
return {
success: false,
@@ -76,14 +112,14 @@ export default async function handleSocialDb({
};
}
const foundUserQuery = `SELECT * FROM datasquirel.users WHERE email=? AND social_login='1' AND social_platform=? AND social_id=?`;
const foundUserQuery = `SELECT * FROM ${dbAppend}users WHERE email=? AND social_login='1' AND social_platform=? AND social_id=?`;
const foundUserQueryValues = [finalEmail, social_platform, social_id];
const foundUser = await varDatabaseDbHandler({
database: database ? database : "datasquirel",
database: finalDbName,
queryString: foundUserQuery,
queryValuesArray: foundUserQueryValues,
useLocal,
debug,
});
if (foundUser && foundUser[0]) {
@@ -91,9 +127,9 @@ export default async function handleSocialDb({
user: payload,
social_platform,
invitation,
database,
database: finalDbName,
additionalFields,
useLocal,
debug,
});
}
@@ -111,11 +147,10 @@ export default async function handleSocialDb({
data[key] = payload[key];
});
/** @type {any} */
const newUser = await addDbEntry({
dbContext: database ? "Dsql User" : undefined,
paradigm: database ? "Full Access" : undefined,
dbFullName: database ? database : "datasquirel",
dbContext: finalDbName ? "Dsql User" : undefined,
paradigm: finalDbName ? "Full Access" : undefined,
dbFullName: finalDbName,
tableName: "users",
duplicateColumnName: "email",
duplicateColumnValue: finalEmail,
@@ -123,7 +158,6 @@ export default async function handleSocialDb({
...data,
email: finalEmail,
},
useLocal,
});
if (newUser?.insertId) {
@@ -131,15 +165,15 @@ export default async function handleSocialDb({
/**
* Add a Mariadb User for this User
*/
await addMariadbUser({ userId: newUser.insertId, useLocal });
await addMariadbUser({ userId: newUser.insertId });
}
const newUserQueriedQuery = `SELECT * FROM datasquirel.users WHERE id='${newUser.insertId}'`;
const newUserQueriedQuery = `SELECT * FROM ${dbAppend}users WHERE id='${newUser.insertId}'`;
const newUserQueried = await varDatabaseDbHandler({
database: database ? database : "datasquirel",
database: finalDbName,
queryString: newUserQueriedQuery,
useLocal,
debug,
});
if (!newUserQueried || !newUserQueried[0])
@@ -215,9 +249,9 @@ export default async function handleSocialDb({
user: newUserQueried[0],
social_platform,
invitation,
database,
database: finalDbName,
additionalFields,
useLocal,
debug,
});
} else {
console.log(
+11 -10
View File
@@ -1,6 +1,9 @@
import addAdminUserOnLogin from "../../backend/addAdminUserOnLogin";
import varDatabaseDbHandler from "../../backend/varDatabaseDbHandler";
import { APILoginFunctionReturn } from "../../../types";
import {
APILoginFunctionReturn,
DATASQUIREL_LoggedInUser,
} from "../../../types";
type Param = {
user: {
@@ -13,7 +16,7 @@ type Param = {
invitation?: any;
database?: string;
additionalFields?: string[];
useLocal?: boolean;
debug?: boolean;
};
/**
@@ -28,18 +31,19 @@ export default async function loginSocialUser({
invitation,
database,
additionalFields,
useLocal,
debug,
}: Param): Promise<APILoginFunctionReturn> {
const finalDbName = database ? database : "datasquirel";
const dbAppend = database ? `\`${finalDbName}\`.` : "";
const foundUserQuery = `SELECT * FROM \`${finalDbName}\`.\`users\` WHERE email=? AND social_id=? AND social_platform=?`;
const foundUserQuery = `SELECT * FROM ${dbAppend}\`users\` WHERE email=? AND social_id=? AND social_platform=?`;
const foundUserValues = [user.email, user.social_id, social_platform];
const foundUser = await varDatabaseDbHandler({
database: finalDbName,
queryString: foundUserQuery,
queryValuesArray: foundUserValues,
useLocal,
debug,
});
if (!foundUser?.[0])
@@ -53,8 +57,7 @@ export default async function loginSocialUser({
"-" +
Math.random().toString(36).substring(2);
/** @type {import("../../../types").DATASQUIREL_LoggedInUser} */
let userPayload: import("../../../types").DATASQUIREL_LoggedInUser = {
let userPayload: DATASQUIREL_LoggedInUser = {
id: foundUser[0].id,
first_name: foundUser[0].first_name,
last_name: foundUser[0].last_name,
@@ -82,12 +85,10 @@ export default async function loginSocialUser({
addAdminUserOnLogin({
query: invitation,
user: userPayload,
useLocal,
});
}
/** @type {import("../../../types").APILoginFunctionReturn} */
let result: import("../../../types").APILoginFunctionReturn = {
let result: APILoginFunctionReturn = {
success: true,
payload: userPayload,
csrf: csrfKey,
@@ -15,7 +15,6 @@ export default async function apiCreateUser({
payload,
database,
userId,
useLocal,
}: APICreateUserFunctionParams) {
const dbFullName = database;
const API_USER_ID = userId || process.env.DSQL_API_USER_ID;
@@ -51,21 +50,19 @@ export default async function apiCreateUser({
let fields = await varDatabaseDbHandler({
queryString: fieldsQuery,
database: dbFullName,
useLocal,
});
if (!fields?.[0]) {
const newTable = await addUsersTableToDb({
userId: Number(API_USER_ID),
database: dbFullName,
useLocal,
payload: payload,
});
fields = await varDatabaseDbHandler({
queryString: fieldsQuery,
database: dbFullName,
useLocal,
});
}
@@ -111,7 +108,6 @@ export default async function apiCreateUser({
queryString: existingUserQuery,
queryValuesArray: existingUserValues,
database: dbFullName,
useLocal,
});
if (existingUser?.[0]) {
@@ -136,7 +132,6 @@ export default async function apiCreateUser({
process.env.DSQL_DEFAULT_USER_IMAGE ||
"/images/user-preset-thumbnail.png",
},
useLocal,
});
if (addUser?.insertId) {
@@ -145,7 +140,6 @@ export default async function apiCreateUser({
const newlyAddedUser = await varDatabaseDbHandler({
queryString: newlyAddedUserQuery,
database: dbFullName,
useLocal,
});
return {
@@ -4,7 +4,6 @@ import varDatabaseDbHandler from "../../backend/varDatabaseDbHandler";
type Param = {
dbFullName: string;
deletedUserId: string | number;
useLocal?: boolean;
};
type Return = { success: boolean; result?: any; msg?: string };
@@ -14,7 +13,6 @@ type Return = { success: boolean; result?: any; msg?: string };
export default async function apiDeleteUser({
dbFullName,
deletedUserId,
useLocal,
}: Param): Promise<Return> {
const existingUserQuery = `SELECT * FROM ${dbFullName}.users WHERE id = ?`;
const existingUserValues = [deletedUserId];
@@ -23,7 +21,6 @@ export default async function apiDeleteUser({
queryString: existingUserQuery,
queryValuesArray: existingUserValues,
database: dbFullName,
useLocal,
});
if (!existingUser?.[0]) {
@@ -35,12 +32,10 @@ export default async function apiDeleteUser({
const deleteUser = await deleteDbEntry({
dbContext: "Dsql User",
paradigm: "Full Access",
dbFullName,
tableName: "users",
identifierColumnName: "id",
identifierValue: deletedUserId,
useLocal,
});
return {
@@ -11,7 +11,6 @@ export default async function apiGetUser({
fields,
dbFullName,
userId,
useLocal,
}: APIGetUserFunctionParams): Promise<GetUserFunctionReturn> {
const finalDbName = dbFullName.replace(/[^a-z0-9_]/g, "");
@@ -24,7 +23,6 @@ export default async function apiGetUser({
queryString: query,
queryValuesArray: [API_USER_ID],
database: finalDbName,
useLocal,
});
if (!foundUser || !foundUser[0]) {
@@ -20,14 +20,13 @@ export default async function apiLoginUser({
email_login,
email_login_code,
email_login_field,
token,
skipPassword,
social,
useLocal,
dbUserId,
debug,
}: APILoginFunctionParams): Promise<APILoginFunctionReturn> {
const dbFullName = grabDbFullName({ dbName: database, userId: dbUserId });
const dbAppend = global.DSQL_USE_LOCAL ? "" : `${dbFullName}.`;
/**
* Check input validity
@@ -63,10 +62,10 @@ export default async function apiLoginUser({
}
let foundUser = await varDatabaseDbHandler({
queryString: `SELECT * FROM ${dbFullName}.users WHERE email = ? OR username = ?`,
queryString: `SELECT * FROM ${dbAppend}users WHERE email = ? OR username = ?`,
queryValuesArray: [email, username],
database: dbFullName,
useLocal,
debug,
});
@@ -140,10 +139,9 @@ export default async function apiLoginUser({
if (isPasswordCorrect && email_login) {
const resetTempCode = await varDatabaseDbHandler({
queryString: `UPDATE ${dbFullName}.users SET ${email_login_field} = '' WHERE email = ? OR username = ?`,
queryString: `UPDATE ${dbAppend}users SET ${email_login_field} = '' WHERE email = ? OR username = ?`,
queryValuesArray: [email, username],
database: dbFullName,
useLocal,
});
}
@@ -5,7 +5,6 @@ type Param = {
existingUser: { [s: string]: any };
database?: string;
additionalFields?: string[];
useLocal?: boolean;
};
/**
@@ -15,15 +14,19 @@ export default async function apiReauthUser({
existingUser,
database,
additionalFields,
useLocal,
}: Param): Promise<APILoginFunctionReturn> {
const dbAppend = global.DSQL_USE_LOCAL
? ""
: database
? `${database}.`
: "";
let foundUser =
existingUser?.id && existingUser.id.toString().match(/./)
? await varDatabaseDbHandler({
queryString: `SELECT * FROM ${database}.users WHERE id=?`,
queryString: `SELECT * FROM ${dbAppend}users WHERE id=?`,
queryValuesArray: [existingUser.id.toString()],
database,
useLocal,
})
: null;
@@ -39,7 +42,6 @@ export default async function apiReauthUser({
"-" +
Math.random().toString(36).substring(2);
/** @type {import("../../../types").DATASQUIREL_LoggedInUser} */
let userPayload: import("../../../types").DATASQUIREL_LoggedInUser = {
id: foundUser[0].id,
first_name: foundUser[0].first_name,
@@ -16,7 +16,6 @@ type Param = {
mail_username?: string;
mail_password?: string;
html: string;
useLocal?: boolean;
response?: http.ServerResponse & { [s: string]: any };
extraCookies?: import("../../../../package-shared/types").CookieObject[];
};
@@ -34,7 +33,6 @@ export default async function apiSendEmailCode({
mail_username,
mail_password,
html,
useLocal,
response,
extraCookies,
}: Param): Promise<SendOneTimeCodeEmailResponse> {
@@ -53,7 +51,6 @@ export default async function apiSendEmailCode({
queryString: foundUserQuery,
queryValuesArray: foundUserValues,
database,
useLocal,
});
////////////////////////////////////////
@@ -114,7 +111,6 @@ export default async function apiSendEmailCode({
queryString: setTempCodeQuery,
queryValuesArray: setTempCodeValues,
database,
useLocal,
});
/** @type {import("../../../types").SendOneTimeCodeEmailResponse} */
@@ -9,7 +9,6 @@ type Param = {
payload: { [s: string]: any };
dbFullName: string;
updatedUserId: string | number;
useLocal?: boolean;
dbSchema?: import("../../../types").DSQL_DatabaseSchemaType;
};
@@ -22,7 +21,7 @@ export default async function apiUpdateUser({
payload,
dbFullName,
updatedUserId,
useLocal,
dbSchema,
}: Param): Promise<Return> {
const existingUserQuery = `SELECT * FROM ${dbFullName}.users WHERE id = ?`;
@@ -32,7 +31,6 @@ export default async function apiUpdateUser({
queryString: existingUserQuery,
queryValuesArray: existingUserValues,
database: dbFullName,
useLocal,
});
if (!existingUser?.[0]) {
@@ -83,13 +81,11 @@ export default async function apiUpdateUser({
const updateUser = await updateDbEntry({
dbContext: "Dsql User",
paradigm: "Full Access",
dbFullName,
tableName: "users",
identifierColumnName: "id",
identifierValue: updatedUserId,
data: data,
useLocal,
});
return {
@@ -14,7 +14,6 @@ type Param = {
email: string;
encryptionKey?: string;
encryptionSalt?: string;
useLocal?: boolean;
debug?: boolean;
apiUserID?: string | number;
dbUserId?: string | number;
@@ -26,13 +25,8 @@ type Param = {
export default async function apiSendResetPasswordLink({
database,
email,
apiUserID,
dbUserId,
debug,
encryptionKey,
encryptionSalt,
key,
useLocal,
}: Param): Promise<Return> {
const dbFullName = grabDbFullName({ dbName: database, userId: dbUserId });
@@ -52,7 +46,6 @@ export default async function apiSendResetPasswordLink({
queryString: `SELECT * FROM ${dbFullName}.users WHERE email = ? OR username = ?`,
queryValuesArray: [email, email],
database: dbFullName,
useLocal,
debug,
});
@@ -15,6 +15,7 @@ export default async function apiGoogleLogin({
database,
additionalFields,
additionalData,
debug,
}: APIGoogleLoginFunctionParams): Promise<APILoginFunctionReturn> {
try {
const gUser: GoogleOauth2User | undefined = await new Promise(
@@ -45,18 +46,6 @@ export default async function apiGoogleLogin({
if (!gUser?.email_verified) throw new Error("No Google User.");
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
if (!database || typeof database != "string" || database?.match(/ /)) {
return {
success: false,
payload: undefined,
msg: "Please provide a database slug(database name in lowercase with no spaces)",
};
}
/**
* Create new user folder and file
*
@@ -65,7 +54,6 @@ export default async function apiGoogleLogin({
const { given_name, family_name, email, sub, picture } = gUser;
/** @type {Object<string, any>} */
let payloadObject: { [s: string]: any } = {
email: email,
first_name: given_name,
@@ -88,6 +76,7 @@ export default async function apiGoogleLogin({
social_platform: "google",
social_id: sub,
additionalFields,
debug,
});
////////////////////////////////////////
+3 -5
View File
@@ -11,7 +11,6 @@ type Param = {
priviledge: string;
email: string;
};
useLocal?: boolean;
user: DATASQUIREL_LoggedInUser;
};
@@ -26,10 +25,11 @@ type Param = {
export default async function addAdminUserOnLogin({
query,
user,
useLocal,
}: Param): Promise<any> {
try {
const finalDbHandler = useLocal ? LOCAL_DB_HANDLER : DB_HANDLER;
const finalDbHandler = global.DSQL_USE_LOCAL
? LOCAL_DB_HANDLER
: DB_HANDLER;
const { invite, database_access, priviledge, email } = query;
const lastInviteTimeQuery = `SELECT date_created_code FROM invitations WHERE inviting_user_id=? AND invited_user_email=?`;
@@ -82,7 +82,6 @@ export default async function addAdminUserOnLogin({
image: user.image,
image_thumbnail: user.image_thumbnail,
},
useLocal,
});
////////////////////////////////////////////////
@@ -122,7 +121,6 @@ export default async function addAdminUserOnLogin({
table: table_slug,
priviledge: priviledge,
},
useLocal,
});
}
}
@@ -7,16 +7,12 @@ import LOCAL_DB_HANDLER from "../../utils/backend/global-db/LOCAL_DB_HANDLER";
type Param = {
userId: number | string;
useLocal?: boolean;
};
/**
* # Add Mariadb User
*/
export default async function addMariadbUser({
userId,
useLocal,
}: Param): Promise<any> {
export default async function addMariadbUser({ userId }: Param): Promise<any> {
try {
const defaultMariadbUserHost = process.env.DSQL_DB_HOST || "127.0.0.1";
@@ -32,7 +28,7 @@ export default async function addMariadbUser({
const createMariadbUsersQuery = `CREATE USER IF NOT EXISTS '${username}'@'127.0.0.1' IDENTIFIED BY '${password}'`;
if (useLocal) {
if (global.DSQL_USE_LOCAL) {
await LOCAL_DB_HANDLER(createMariadbUsersQuery);
} else {
await NO_DB_HANDLER(createMariadbUsersQuery);
@@ -41,7 +37,7 @@ export default async function addMariadbUser({
const updateUserQuery = `UPDATE users SET mariadb_user = ?, mariadb_host = '127.0.0.1', mariadb_pass = ? WHERE id = ?`;
const updateUserValues = [username, encryptedPassword, userId];
const updateUser = useLocal
const updateUser = global.DSQL_USE_LOCAL
? await LOCAL_DB_HANDLER(updateUserQuery, updateUserValues)
: await DB_HANDLER(updateUserQuery, updateUserValues);
@@ -56,7 +52,6 @@ export default async function addMariadbUser({
grants: '[{"database":"*","table":"*","privileges":["ALL"]}]',
},
dbContext: "Master",
useLocal,
});
console.log(`User ${userId} SQL credentials successfully added.`);
+1 -5
View File
@@ -10,7 +10,6 @@ import grabNewUsersTableSchema from "./grabNewUsersTableSchema";
type Param = {
userId: number;
database: string;
useLocal?: boolean;
payload?: { [s: string]: any };
};
@@ -20,7 +19,6 @@ type Param = {
export default async function addUsersTableToDb({
userId,
database,
useLocal,
payload,
}: Param): Promise<any> {
try {
@@ -52,8 +50,7 @@ export default async function addUsersTableToDb({
setUserSchemaData({ schemaData: userSchemaData, userId });
/** @type {any[] | null} */
const targetDb: any[] | null = useLocal
const targetDb: any[] | null = global.DSQL_USE_LOCAL
? await LOCAL_DB_HANDLER(
`SELECT id FROM user_databases WHERE user_id=? AND db_slug=?`,
[userId, database]
@@ -74,7 +71,6 @@ export default async function addUsersTableToDb({
table_name: "Users",
table_slug: "users",
},
useLocal,
});
}
@@ -1,16 +1,14 @@
// @ts-check
import sanitizeHtml from "sanitize-html";
import sanitizeHtmlOptions from "../html/sanitizeHtmlOptions";
import updateDbEntry from "./updateDbEntry";
import _ from "lodash";
import DB_HANDLER from "../../../utils/backend/global-db/DB_HANDLER";
import DSQL_USER_DB_HANDLER from "../../../utils/backend/global-db/DSQL_USER_DB_HANDLER";
import encrypt from "../../dsql/encrypt";
import LOCAL_DB_HANDLER from "../../../utils/backend/global-db/LOCAL_DB_HANDLER";
import connDbHandler from "../../../utils/db/conn-db-handler";
import checkIfIsMaster from "../../../utils/check-if-is-master";
import { DbContextsArray } from "./runQuery";
type Param = {
dbContext?: "Master" | "Dsql User";
dbContext?: (typeof DbContextsArray)[number];
paradigm?: "Read Only" | "Full Access";
dbFullName?: string;
tableName: string;
@@ -21,32 +19,10 @@ type Param = {
update?: boolean;
encryptionKey?: string;
encryptionSalt?: string;
useLocal?: boolean;
};
/**
* 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
* @param {boolean} [params.useLocal]
*
* @returns {Promise<any>}
*/
export default async function addDbEntry({
dbContext,
@@ -60,25 +36,18 @@ export default async function addDbEntry({
update,
encryptionKey,
encryptionSalt,
useLocal,
}: Param): Promise<any> {
/**
* Initialize variables
*/
const isMaster = useLocal
? true
: dbContext?.match(/dsql.user/i)
? false
: dbFullName && !dbFullName.match(/^datasquirel$/)
? false
: true;
const isMaster = checkIfIsMaster({ dbContext, dbFullName });
/** @type { any } */
const dbHandler: any = useLocal
? LOCAL_DB_HANDLER
: isMaster
? DB_HANDLER
: DSQL_USER_DB_HANDLER;
const DB_CONN = isMaster
? global.DSQL_DB_CONN
: global.DSQL_FULL_ACCESS_DB_CONN || global.DSQL_DB_CONN;
const DB_RO_CONN = isMaster
? global.DSQL_DB_CONN
: global.DSQL_READ_ONLY_DB_CONN || global.DSQL_DB_CONN;
////////////////////////////////////////
////////////////////////////////////////
@@ -95,28 +64,22 @@ export default async function addDbEntry({
////////////////////////////////////////
////////////////////////////////////////
/**
* Handle function logic
*/
if (duplicateColumnName && typeof duplicateColumnName === "string") {
const duplicateValue = isMaster
? await dbHandler(
`SELECT * FROM \`${tableName}\` WHERE \`${duplicateColumnName}\`=?`,
[duplicateColumnValue]
)
: await dbHandler({
paradigm: "Read Only",
queryString: `SELECT * FROM \`${dbFullName}\`.\`${tableName}\` WHERE \`${duplicateColumnName}\`=?`,
queryValues: [duplicateColumnValue],
});
const checkDuplicateQuery = `SELECT * FROM ${
isMaster ? "" : `\`${dbFullName}\`.`
}\`${tableName}\` WHERE \`${duplicateColumnName}\`=?`;
const duplicateValue = await connDbHandler(
DB_RO_CONN,
checkDuplicateQuery,
[duplicateColumnValue]
);
if (duplicateValue?.[0] && !update) {
return null;
} else if (duplicateValue && duplicateValue[0] && update) {
return await updateDbEntry({
dbContext,
paradigm,
dbFullName,
tableName,
data,
@@ -201,7 +164,7 @@ export default async function addDbEntry({
} else {
insertValuesArray.push(value);
}
} catch (/** @type {any} */ error: any) {
} catch (error: any) {
console.log("DSQL: Error in parsing data keys =>", error.message);
continue;
}
@@ -233,18 +196,14 @@ export default async function addDbEntry({
////////////////////////////////////////
const query = `INSERT INTO \`${dbFullName}\`.\`${tableName}\` (${insertKeysArray.join(
","
)}) VALUES (${insertValuesArray.map(() => "?").join(",")})`;
const query = `INSERT INTO ${
isMaster ? "" : `\`${dbFullName}\`.`
}\`${tableName}\` (${insertKeysArray.join(",")}) VALUES (${insertValuesArray
.map(() => "?")
.join(",")})`;
const queryValuesArray = insertValuesArray;
const newInsert = isMaster
? await dbHandler(query, queryValuesArray)
: await dbHandler({
paradigm,
queryString: query,
queryValues: queryValuesArray,
});
const newInsert = await connDbHandler(DB_CONN, query, queryValuesArray);
/**
* Return statement
@@ -1,16 +1,14 @@
import DB_HANDLER from "../../../utils/backend/global-db/DB_HANDLER";
import DSQL_USER_DB_HANDLER from "../../../utils/backend/global-db/DSQL_USER_DB_HANDLER";
import LOCAL_DB_HANDLER from "../../../utils/backend/global-db/LOCAL_DB_HANDLER";
import checkIfIsMaster from "../../../utils/check-if-is-master";
import connDbHandler from "../../../utils/db/conn-db-handler";
import { DbContextsArray } from "./runQuery";
type Param = {
dbContext?: string;
paradigm?: "Read Only" | "Full Access";
dbContext?: (typeof DbContextsArray)[number];
dbFullName: string;
tableName: string;
tableSchema?: import("../../../types").DSQL_TableSchemaType;
identifierColumnName: string;
identifierValue: string | number;
useLocal?: boolean;
};
/**
@@ -19,43 +17,33 @@ type Param = {
*/
export default async function deleteDbEntry({
dbContext,
paradigm,
dbFullName,
tableName,
identifierColumnName,
identifierValue,
useLocal,
}: Param): Promise<object | null> {
try {
const isMaster = useLocal
? true
: dbContext?.match(/dsql.user/i)
? false
: dbFullName && !dbFullName.match(/^datasquirel$/)
? false
: true;
const isMaster = checkIfIsMaster({ dbContext, dbFullName });
/** @type { (a1:any, a2?:any) => any } */
const dbHandler: (a1: any, a2?: any) => any = useLocal
? LOCAL_DB_HANDLER
: isMaster
? DB_HANDLER
: DSQL_USER_DB_HANDLER;
const DB_CONN = isMaster
? global.DSQL_DB_CONN
: global.DSQL_FULL_ACCESS_DB_CONN || global.DSQL_DB_CONN;
const DB_RO_CONN = isMaster
? global.DSQL_DB_CONN
: global.DSQL_READ_ONLY_DB_CONN || global.DSQL_DB_CONN;
/**
* Execution
*
* @description
*/
const query = `DELETE FROM \`${dbFullName}\`.\`${tableName}\` WHERE \`${identifierColumnName}\`=?`;
const query = `DELETE FROM ${
isMaster ? "" : `\`${dbFullName}\`.`
}\`${tableName}\` WHERE \`${identifierColumnName}\`=?`;
const deletedEntry = isMaster
? await dbHandler(query, [identifierValue])
: await dbHandler({
paradigm,
queryString: query,
queryValues: [identifierValue],
});
const deletedEntry = await connDbHandler(DB_CONN, query, [
identifierValue,
]);
/**
* Return statement
@@ -7,11 +7,14 @@ import deleteDbEntry from "./deleteDbEntry";
import trimSql from "../../../utils/trim-sql";
import { DSQL_TableSchemaType } from "../../../types";
export const DbContextsArray = ["Master", "Dsql User"] as const;
type Param = {
dbContext?: (typeof DbContextsArray)[number];
dbFullName: string;
query: string | any;
readOnly?: boolean;
local?: boolean;
debug?: boolean;
dbSchema?: import("../../../types").DSQL_DatabaseSchemaType;
queryValuesArray?: (string | number)[];
tableName?: string;
@@ -27,7 +30,8 @@ export default async function runQuery({
dbSchema,
queryValuesArray,
tableName,
local,
debug,
dbContext,
}: Param): Promise<any> {
/**
* Declare variables
@@ -66,6 +70,10 @@ export default async function runQuery({
if (typeof query === "string") {
const formattedQuery = trimSql(query);
if (debug && global.DSQL_USE_LOCAL) {
console.log("runQuery:formattedQuery", formattedQuery);
}
/**
* Input Validation
*
@@ -85,14 +93,12 @@ export default async function runQuery({
queryString: formattedQuery,
queryValuesArray: queryValuesArray?.map((vl) => String(vl)),
tableSchema,
useLocal: local,
});
} else {
result = await fullAccessDbHandler({
queryString: formattedQuery,
queryValuesArray: queryValuesArray?.map((vl) => String(vl)),
tableSchema,
local,
});
}
} else if (typeof query === "object") {
@@ -115,8 +121,7 @@ export default async function runQuery({
switch (action.toLowerCase()) {
case "insert":
result = await addDbEntry({
dbContext: local ? "Master" : "Dsql User",
paradigm: "Full Access",
dbContext,
dbFullName: dbFullName,
tableName: table,
data: data,
@@ -124,7 +129,6 @@ export default async function runQuery({
duplicateColumnName,
duplicateColumnValue,
tableSchema,
useLocal: local,
});
if (!result?.insertId) {
@@ -135,29 +139,25 @@ export default async function runQuery({
case "update":
result = await updateDbEntry({
dbContext: local ? "Master" : "Dsql User",
paradigm: "Full Access",
dbContext,
dbFullName: dbFullName,
tableName: table,
data: data,
identifierColumnName,
identifierValue,
tableSchema,
useLocal: local,
});
break;
case "delete":
result = await deleteDbEntry({
dbContext: local ? "Master" : "Dsql User",
paradigm: "Full Access",
dbContext,
dbFullName: dbFullName,
tableName: table,
identifierColumnName,
identifierValue,
tableSchema,
useLocal: local,
});
break;
@@ -167,11 +167,16 @@ export default async function runQuery({
break;
}
}
} catch (/** @type {any} */ error: any) {
} catch (error: any) {
serverError({
component: "functions/backend/runQuery",
message: error.message,
});
if (debug && global.DSQL_USE_LOCAL) {
console.log("runQuery:error", error.message);
}
result = null;
error = error.message;
}
@@ -1,13 +1,12 @@
import sanitizeHtml from "sanitize-html";
import sanitizeHtmlOptions from "../html/sanitizeHtmlOptions";
import DB_HANDLER from "../../../utils/backend/global-db/DB_HANDLER";
import DSQL_USER_DB_HANDLER from "../../../utils/backend/global-db/DSQL_USER_DB_HANDLER";
import encrypt from "../../dsql/encrypt";
import LOCAL_DB_HANDLER from "../../../utils/backend/global-db/LOCAL_DB_HANDLER";
import checkIfIsMaster from "../../../utils/check-if-is-master";
import connDbHandler from "../../../utils/db/conn-db-handler";
import { DbContextsArray } from "./runQuery";
type Param = {
dbContext?: "Master" | "Dsql User";
paradigm?: "Read Only" | "Full Access";
dbContext?: (typeof DbContextsArray)[number];
dbFullName?: string;
tableName: string;
encryptionKey?: string;
@@ -16,7 +15,6 @@ type Param = {
tableSchema?: import("../../../types").DSQL_TableSchemaType;
identifierColumnName: string;
identifierValue: string | number;
useLocal?: boolean;
};
/**
@@ -25,7 +23,6 @@ type Param = {
*/
export default async function updateDbEntry({
dbContext,
paradigm,
dbFullName,
tableName,
data,
@@ -34,27 +31,20 @@ export default async function updateDbEntry({
identifierValue,
encryptionKey,
encryptionSalt,
useLocal,
}: Param): Promise<object | null> {
/**
* Check if data is valid
*/
if (!data || !Object.keys(data).length) return null;
const isMaster = useLocal
? true
: dbContext?.match(/dsql.user/i)
? false
: dbFullName && !dbFullName.match(/^datasquirel$/)
? false
: true;
const isMaster = checkIfIsMaster({ dbContext, dbFullName });
/** @type {(a1:any, a2?:any)=> any } */
const dbHandler: (a1: any, a2?: any) => any = useLocal
? LOCAL_DB_HANDLER
: isMaster
? DB_HANDLER
: DSQL_USER_DB_HANDLER;
const DB_CONN = isMaster
? global.DSQL_DB_CONN
: global.DSQL_FULL_ACCESS_DB_CONN || global.DSQL_DB_CONN;
const DB_RO_CONN = isMaster
? global.DSQL_DB_CONN
: global.DSQL_READ_ONLY_DB_CONN || global.DSQL_DB_CONN;
////////////////////////////////////////
////////////////////////////////////////
@@ -164,19 +154,15 @@ export default async function updateDbEntry({
////////////////////////////////////////
////////////////////////////////////////
const query = `UPDATE \`${dbFullName}\`.\`${tableName}\` SET ${updateKeyValueArray.join(
const query = `UPDATE ${
isMaster ? "" : `\`${dbFullName}\`.`
}\`${tableName}\` SET ${updateKeyValueArray.join(
","
)} WHERE \`${identifierColumnName}\`=?`;
updateValues.push(identifierValue);
const updatedEntry = isMaster
? await dbHandler(query, updateValues)
: await dbHandler({
paradigm,
queryString: query,
queryValues: updateValues,
});
const updatedEntry = await connDbHandler(DB_CONN, query, updateValues);
/**
* Return statement
@@ -1,7 +1,7 @@
import fs from "fs";
import serverError from "./serverError";
import mysql from "serverless-mysql";
import grabDSQLConnection from "../../utils/grab-dsql-connection";
import path from "path";
/**
* # Main DB Handler Function
@@ -37,8 +37,12 @@ export default async function dbHandler(...args: any[]) {
);
});
} catch (error: any) {
const tmpFolder = path.resolve(process.cwd(), "./.tmp");
if (!fs.existsSync(tmpFolder))
fs.mkdirSync(tmpFolder, { recursive: true });
fs.appendFileSync(
"./.tmp/dbErrorLogs.txt",
path.resolve(tmpFolder, "./dbErrorLogs.txt"),
JSON.stringify(error, null, 4) + "\n" + Date() + "\n\n\n",
"utf8"
);
@@ -1,13 +1,9 @@
// @ts-check
import DSQL_USER_DB_HANDLER from "../../utils/backend/global-db/DSQL_USER_DB_HANDLER";
import LOCAL_DB_HANDLER from "../../utils/backend/global-db/LOCAL_DB_HANDLER";
import connDbHandler from "../../utils/db/conn-db-handler";
import parseDbResults from "./parseDbResults";
import serverError from "./serverError";
type Param = {
queryString: string;
local?: boolean;
tableSchema?: import("../../types").DSQL_TableSchemaType | null;
queryValuesArray?: string[];
};
@@ -19,7 +15,6 @@ export default async function fullAccessDbHandler({
queryString,
tableSchema,
queryValuesArray,
local,
}: Param) {
/**
* Declare variables
@@ -28,24 +23,18 @@ export default async function fullAccessDbHandler({
*/
let results;
const DB_CONN = global.DSQL_FULL_ACCESS_DB_CONN || global.DSQL_DB_CONN;
/**
* Fetch from db
*
* @description Fetch data from db if no cache
*/
try {
/** ********************* Run Query */
results = local
? await LOCAL_DB_HANDLER(queryString, queryValuesArray)
: await DSQL_USER_DB_HANDLER({
paradigm: "Full Access",
queryString,
queryValues: queryValuesArray,
});
results = await connDbHandler(DB_CONN, queryString, queryValuesArray);
////////////////////////////////////////
} catch (/** @type {any} */ error: any) {
} catch (error: any) {
////////////////////////////////////////
serverError({
@@ -57,6 +46,8 @@ export default async function fullAccessDbHandler({
* Return error
*/
return error.message;
} finally {
DB_CONN?.end();
}
/**
View File
View File
View File
View File
@@ -37,18 +37,23 @@ export default function httpRequest<
delete params.query;
delete params.urlEncodedFormBody;
let finalHeaders: http.OutgoingHttpHeaders = {
"Content-Type": isUrlEncodedFormBody
? "application/x-www-form-urlencoded"
: "application/json",
};
if (reqPayloadString) {
finalHeaders["Content-Length"] =
Buffer.from(reqPayloadString).length;
}
finalHeaders = { ...finalHeaders, ...params.headers };
/** @type {import("node:https").RequestOptions} */
const requestOptions: import("node:https").RequestOptions = {
...params,
headers: {
"Content-Type": isUrlEncodedFormBody
? "application/x-www-form-urlencoded"
: "application/json",
"Content-Length": reqPayloadString
? Buffer.from(reqPayloadString).length
: undefined,
...params.headers,
},
headers: finalHeaders,
port: paramScheme == "https" ? 443 : params.port,
path: finalPath,
};
View File
View File
View File
@@ -8,7 +8,6 @@ type Param = {
queryValuesArray?: any[];
database?: string;
tableSchema?: import("../../types").DSQL_TableSchemaType;
useLocal?: boolean;
debug?: boolean;
};
@@ -20,16 +19,16 @@ export default async function varDatabaseDbHandler({
queryValuesArray,
database,
tableSchema,
useLocal,
debug,
}: Param): Promise<any> {
let CONNECTION = grabDSQLConnection({ fa: true });
if (useLocal) CONNECTION = grabDSQLConnection({ local: true });
if (global.DSQL_USE_LOCAL) CONNECTION = grabDSQLConnection({ local: true });
if (database?.match(/^datasquirel$/)) CONNECTION = grabDSQLConnection();
if (debug) {
console.log(`varDatabaseDbHandler:query:`, queryString);
console.log(`varDatabaseDbHandler:values:`, queryValuesArray);
console.log(`varDatabaseDbHandler:CONNECTION:`, CONNECTION.getConfig());
}
let results = await connDbHandler(
@@ -1,16 +1,11 @@
// @ts-check
import fs from "fs";
import serverError from "./serverError";
import parseDbResults from "./parseDbResults";
import DSQL_USER_DB_HANDLER from "../../utils/backend/global-db/DSQL_USER_DB_HANDLER";
import LOCAL_DB_HANDLER from "../../utils/backend/global-db/LOCAL_DB_HANDLER";
import connDbHandler from "../../utils/db/conn-db-handler";
type Param = {
queryString: string;
queryValuesArray?: string[];
tableSchema?: import("../../types").DSQL_TableSchemaType;
useLocal?: boolean;
};
/**
@@ -21,7 +16,6 @@ export default async function varReadOnlyDatabaseDbHandler({
queryString,
queryValuesArray,
tableSchema,
useLocal,
}: Param) {
/**
* Declare variables
@@ -30,22 +24,18 @@ export default async function varReadOnlyDatabaseDbHandler({
*/
let results;
const DB_CONN = global.DSQL_READ_ONLY_DB_CONN || global.DSQL_DB_CONN;
/**
* Fetch from db
*
* @description Fetch data from db if no cache
*/
try {
results = useLocal
? await LOCAL_DB_HANDLER(queryString, queryValuesArray)
: await DSQL_USER_DB_HANDLER({
paradigm: "Read Only",
queryString,
queryValues: queryValuesArray,
});
results = await connDbHandler(DB_CONN, queryString, queryValuesArray);
////////////////////////////////////////
} catch (/** @type {any} */ error: any) {
} catch (error: any) {
////////////////////////////////////////
serverError({
@@ -58,6 +48,8 @@ export default async function varReadOnlyDatabaseDbHandler({
* Return error
*/
return error.message;
} finally {
DB_CONN?.end();
}
/**
@@ -9,12 +9,16 @@ interface SQLDeleteGenReturn {
export default function sqlDeleteGenerator({
tableName,
data,
dbFullName,
}: {
data: any;
tableName: string;
dbFullName?: string;
}): SQLDeleteGenReturn | undefined {
const finalDbName = dbFullName ? `${dbFullName}.` : "";
try {
let queryStr = `DELETE FROM ${tableName}`;
let queryStr = `DELETE FROM ${finalDbName}${tableName}`;
let deleteBatch: string[] = [];
let queryArr: string[] = [];
@@ -4,9 +4,10 @@ import {
ServerQueryQueryObject,
} from "../../../types";
type Param = {
genObject?: ServerQueryParam;
type Param<T extends { [key: string]: any } = { [key: string]: any }> = {
genObject?: ServerQueryParam<T>;
tableName: string;
dbFullName?: string;
};
type Return =
@@ -20,7 +21,9 @@ type Return =
* # SQL Query Generator
* @description Generates an SQL Query for node module `mysql` or `serverless-mysql`
*/
export default function sqlGenerator({ tableName, genObject }: Param): Return {
export default function sqlGenerator<
T extends { [key: string]: any } = { [key: string]: any }
>({ tableName, genObject, dbFullName }: Param<T>): Return {
if (!genObject) return undefined;
const finalQuery = genObject.query ? genObject.query : undefined;
@@ -29,6 +32,8 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
const sqlSearhValues: string[] = [];
const finalDbName = dbFullName ? `${dbFullName}.` : "";
/**
* # Generate Query
*/
@@ -43,10 +48,10 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
}) {
const finalFieldName = (() => {
if (queryObj?.tableName) {
return `${queryObj.tableName}.${field}`;
return `${finalDbName}${queryObj.tableName}.${field}`;
}
if (join) {
return `${tableName}.${field}`;
return `${finalDbName}${tableName}.${field}`;
}
return field;
})();
@@ -112,7 +117,6 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
join: genObject.join,
});
});
console.log("queryObj.operator", queryObj.operator);
return (
"(" +
@@ -128,7 +132,7 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
/** @type {import("../../../types").ServerQueryParamsJoinMatchObject} */ mtch: import("../../../types").ServerQueryParamsJoinMatchObject,
/** @type {import("../../../types").ServerQueryParamsJoin} */ join: import("../../../types").ServerQueryParamsJoin
) {
return `${
return `${finalDbName}${
typeof mtch.source == "object" ? mtch.source.tableName : tableName
}.${
typeof mtch.source == "object" ? mtch.source.fieldName : mtch.source
@@ -138,7 +142,7 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
}
if (join.alias) {
return `${
return `${finalDbName}${
typeof mtch.target == "object"
? mtch.target.tableName
: join.alias
@@ -149,7 +153,7 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
}`;
}
return `${
return `${finalDbName}${
typeof mtch.target == "object"
? mtch.target.tableName
: join.tableName
@@ -166,14 +170,14 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
if (genObject.selectFields?.[0]) {
if (genObject.join) {
str += ` ${genObject.selectFields
?.map((fld) => `${tableName}.${fld}`)
?.map((fld) => `${finalDbName}${tableName}.${fld}`)
.join(",")}`;
} else {
str += ` ${genObject.selectFields?.join(",")}`;
}
} else {
if (genObject.join) {
str += ` ${tableName}.*`;
str += ` ${finalDbName}${tableName}.*`;
} else {
str += " *";
}
@@ -199,11 +203,11 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
return joinObj.selectFields
.map((selectField) => {
if (typeof selectField == "string") {
return `${joinTableName}.${selectField}`;
return `${finalDbName}${joinTableName}.${selectField}`;
} else if (typeof selectField == "object") {
let aliasSelectField = selectField.count
? `COUNT(${joinTableName}.${selectField.field})`
: `${joinTableName}.${selectField.field}`;
? `COUNT(${finalDbName}${joinTableName}.${selectField.field})`
: `${finalDbName}${joinTableName}.${selectField.field}`;
if (selectField.alias)
aliasSelectField += ` AS ${selectField.alias}`;
return aliasSelectField;
@@ -211,14 +215,14 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
})
.join(",");
} else {
return `${joinTableName}.*`;
return `${finalDbName}${joinTableName}.*`;
}
})
.filter((_) => Boolean(_))
.join(",");
}
str += ` FROM ${tableName}`;
str += ` FROM ${finalDbName}${tableName}`;
if (genObject.join) {
str +=
@@ -229,8 +233,10 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
join.joinType +
" " +
(join.alias
? join.tableName + " " + join.alias
: join.tableName) +
? `${finalDbName}${join.tableName}` +
" " +
join.alias
: `${finalDbName}${join.tableName}`) +
" ON " +
(() => {
if (Array.isArray(join.match)) {
@@ -267,8 +273,8 @@ export default function sqlGenerator({ tableName, genObject }: Param): Return {
if (genObject.order)
queryString += ` ORDER BY ${
genObject.join
? `${tableName}.${genObject.order.field}`
: genObject.order.field
? `${finalDbName}${tableName}.${String(genObject.order.field)}`
: String(genObject.order.field)
} ${genObject.order.strategy}`;
if (genObject.limit) queryString += ` LIMIT ${genObject.limit}`;
@@ -11,13 +11,16 @@ interface SQLInsertGenReturn {
export default function sqlInsertGenerator({
tableName,
data,
dbFullName,
}: {
data: any[];
tableName: string;
dbFullName?: string;
}): SQLInsertGenReturn | undefined {
const finalDbName = dbFullName ? `${dbFullName}.` : "";
try {
if (Array.isArray(data) && data?.[0]) {
/** @type {string[]} */
let insertKeys: string[] = [];
data.forEach((dt) => {
@@ -48,7 +51,7 @@ export default function sqlInsertGenerator({
.join(",")})`
);
});
let query = `INSERT INTO ${tableName} (${insertKeys.join(
let query = `INSERT INTO ${finalDbName}${tableName} (${insertKeys.join(
","
)}) VALUES ${queryBatches.join(",")}`;
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
+5 -4
View File
@@ -1,8 +1,5 @@
import fs from "fs";
import path from "path";
import mysql from "serverless-mysql";
import grabDbSSL from "../../utils/backend/grabDbSSL";
import grabDSQLConnection from "../../utils/grab-dsql-connection";
type Param = {
@@ -37,8 +34,12 @@ export default async function dbHandler({
console.log(error);
console.log(CONNECTION.config());
const tmpFolder = path.resolve(process.cwd(), "./.tmp");
if (!fs.existsSync(tmpFolder))
fs.mkdirSync(tmpFolder, { recursive: true });
fs.appendFileSync(
path.resolve(__dirname, "../.tmp/dbErrorLogs.txt"),
path.resolve(tmpFolder, "./dbErrorLogs.txt"),
JSON.stringify(error, null, 4) + "\n" + Date() + "\n\n\n",
"utf8"
);
View File
View File
View File
View File
View File
View File
+90 -19
View File
@@ -1,5 +1,5 @@
import type { IncomingMessage, ServerResponse } from "http";
import { RequestOptions } from "https";
import type { RequestOptions } from "https";
import { Editor } from "tinymce";
export type DSQL_DatabaseFullName = string;
@@ -41,7 +41,17 @@ export interface DSQL_ChildrenTablesType {
tableNameFull?: string;
}
export interface DSQL_FieldSchemaType {
export const TextFieldTypesArray = [
{ title: "Plain Text", value: "plain" },
{ title: "Rich Text", value: "richText" },
{ title: "JSON", value: "json" },
{ title: "YAML", value: "yaml" },
{ title: "HTML", value: "html" },
{ title: "CSS", value: "css" },
{ title: "Javascript", value: "javascript" },
] as const;
export type DSQL_FieldSchemaType = {
fieldName?: string;
originName?: string;
updatedField?: boolean;
@@ -54,13 +64,6 @@ export interface DSQL_FieldSchemaType {
defaultValue?: string | number;
defaultValueLiteral?: string;
foreignKey?: DSQL_ForeignKeyType;
richText?: boolean;
json?: boolean;
yaml?: boolean;
html?: boolean;
css?: boolean;
javascript?: boolean;
shell?: boolean;
newTempField?: boolean;
defaultField?: boolean;
plainText?: boolean;
@@ -72,7 +75,11 @@ export interface DSQL_FieldSchemaType {
onDelete?: string;
onDeleteLiteral?: string;
cssFiles?: string[];
}
integerLength?: string | number;
decimals?: string | number;
} & {
[key in (typeof TextFieldTypesArray)[number]["value"]]?: boolean;
};
export interface DSQL_ForeignKeyType {
foreignKeyName?: string;
@@ -185,6 +192,7 @@ export interface GetReqQueryObject {
query: string;
queryValues?: string;
tableName?: string;
debug?: boolean;
}
export type DATASQUIREL_LoggedInUser = {
@@ -288,6 +296,7 @@ export interface GetReturn {
msg?: string;
error?: string;
schema?: DSQL_TableSchemaType;
finalQuery?: string;
}
export interface GetSchemaRequestQuery {
@@ -921,6 +930,7 @@ export interface MYSQL_user_database_tables_table_def {
table_slug?: string;
table_description?: string;
child_table?: number;
active_data?: 0 | 1;
child_table_parent_database?: string;
child_table_parent_table?: string;
date_created?: string;
@@ -1082,19 +1092,22 @@ export type FetchApiReturn = {
export const ServerQueryOperators = ["AND", "OR"] as const;
export const ServerQueryEqualities = ["EQUAL", "LIKE", "NOT EQUAL"] as const;
export type ServerQueryParam = {
export type ServerQueryParam<
T extends { [k: string]: any } = { [k: string]: any }
> = {
selectFields?: string[];
query?: ServerQueryQueryObject;
query?: ServerQueryQueryObject<T>;
limit?: number;
page?: number;
offset?: number;
order?: {
field: string;
field: keyof T;
strategy: "ASC" | "DESC";
};
searchOperator?: (typeof ServerQueryOperators)[number];
searchEquality?: (typeof ServerQueryEqualities)[number];
addUserId?: {
fieldName: string;
fieldName: keyof T;
};
join?: ServerQueryParamsJoin[];
[key: string]: any;
@@ -1208,7 +1221,6 @@ export type APILoginFunctionParams = {
token?: boolean;
skipPassword?: boolean;
social?: boolean;
useLocal?: boolean;
dbUserId?: number | string;
debug?: boolean;
};
@@ -1228,7 +1240,6 @@ export type APICreateUserFunctionParams = {
payload: any;
database: string;
userId?: string | number;
useLocal?: boolean;
};
export type APICreateUserFunction = (
@@ -1242,7 +1253,6 @@ export type APIGetUserFunctionParams = {
fields: string[];
dbFullName: string;
userId: string | number;
useLocal?: boolean;
};
/**
@@ -1250,9 +1260,10 @@ export type APIGetUserFunctionParams = {
*/
export type APIGoogleLoginFunctionParams = {
token: string;
database: string;
database?: string;
additionalFields?: string[];
additionalData?: { [key: string]: string | number };
debug?: boolean;
};
export type APIGoogleLoginFunction = (
@@ -1271,7 +1282,7 @@ export type HandleSocialDbFunctionParams = {
invitation?: any;
supEmail?: string;
additionalFields?: string[];
useLocal?: boolean;
debug?: boolean;
};
export type HandleSocialDbFunctionReturn = {
@@ -1444,3 +1455,63 @@ export type HttpFunctionResponse<
str?: string;
requestedPath?: string;
};
export type ApiGetQueryObject<
T extends { [k: string]: any } = { [k: string]: any }
> = {
query: ServerQueryParam<T>;
table: string;
dbFullName?: string;
};
export const DataCrudRequestMethods = ["GET", "POST", "PUT", "DELETE"] as const;
export type DsqlMethodCrudParam<
T extends { [key: string]: any } = { [key: string]: any }
> = {
method: (typeof DataCrudRequestMethods)[number];
body?: T;
query?: DsqlCrudQueryObject<T>;
tableName: string;
addUser?: {
field: keyof T;
};
user?: DATASQUIREL_LoggedInUser;
extraData?: T;
transform?: DsqlCrudTransformFunction<T>;
existingData?: T;
targetId?: string | number;
sanitize?: (data?: T) => T;
};
export type DsqlCrudTransformFunction<
T extends { [key: string]: any } = { [key: string]: any }
> = ({
data,
existingData,
user,
}: {
user?: DATASQUIREL_LoggedInUser;
data: T;
existingData?: T;
reqMethod: (typeof DataCrudRequestMethods)[number];
}) => Promise<T>;
export const DsqlCrudActions = ["insert", "update", "delete", "get"] as const;
export type DsqlCrudQueryObject<
T extends { [key: string]: any } = { [key: string]: any }
> = ServerQueryParam<T> & {
query?: ServerQueryQueryObject<T>;
};
export type DsqlCrudParam<
T extends { [key: string]: any } = { [key: string]: any }
> = {
action: (typeof DsqlCrudActions)[number];
table: string;
data?: T;
targetId?: string | number;
query?: DsqlCrudQueryObject<T>;
sanitize?: (data?: T) => T;
};
@@ -1,4 +1,3 @@
import mysql from "serverless-mysql";
import grabDSQLConnection from "../../grab-dsql-connection";
/**
@@ -6,8 +6,6 @@ import grabDSQLConnection from "../../grab-dsql-connection";
export default async function LOCAL_DB_HANDLER(...args: any[]) {
const MASTER = grabDSQLConnection();
console.log("Querying ...");
try {
const results = await MASTER.query(...args);
@@ -0,0 +1,14 @@
type Param = {
dbContext?: "Master" | "Dsql User";
dbFullName?: string;
};
export default function checkIfIsMaster({ dbContext, dbFullName }: Param) {
return dbContext?.match(/dsql.user/i)
? false
: global.DSQL_USE_LOCAL
? true
: dbFullName && !dbFullName.match(/^datasquirel$/)
? false
: true;
}
@@ -0,0 +1,74 @@
import get from "../../actions/get";
import post from "../../actions/post";
import sqlGenerator from "../../functions/dsql/sql/sql-generator";
import { DsqlCrudParam, PostReturn } from "../../types";
export default async function dsqlCrud<
T extends { [key: string]: any } = { [key: string]: any }
>({
action,
data,
table,
targetId,
query,
sanitize,
}: DsqlCrudParam<T>): Promise<
| (PostReturn & {
queryObject?: ReturnType<Awaited<typeof sqlGenerator>>;
})
| null
> {
const finalData = sanitize ? sanitize(data) : data;
const finalId = targetId;
let queryObject: ReturnType<Awaited<typeof sqlGenerator>> | undefined;
switch (action) {
case "get":
queryObject = sqlGenerator({
tableName: table,
genObject: query,
});
const GET_RES = await get({
query: queryObject?.string || "",
queryValues: queryObject?.values || [],
});
return { ...GET_RES, queryObject };
case "insert":
return await post({
query: {
action: "insert",
table,
data: finalData,
},
});
case "update":
delete data?.id;
return await post({
query: {
action: "update",
table,
identifierColumnName: "id",
identifierValue: String(finalId),
data: finalData,
},
});
case "delete":
return await post({
query: {
action: "delete",
table,
identifierColumnName: "id",
identifierValue: String(finalId),
},
});
default:
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More