Autosave: 20260210-061827
This commit is contained in:
parent
b6d69636c6
commit
9bf5ff301f
@ -1,3 +0,0 @@
|
|||||||
backend/node_modules
|
|
||||||
frontend/node_modules
|
|
||||||
frontend/build
|
|
||||||
0
.perm_test_exec
Normal file
0
.perm_test_exec
Normal file
21
Dockerfile
21
Dockerfile
@ -1,21 +0,0 @@
|
|||||||
FROM node:20.15.1-alpine AS builder
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
WORKDIR /app
|
|
||||||
COPY frontend/package.json frontend/yarn.lock ./
|
|
||||||
RUN yarn install --pure-lockfile
|
|
||||||
COPY frontend .
|
|
||||||
RUN yarn build
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FROM node:20.15.1-alpine
|
|
||||||
WORKDIR /app
|
|
||||||
COPY backend/package.json backend/yarn.lock ./
|
|
||||||
RUN yarn install --pure-lockfile
|
|
||||||
COPY backend .
|
|
||||||
|
|
||||||
COPY --from=builder /app/build /app/public
|
|
||||||
CMD ["yarn", "start"]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
# Base image for Node.js dependencies
|
|
||||||
FROM node:20.15.1-alpine AS frontend-deps
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
WORKDIR /app/frontend
|
|
||||||
COPY frontend/package.json frontend/yarn.lock ./
|
|
||||||
RUN yarn install --pure-lockfile
|
|
||||||
|
|
||||||
FROM node:20.15.1-alpine AS backend-deps
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
WORKDIR /app/backend
|
|
||||||
COPY backend/package.json backend/yarn.lock ./
|
|
||||||
RUN yarn install --pure-lockfile
|
|
||||||
|
|
||||||
FROM node:20.15.1-alpine AS app-shell-deps
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
WORKDIR /app/app-shell
|
|
||||||
COPY app-shell/package.json app-shell/yarn.lock ./
|
|
||||||
RUN yarn install --pure-lockfile
|
|
||||||
|
|
||||||
# Nginx setup and application build
|
|
||||||
FROM node:20.15.1-alpine AS build
|
|
||||||
RUN apk add --no-cache git nginx curl
|
|
||||||
RUN apk add --no-cache lsof procps
|
|
||||||
RUN yarn global add concurrently
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
chromium \
|
|
||||||
nss \
|
|
||||||
freetype \
|
|
||||||
harfbuzz \
|
|
||||||
ttf-freefont \
|
|
||||||
fontconfig
|
|
||||||
|
|
||||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
|
||||||
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
|
|
||||||
|
|
||||||
RUN mkdir -p /app/pids
|
|
||||||
|
|
||||||
# Make sure to add yarn global bin to PATH
|
|
||||||
ENV PATH /root/.yarn/bin:/root/.config/yarn/global/node_modules/.bin:$PATH
|
|
||||||
|
|
||||||
# Copy dependencies
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=frontend-deps /app/frontend /app/frontend
|
|
||||||
COPY --from=backend-deps /app/backend /app/backend
|
|
||||||
COPY --from=app-shell-deps /app/app-shell /app/app-shell
|
|
||||||
|
|
||||||
COPY frontend /app/frontend
|
|
||||||
COPY backend /app/backend
|
|
||||||
COPY app-shell /app/app-shell
|
|
||||||
COPY docker /app/docker
|
|
||||||
|
|
||||||
# Copy all files from root to /app
|
|
||||||
COPY . /app
|
|
||||||
|
|
||||||
# Copy Nginx configuration
|
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
# Copy custom error page
|
|
||||||
COPY 502.html /usr/share/nginx/html/502.html
|
|
||||||
|
|
||||||
# Change owner and permissions of the error page
|
|
||||||
RUN chown nginx:nginx /usr/share/nginx/html/502.html && \
|
|
||||||
chmod 644 /usr/share/nginx/html/502.html
|
|
||||||
|
|
||||||
# Expose the port the app runs on
|
|
||||||
EXPOSE 8080
|
|
||||||
ENV NODE_ENV=dev_stage
|
|
||||||
ENV FRONT_PORT=3001
|
|
||||||
ENV BACKEND_PORT=3000
|
|
||||||
ENV APP_SHELL_PORT=4000
|
|
||||||
|
|
||||||
|
|
||||||
CMD ["sh", "-c", "\
|
|
||||||
yarn --cwd /app/frontend dev & echo $! > /app/pids/frontend.pid && \
|
|
||||||
yarn --cwd /app/backend start & echo $! > /app/pids/backend.pid && \
|
|
||||||
sleep 10 && nginx -g 'daemon off;' & \
|
|
||||||
NGINX_PID=$! && \
|
|
||||||
echo 'Waiting for backend (port 3000) to be available...' && \
|
|
||||||
while ! nc -z localhost ${BACKEND_PORT}; do \
|
|
||||||
sleep 2; \
|
|
||||||
done && \
|
|
||||||
echo 'Backend is up. Starting app_shell for Git check...' && \
|
|
||||||
yarn --cwd /app/app-shell start && \
|
|
||||||
wait $NGINX_PID"]
|
|
||||||
14
backend/.env
14
backend/.env
@ -1,14 +0,0 @@
|
|||||||
DB_NAME=app_38334
|
|
||||||
DB_USER=app_38334
|
|
||||||
DB_PASS=02f73895-cabe-4aa2-94ec-5acefd8fd4d0
|
|
||||||
DB_HOST=127.0.0.1
|
|
||||||
DB_PORT=5432
|
|
||||||
PORT=3000
|
|
||||||
GOOGLE_CLIENT_ID=671001533244-kf1k1gmp6mnl0r030qmvdu6v36ghmim6.apps.googleusercontent.com
|
|
||||||
GOOGLE_CLIENT_SECRET=Yo4qbKZniqvojzUQ60iKlxqR
|
|
||||||
MS_CLIENT_ID=4696f457-31af-40de-897c-e00d7d4cff73
|
|
||||||
MS_CLIENT_SECRET=m8jzZ.5UpHF3=-dXzyxiZ4e[F8OF54@p
|
|
||||||
EMAIL_USER=AKIAVEW7G4PQUBGM52OF
|
|
||||||
EMAIL_PASS=BLnD4hKGb6YkSz3gaQrf8fnyLi3C3/EdjOOsLEDTDPTz
|
|
||||||
SECRET_KEY=HUEyqESqgQ1yTwzVlO6wprC9Kf1J1xuA
|
|
||||||
PEXELS_KEY=Vc99rnmOhHhJAbgGQoKLZtsaIVfkeownoQNbTj78VemUjKh08ZYRbf18
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
# Ignore generated and runtime files
|
|
||||||
node_modules/
|
|
||||||
tmp/
|
|
||||||
logs/
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
es2021: true
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended'
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
'import'
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'import/no-unresolved': 'error'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"singleQuote": true,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"printWidth": 80,
|
|
||||||
"trailingComma": "all",
|
|
||||||
"quoteProps": "as-needed",
|
|
||||||
"jsxSingleQuote": true,
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"bracketSameLine": false,
|
|
||||||
"arrowParens": "always"
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
module.exports = {
|
|
||||||
"config": path.resolve("src", "db", "db.config.js"),
|
|
||||||
"models-path": path.resolve("src", "db", "models"),
|
|
||||||
"seeders-path": path.resolve("src", "db", "seeders"),
|
|
||||||
"migrations-path": path.resolve("src", "db", "migrations")
|
|
||||||
};
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
FROM node:20.15.1-alpine
|
|
||||||
|
|
||||||
RUN apk update && apk add bash
|
|
||||||
# Create app directory
|
|
||||||
WORKDIR /usr/src/app
|
|
||||||
|
|
||||||
# Install app dependencies
|
|
||||||
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
|
||||||
# where available (npm@5+)
|
|
||||||
COPY package*.json ./
|
|
||||||
|
|
||||||
RUN yarn install
|
|
||||||
# If you are building your code for production
|
|
||||||
# RUN npm ci --only=production
|
|
||||||
|
|
||||||
|
|
||||||
# Bundle app source
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
CMD [ "yarn", "start" ]
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
|
|
||||||
#Blackness Studio Website - template backend,
|
|
||||||
|
|
||||||
#### Run App on local machine:
|
|
||||||
|
|
||||||
##### Install local dependencies:
|
|
||||||
- `yarn install`
|
|
||||||
|
|
||||||
------------
|
|
||||||
|
|
||||||
##### Adjust local db:
|
|
||||||
###### 1. Install postgres:
|
|
||||||
- MacOS:
|
|
||||||
- `brew install postgres`
|
|
||||||
|
|
||||||
- Ubuntu:
|
|
||||||
- `sudo apt update`
|
|
||||||
- `sudo apt install postgresql postgresql-contrib`
|
|
||||||
|
|
||||||
###### 2. Create db and admin user:
|
|
||||||
- Before run and test connection, make sure you have created a database as described in the above configuration. You can use the `psql` command to create a user and database.
|
|
||||||
- `psql postgres --u postgres`
|
|
||||||
|
|
||||||
- Next, type this command for creating a new user with password then give access for creating the database.
|
|
||||||
- `postgres-# CREATE ROLE admin WITH LOGIN PASSWORD 'admin_pass';`
|
|
||||||
- `postgres-# ALTER ROLE admin CREATEDB;`
|
|
||||||
|
|
||||||
- Quit `psql` then log in again using the new user that previously created.
|
|
||||||
- `postgres-# \q`
|
|
||||||
- `psql postgres -U admin`
|
|
||||||
|
|
||||||
- Type this command to creating a new database.
|
|
||||||
- `postgres=> CREATE DATABASE db_blackness_studio_website;`
|
|
||||||
|
|
||||||
- Then give that new user privileges to the new database then quit the `psql`.
|
|
||||||
- `postgres=> GRANT ALL PRIVILEGES ON DATABASE db_blackness_studio_website TO admin;`
|
|
||||||
- `postgres=> \q`
|
|
||||||
|
|
||||||
------------
|
|
||||||
|
|
||||||
#### Api Documentation (Swagger)
|
|
||||||
|
|
||||||
http://localhost:8080/api-docs (local host)
|
|
||||||
|
|
||||||
http://host_name/api-docs
|
|
||||||
|
|
||||||
------------
|
|
||||||
|
|
||||||
##### Setup database tables or update after schema change
|
|
||||||
- `yarn db:migrate`
|
|
||||||
|
|
||||||
##### Seed the initial data (admin accounts, relevant for the first setup):
|
|
||||||
- `yarn db:seed`
|
|
||||||
|
|
||||||
##### Start build:
|
|
||||||
- `yarn start`
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "blacknessstudiowebsite",
|
|
||||||
"description": "Blackness Studio Website - template backend",
|
|
||||||
"scripts": {
|
|
||||||
"start": "npm run db:migrate && npm run db:seed && npm run watch",
|
|
||||||
"lint": "eslint . --ext .js",
|
|
||||||
"db:migrate": "sequelize-cli db:migrate",
|
|
||||||
"db:seed": "sequelize-cli db:seed:all",
|
|
||||||
"db:drop": "sequelize-cli db:drop",
|
|
||||||
"db:create": "sequelize-cli db:create",
|
|
||||||
"watch": "node watcher.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@google-cloud/storage": "^5.18.2",
|
|
||||||
"axios": "^1.6.7",
|
|
||||||
"bcrypt": "5.1.1",
|
|
||||||
"chokidar": "^4.0.3",
|
|
||||||
"cors": "2.8.5",
|
|
||||||
"csv-parser": "^3.0.0",
|
|
||||||
"express": "4.18.2",
|
|
||||||
"formidable": "1.2.2",
|
|
||||||
"helmet": "4.1.1",
|
|
||||||
"json2csv": "^5.0.7",
|
|
||||||
"jsonwebtoken": "8.5.1",
|
|
||||||
"lodash": "4.17.21",
|
|
||||||
"moment": "2.30.1",
|
|
||||||
"multer": "^1.4.4",
|
|
||||||
"mysql2": "2.2.5",
|
|
||||||
"nodemailer": "6.9.9",
|
|
||||||
"passport": "^0.7.0",
|
|
||||||
"passport-google-oauth2": "^0.2.0",
|
|
||||||
"passport-jwt": "^4.0.1",
|
|
||||||
"passport-microsoft": "^0.1.0",
|
|
||||||
"pg": "8.4.1",
|
|
||||||
"pg-hstore": "2.3.4",
|
|
||||||
"sequelize": "6.35.2",
|
|
||||||
"sequelize-json-schema": "^2.1.1",
|
|
||||||
"sqlite": "4.0.15",
|
|
||||||
"swagger-jsdoc": "^6.2.8",
|
|
||||||
"swagger-ui-express": "^5.0.0",
|
|
||||||
"tedious": "^18.2.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"private": true,
|
|
||||||
"devDependencies": {
|
|
||||||
"cross-env": "7.0.3",
|
|
||||||
"eslint": "^8.23.1",
|
|
||||||
"eslint-plugin-import": "^2.29.1",
|
|
||||||
"mocha": "8.1.3",
|
|
||||||
"node-mocks-http": "1.9.0",
|
|
||||||
"nodemon": "2.0.5",
|
|
||||||
"sequelize-cli": "6.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,484 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const fs = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
const http = require("http");
|
|
||||||
const https = require("https");
|
|
||||||
const { URL } = require("url");
|
|
||||||
|
|
||||||
let CONFIG_CACHE = null;
|
|
||||||
|
|
||||||
class LocalAIApi {
|
|
||||||
static createResponse(params, options) {
|
|
||||||
return createResponse(params, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static request(pathValue, payload, options) {
|
|
||||||
return request(pathValue, payload, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static fetchStatus(aiRequestId, options) {
|
|
||||||
return fetchStatus(aiRequestId, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static awaitResponse(aiRequestId, options) {
|
|
||||||
return awaitResponse(aiRequestId, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static extractText(response) {
|
|
||||||
return extractText(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static decodeJsonFromResponse(response) {
|
|
||||||
return decodeJsonFromResponse(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createResponse(params, options = {}) {
|
|
||||||
const payload = { ...(params || {}) };
|
|
||||||
|
|
||||||
if (!Array.isArray(payload.input) || payload.input.length === 0) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: "input_missing",
|
|
||||||
message: 'Parameter "input" is required and must be a non-empty array.',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const cfg = config();
|
|
||||||
if (!payload.model) {
|
|
||||||
payload.model = cfg.defaultModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
const initial = await request(options.path, payload, options);
|
|
||||||
if (!initial.success) {
|
|
||||||
return initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = initial.data;
|
|
||||||
if (data && typeof data === "object" && data.ai_request_id) {
|
|
||||||
const pollTimeout = Number(options.poll_timeout ?? 300);
|
|
||||||
const pollInterval = Number(options.poll_interval ?? 5);
|
|
||||||
return await awaitResponse(data.ai_request_id, {
|
|
||||||
interval: pollInterval,
|
|
||||||
timeout: pollTimeout,
|
|
||||||
headers: options.headers,
|
|
||||||
timeout_per_call: options.timeout,
|
|
||||||
verify_tls: options.verify_tls,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function request(pathValue, payload = {}, options = {}) {
|
|
||||||
const cfg = config();
|
|
||||||
const resolvedPath = pathValue || options.path || cfg.responsesPath;
|
|
||||||
|
|
||||||
if (!resolvedPath) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: "project_id_missing",
|
|
||||||
message: "PROJECT_ID is not defined; cannot resolve AI proxy endpoint.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cfg.projectUuid) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: "project_uuid_missing",
|
|
||||||
message: "PROJECT_UUID is not defined; aborting AI request.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const bodyPayload = { ...(payload || {}) };
|
|
||||||
if (!bodyPayload.project_uuid) {
|
|
||||||
bodyPayload.project_uuid = cfg.projectUuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = buildUrl(resolvedPath, cfg.baseUrl);
|
|
||||||
const timeout = resolveTimeout(options.timeout, cfg.timeout);
|
|
||||||
const verifyTls = resolveVerifyTls(options.verify_tls, cfg.verifyTls);
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
Accept: "application/json",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
[cfg.projectHeader]: cfg.projectUuid,
|
|
||||||
};
|
|
||||||
if (Array.isArray(options.headers)) {
|
|
||||||
for (const header of options.headers) {
|
|
||||||
if (typeof header === "string" && header.includes(":")) {
|
|
||||||
const [name, value] = header.split(":", 2);
|
|
||||||
headers[name.trim()] = value.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = JSON.stringify(bodyPayload);
|
|
||||||
return sendRequest(url, "POST", body, headers, timeout, verifyTls);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchStatus(aiRequestId, options = {}) {
|
|
||||||
const cfg = config();
|
|
||||||
if (!cfg.projectUuid) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: "project_uuid_missing",
|
|
||||||
message: "PROJECT_UUID is not defined; aborting status check.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusPath = resolveStatusPath(aiRequestId, cfg);
|
|
||||||
const url = buildUrl(statusPath, cfg.baseUrl);
|
|
||||||
const timeout = resolveTimeout(options.timeout, cfg.timeout);
|
|
||||||
const verifyTls = resolveVerifyTls(options.verify_tls, cfg.verifyTls);
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
Accept: "application/json",
|
|
||||||
[cfg.projectHeader]: cfg.projectUuid,
|
|
||||||
};
|
|
||||||
if (Array.isArray(options.headers)) {
|
|
||||||
for (const header of options.headers) {
|
|
||||||
if (typeof header === "string" && header.includes(":")) {
|
|
||||||
const [name, value] = header.split(":", 2);
|
|
||||||
headers[name.trim()] = value.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sendRequest(url, "GET", null, headers, timeout, verifyTls);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function awaitResponse(aiRequestId, options = {}) {
|
|
||||||
const timeout = Number(options.timeout ?? 300);
|
|
||||||
const interval = Math.max(Number(options.interval ?? 5), 1);
|
|
||||||
const deadline = Date.now() + Math.max(timeout, interval) * 1000;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const statusResp = await fetchStatus(aiRequestId, {
|
|
||||||
headers: options.headers,
|
|
||||||
timeout: options.timeout_per_call,
|
|
||||||
verify_tls: options.verify_tls,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (statusResp.success) {
|
|
||||||
const data = statusResp.data || {};
|
|
||||||
if (data && typeof data === "object") {
|
|
||||||
if (data.status === "success") {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
status: 200,
|
|
||||||
data: data.response || data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (data.status === "failed") {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
status: 500,
|
|
||||||
error: String(data.error || "AI request failed"),
|
|
||||||
data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return statusResp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Date.now() >= deadline) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: "timeout",
|
|
||||||
message: "Timed out waiting for AI response.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
await sleep(interval * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractText(response) {
|
|
||||||
const payload = response && typeof response === "object" ? response.data || response : null;
|
|
||||||
if (!payload || typeof payload !== "object") {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(payload.output)) {
|
|
||||||
let combined = "";
|
|
||||||
for (const item of payload.output) {
|
|
||||||
if (!item || !Array.isArray(item.content)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const block of item.content) {
|
|
||||||
if (
|
|
||||||
block &&
|
|
||||||
typeof block === "object" &&
|
|
||||||
block.type === "output_text" &&
|
|
||||||
typeof block.text === "string" &&
|
|
||||||
block.text.length > 0
|
|
||||||
) {
|
|
||||||
combined += block.text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (combined) {
|
|
||||||
return combined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
payload.choices &&
|
|
||||||
payload.choices[0] &&
|
|
||||||
payload.choices[0].message &&
|
|
||||||
typeof payload.choices[0].message.content === "string"
|
|
||||||
) {
|
|
||||||
return payload.choices[0].message.content;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function decodeJsonFromResponse(response) {
|
|
||||||
const text = extractText(response);
|
|
||||||
if (!text) {
|
|
||||||
throw new Error("No text found in AI response.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsed = parseJson(text);
|
|
||||||
if (parsed.ok && parsed.value && typeof parsed.value === "object") {
|
|
||||||
return parsed.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const stripped = stripJsonFence(text);
|
|
||||||
if (stripped !== text) {
|
|
||||||
const parsedStripped = parseJson(stripped);
|
|
||||||
if (parsedStripped.ok && parsedStripped.value && typeof parsedStripped.value === "object") {
|
|
||||||
return parsedStripped.value;
|
|
||||||
}
|
|
||||||
throw new Error(`JSON parse failed after stripping fences: ${parsedStripped.error}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`JSON parse failed: ${parsed.error}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function config() {
|
|
||||||
if (CONFIG_CACHE) {
|
|
||||||
return CONFIG_CACHE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureEnvLoaded();
|
|
||||||
|
|
||||||
const baseUrl = process.env.AI_PROXY_BASE_URL || "https://flatlogic.com";
|
|
||||||
const projectId = process.env.PROJECT_ID || null;
|
|
||||||
let responsesPath = process.env.AI_RESPONSES_PATH || null;
|
|
||||||
if (!responsesPath && projectId) {
|
|
||||||
responsesPath = `/projects/${projectId}/ai-request`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeout = resolveTimeout(process.env.AI_TIMEOUT, 30);
|
|
||||||
const verifyTls = resolveVerifyTls(process.env.AI_VERIFY_TLS, true);
|
|
||||||
|
|
||||||
CONFIG_CACHE = {
|
|
||||||
baseUrl,
|
|
||||||
responsesPath,
|
|
||||||
projectId,
|
|
||||||
projectUuid: process.env.PROJECT_UUID || null,
|
|
||||||
projectHeader: process.env.AI_PROJECT_HEADER || "project-uuid",
|
|
||||||
defaultModel: process.env.AI_DEFAULT_MODEL || "gpt-5-mini",
|
|
||||||
timeout,
|
|
||||||
verifyTls,
|
|
||||||
};
|
|
||||||
|
|
||||||
return CONFIG_CACHE;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildUrl(pathValue, baseUrl) {
|
|
||||||
const trimmed = String(pathValue || "").trim();
|
|
||||||
if (trimmed === "") {
|
|
||||||
return baseUrl;
|
|
||||||
}
|
|
||||||
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
|
|
||||||
return trimmed;
|
|
||||||
}
|
|
||||||
if (trimmed.startsWith("/")) {
|
|
||||||
return `${baseUrl}${trimmed}`;
|
|
||||||
}
|
|
||||||
return `${baseUrl}/${trimmed}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveStatusPath(aiRequestId, cfg) {
|
|
||||||
const basePath = (cfg.responsesPath || "").replace(/\/+$/, "");
|
|
||||||
if (!basePath) {
|
|
||||||
return `/ai-request/${encodeURIComponent(String(aiRequestId))}/status`;
|
|
||||||
}
|
|
||||||
const normalized = basePath.endsWith("/ai-request") ? basePath : `${basePath}/ai-request`;
|
|
||||||
return `${normalized}/${encodeURIComponent(String(aiRequestId))}/status`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendRequest(urlString, method, body, headers, timeoutSeconds, verifyTls) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
let targetUrl;
|
|
||||||
try {
|
|
||||||
targetUrl = new URL(urlString);
|
|
||||||
} catch (err) {
|
|
||||||
resolve({
|
|
||||||
success: false,
|
|
||||||
error: "invalid_url",
|
|
||||||
message: err.message,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isHttps = targetUrl.protocol === "https:";
|
|
||||||
const requestFn = isHttps ? https.request : http.request;
|
|
||||||
const options = {
|
|
||||||
protocol: targetUrl.protocol,
|
|
||||||
hostname: targetUrl.hostname,
|
|
||||||
port: targetUrl.port || (isHttps ? 443 : 80),
|
|
||||||
path: `${targetUrl.pathname}${targetUrl.search}`,
|
|
||||||
method: method.toUpperCase(),
|
|
||||||
headers,
|
|
||||||
timeout: Math.max(Number(timeoutSeconds || 30), 1) * 1000,
|
|
||||||
};
|
|
||||||
if (isHttps) {
|
|
||||||
options.rejectUnauthorized = Boolean(verifyTls);
|
|
||||||
}
|
|
||||||
|
|
||||||
const req = requestFn(options, (res) => {
|
|
||||||
let responseBody = "";
|
|
||||||
res.setEncoding("utf8");
|
|
||||||
res.on("data", (chunk) => {
|
|
||||||
responseBody += chunk;
|
|
||||||
});
|
|
||||||
res.on("end", () => {
|
|
||||||
const status = res.statusCode || 0;
|
|
||||||
const parsed = parseJson(responseBody);
|
|
||||||
const payload = parsed.ok ? parsed.value : responseBody;
|
|
||||||
|
|
||||||
if (status >= 200 && status < 300) {
|
|
||||||
const result = {
|
|
||||||
success: true,
|
|
||||||
status,
|
|
||||||
data: payload,
|
|
||||||
};
|
|
||||||
if (!parsed.ok) {
|
|
||||||
result.json_error = parsed.error;
|
|
||||||
}
|
|
||||||
resolve(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorMessage =
|
|
||||||
parsed.ok && payload && typeof payload === "object"
|
|
||||||
? String(payload.error || payload.message || "AI proxy request failed")
|
|
||||||
: String(responseBody || "AI proxy request failed");
|
|
||||||
|
|
||||||
resolve({
|
|
||||||
success: false,
|
|
||||||
status,
|
|
||||||
error: errorMessage,
|
|
||||||
response: payload,
|
|
||||||
json_error: parsed.ok ? undefined : parsed.error,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on("timeout", () => {
|
|
||||||
req.destroy(new Error("request_timeout"));
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on("error", (err) => {
|
|
||||||
resolve({
|
|
||||||
success: false,
|
|
||||||
error: "request_failed",
|
|
||||||
message: err.message,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (body) {
|
|
||||||
req.write(body);
|
|
||||||
}
|
|
||||||
req.end();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseJson(value) {
|
|
||||||
if (typeof value !== "string" || value.trim() === "") {
|
|
||||||
return { ok: false, error: "empty_response" };
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return { ok: true, value: JSON.parse(value) };
|
|
||||||
} catch (err) {
|
|
||||||
return { ok: false, error: err.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stripJsonFence(text) {
|
|
||||||
const trimmed = text.trim();
|
|
||||||
if (trimmed.startsWith("```json")) {
|
|
||||||
return trimmed.replace(/^```json/, "").replace(/```$/, "").trim();
|
|
||||||
}
|
|
||||||
if (trimmed.startsWith("```")) {
|
|
||||||
return trimmed.replace(/^```/, "").replace(/```$/, "").trim();
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveTimeout(value, fallback) {
|
|
||||||
const parsed = Number.parseInt(String(value ?? fallback), 10);
|
|
||||||
return Number.isNaN(parsed) ? Number(fallback) : parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveVerifyTls(value, fallback) {
|
|
||||||
if (value === undefined || value === null) {
|
|
||||||
return Boolean(fallback);
|
|
||||||
}
|
|
||||||
return String(value).toLowerCase() !== "false" && String(value) !== "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureEnvLoaded() {
|
|
||||||
if (process.env.PROJECT_UUID && process.env.PROJECT_ID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const envPath = path.resolve(__dirname, "../../../../.env");
|
|
||||||
if (!fs.existsSync(envPath)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let content;
|
|
||||||
try {
|
|
||||||
content = fs.readFileSync(envPath, "utf8");
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(`Failed to read executor .env: ${err.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const line of content.split(/\r?\n/)) {
|
|
||||||
const trimmed = line.trim();
|
|
||||||
if (!trimmed || trimmed.startsWith("#") || !trimmed.includes("=")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const [rawKey, ...rest] = trimmed.split("=");
|
|
||||||
const key = rawKey.trim();
|
|
||||||
if (!key) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const value = rest.join("=").trim().replace(/^['"]|['"]$/g, "");
|
|
||||||
if (!process.env[key]) {
|
|
||||||
process.env[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sleep(ms) {
|
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
LocalAIApi,
|
|
||||||
createResponse,
|
|
||||||
request,
|
|
||||||
fetchStatus,
|
|
||||||
awaitResponse,
|
|
||||||
extractText,
|
|
||||||
decodeJsonFromResponse,
|
|
||||||
};
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
const config = require('../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const helpers = require('../helpers');
|
|
||||||
const db = require('../db/models');
|
|
||||||
|
|
||||||
const passport = require('passport');
|
|
||||||
const JWTstrategy = require('passport-jwt').Strategy;
|
|
||||||
const ExtractJWT = require('passport-jwt').ExtractJwt;
|
|
||||||
const GoogleStrategy = require('passport-google-oauth2').Strategy;
|
|
||||||
const MicrosoftStrategy = require('passport-microsoft').Strategy;
|
|
||||||
const UsersDBApi = require('../db/api/users');
|
|
||||||
|
|
||||||
|
|
||||||
passport.use(new JWTstrategy({
|
|
||||||
passReqToCallback: true,
|
|
||||||
secretOrKey: config.secret_key,
|
|
||||||
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken()
|
|
||||||
}, async (req, token, done) => {
|
|
||||||
try {
|
|
||||||
const user = await UsersDBApi.findBy( {email: token.user.email});
|
|
||||||
|
|
||||||
if (user && user.disabled) {
|
|
||||||
return done (new Error(`User '${user.email}' is disabled`));
|
|
||||||
}
|
|
||||||
|
|
||||||
req.currentUser = user;
|
|
||||||
|
|
||||||
return done(null, user);
|
|
||||||
} catch (error) {
|
|
||||||
done(error);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
passport.use(new GoogleStrategy({
|
|
||||||
clientID: config.google.clientId,
|
|
||||||
clientSecret: config.google.clientSecret,
|
|
||||||
callbackURL: config.apiUrl + '/auth/signin/google/callback',
|
|
||||||
passReqToCallback: true
|
|
||||||
},
|
|
||||||
function (request, accessToken, refreshToken, profile, done) {
|
|
||||||
socialStrategy(profile.email, profile, providers.GOOGLE, done);
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
passport.use(new MicrosoftStrategy({
|
|
||||||
clientID: config.microsoft.clientId,
|
|
||||||
clientSecret: config.microsoft.clientSecret,
|
|
||||||
callbackURL: config.apiUrl + '/auth/signin/microsoft/callback',
|
|
||||||
passReqToCallback: true
|
|
||||||
},
|
|
||||||
function (request, accessToken, refreshToken, profile, done) {
|
|
||||||
const email = profile._json.mail || profile._json.userPrincipalName;
|
|
||||||
socialStrategy(email, profile, providers.MICROSOFT, done);
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
function socialStrategy(email, profile, provider, done) {
|
|
||||||
db.users.findOrCreate({where: {email, provider}}).then(([user, created]) => {
|
|
||||||
const body = {
|
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
name: profile.displayName,
|
|
||||||
};
|
|
||||||
const token = helpers.jwtSign({user: body});
|
|
||||||
return done(null, {token});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const os = require('os');
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
gcloud: {
|
|
||||||
bucket: "fldemo-files",
|
|
||||||
hash: "afeefb9d49f5b7977577876b99532ac7"
|
|
||||||
},
|
|
||||||
bcrypt: {
|
|
||||||
saltRounds: 12
|
|
||||||
},
|
|
||||||
admin_pass: "02f73895",
|
|
||||||
user_pass: "5acefd8fd4d0",
|
|
||||||
admin_email: "admin@flatlogic.com",
|
|
||||||
providers: {
|
|
||||||
LOCAL: 'local',
|
|
||||||
GOOGLE: 'google',
|
|
||||||
MICROSOFT: 'microsoft'
|
|
||||||
},
|
|
||||||
secret_key: process.env.SECRET_KEY || '02f73895-cabe-4aa2-94ec-5acefd8fd4d0',
|
|
||||||
remote: '',
|
|
||||||
port: process.env.NODE_ENV === "production" ? "" : "8080",
|
|
||||||
hostUI: process.env.NODE_ENV === "production" ? "" : "http://localhost",
|
|
||||||
portUI: process.env.NODE_ENV === "production" ? "" : "3000",
|
|
||||||
|
|
||||||
portUIProd: process.env.NODE_ENV === "production" ? "" : ":3000",
|
|
||||||
|
|
||||||
swaggerUI: process.env.NODE_ENV === "production" ? "" : "http://localhost",
|
|
||||||
swaggerPort: process.env.NODE_ENV === "production" ? "" : ":8080",
|
|
||||||
google: {
|
|
||||||
clientId: process.env.GOOGLE_CLIENT_ID || '',
|
|
||||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
|
|
||||||
},
|
|
||||||
microsoft: {
|
|
||||||
clientId: process.env.MS_CLIENT_ID || '',
|
|
||||||
clientSecret: process.env.MS_CLIENT_SECRET || '',
|
|
||||||
},
|
|
||||||
uploadDir: os.tmpdir(),
|
|
||||||
email: {
|
|
||||||
from: 'Blackness Studio Website <app@flatlogic.app>',
|
|
||||||
host: 'email-smtp.us-east-1.amazonaws.com',
|
|
||||||
port: 587,
|
|
||||||
auth: {
|
|
||||||
user: process.env.EMAIL_USER || '',
|
|
||||||
pass: process.env.EMAIL_PASS,
|
|
||||||
},
|
|
||||||
tls: {
|
|
||||||
rejectUnauthorized: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
roles: {
|
|
||||||
|
|
||||||
admin: 'Administrator',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
user: 'Analytics Viewer',
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
project_uuid: '02f73895-cabe-4aa2-94ec-5acefd8fd4d0',
|
|
||||||
flHost: process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'dev_stage' ? 'https://flatlogic.com/projects' : 'http://localhost:3000/projects',
|
|
||||||
|
|
||||||
|
|
||||||
gpt_key: process.env.GPT_KEY || '',
|
|
||||||
};
|
|
||||||
|
|
||||||
config.pexelsKey = process.env.PEXELS_KEY || '';
|
|
||||||
|
|
||||||
config.pexelsQuery = 'Abstract gold light trails';
|
|
||||||
config.host = process.env.NODE_ENV === "production" ? config.remote : "http://localhost";
|
|
||||||
config.apiUrl = `${config.host}${config.port ? `:${config.port}` : ``}/api`;
|
|
||||||
config.swaggerUrl = `${config.swaggerUI}${config.swaggerPort}`;
|
|
||||||
config.uiUrl = `${config.hostUI}${config.portUI ? `:${config.portUI}` : ``}/#`;
|
|
||||||
config.backUrl = `${config.hostUI}${config.portUI ? `:${config.portUI}` : ``}`;
|
|
||||||
|
|
||||||
module.exports = config;
|
|
||||||
@ -1,446 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class BenefitsDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const benefits = await db.benefits.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
title: data.title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
description: data.description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
icon_name: data.icon_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: data.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: data.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return benefits;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const benefitsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
title: item.title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
description: item.description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
icon_name: item.icon_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: item.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const benefits = await db.benefits.bulkCreate(benefitsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return benefits;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const benefits = await db.benefits.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.title !== undefined) updatePayload.title = data.title;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.description !== undefined) updatePayload.description = data.description;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.icon_name !== undefined) updatePayload.icon_name = data.icon_name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_active !== undefined) updatePayload.is_active = data.is_active;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await benefits.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return benefits;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const benefits = await db.benefits.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of benefits) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of benefits) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return benefits;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const benefits = await db.benefits.findByPk(id, options);
|
|
||||||
|
|
||||||
await benefits.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await benefits.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return benefits;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const benefits = await db.benefits.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!benefits) {
|
|
||||||
return benefits;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = benefits.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.title) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'benefits',
|
|
||||||
'title',
|
|
||||||
filter.title,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.description) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'benefits',
|
|
||||||
'description',
|
|
||||||
filter.description,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.icon_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'benefits',
|
|
||||||
'icon_name',
|
|
||||||
filter.icon_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.is_active) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_active: filter.is_active,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.benefits.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'benefits',
|
|
||||||
'title',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.benefits.findAll({
|
|
||||||
attributes: [ 'id', 'title' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['title', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.title,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
const db = require('../models');
|
|
||||||
const assert = require('assert');
|
|
||||||
const services = require('../../services/file');
|
|
||||||
|
|
||||||
module.exports = class FileDBApi {
|
|
||||||
static async replaceRelationFiles(
|
|
||||||
relation,
|
|
||||||
rawFiles,
|
|
||||||
options,
|
|
||||||
) {
|
|
||||||
assert(relation.belongsTo, 'belongsTo is required');
|
|
||||||
assert(
|
|
||||||
relation.belongsToColumn,
|
|
||||||
'belongsToColumn is required',
|
|
||||||
);
|
|
||||||
assert(relation.belongsToId, 'belongsToId is required');
|
|
||||||
|
|
||||||
let files = [];
|
|
||||||
|
|
||||||
if (Array.isArray(rawFiles)) {
|
|
||||||
files = rawFiles;
|
|
||||||
} else {
|
|
||||||
files = rawFiles ? [rawFiles] : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
await this._removeLegacyFiles(relation, files, options);
|
|
||||||
await this._addFiles(relation, files, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async _addFiles(relation, files, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
|
|
||||||
const inexistentFiles = files.filter(
|
|
||||||
(file) => !!file.new,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const file of inexistentFiles) {
|
|
||||||
await db.file.create(
|
|
||||||
{
|
|
||||||
belongsTo: relation.belongsTo,
|
|
||||||
belongsToColumn: relation.belongsToColumn,
|
|
||||||
belongsToId: relation.belongsToId,
|
|
||||||
name: file.name,
|
|
||||||
sizeInBytes: file.sizeInBytes,
|
|
||||||
privateUrl: file.privateUrl,
|
|
||||||
publicUrl: file.publicUrl,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async _removeLegacyFiles(
|
|
||||||
relation,
|
|
||||||
files,
|
|
||||||
options,
|
|
||||||
) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const filesToDelete = await db.file.findAll({
|
|
||||||
where: {
|
|
||||||
belongsTo: relation.belongsTo,
|
|
||||||
belongsToId: relation.belongsToId,
|
|
||||||
belongsToColumn: relation.belongsToColumn,
|
|
||||||
id: {
|
|
||||||
[db.Sequelize.Op
|
|
||||||
.notIn]: files
|
|
||||||
.filter((file) => !file.new)
|
|
||||||
.map((file) => file.id)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
for (let file of filesToDelete) {
|
|
||||||
await services.deleteGCloud(file.privateUrl);
|
|
||||||
await file.destroy({
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,614 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class InquiriesDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const inquiries = await db.inquiries.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
full_name: data.full_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
email: data.email
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
company_name: data.company_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
subject: data.subject
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
message: data.message
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source_page: data.source_page
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
status: data.status
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
received_at: data.received_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
replied_at: data.replied_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
fiverr_url: data.fiverr_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
await inquiries.setAssigned_to( data.assigned_to || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return inquiries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const inquiriesData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
full_name: item.full_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
email: item.email
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
company_name: item.company_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
subject: item.subject
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
message: item.message
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source_page: item.source_page
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
status: item.status
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
received_at: item.received_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
replied_at: item.replied_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
fiverr_url: item.fiverr_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const inquiries = await db.inquiries.bulkCreate(inquiriesData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return inquiries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const inquiries = await db.inquiries.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.full_name !== undefined) updatePayload.full_name = data.full_name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.email !== undefined) updatePayload.email = data.email;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.company_name !== undefined) updatePayload.company_name = data.company_name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.subject !== undefined) updatePayload.subject = data.subject;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.message !== undefined) updatePayload.message = data.message;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.source_page !== undefined) updatePayload.source_page = data.source_page;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.status !== undefined) updatePayload.status = data.status;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.received_at !== undefined) updatePayload.received_at = data.received_at;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.replied_at !== undefined) updatePayload.replied_at = data.replied_at;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.fiverr_url !== undefined) updatePayload.fiverr_url = data.fiverr_url;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await inquiries.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.assigned_to !== undefined) {
|
|
||||||
await inquiries.setAssigned_to(
|
|
||||||
|
|
||||||
data.assigned_to,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return inquiries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const inquiries = await db.inquiries.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of inquiries) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of inquiries) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return inquiries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const inquiries = await db.inquiries.findByPk(id, options);
|
|
||||||
|
|
||||||
await inquiries.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await inquiries.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return inquiries;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const inquiries = await db.inquiries.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!inquiries) {
|
|
||||||
return inquiries;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = inquiries.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.assigned_to = await inquiries.getAssigned_to({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.users,
|
|
||||||
as: 'assigned_to',
|
|
||||||
|
|
||||||
where: filter.assigned_to ? {
|
|
||||||
[Op.or]: [
|
|
||||||
{ id: { [Op.in]: filter.assigned_to.split('|').map(term => Utils.uuid(term)) } },
|
|
||||||
{
|
|
||||||
firstName: {
|
|
||||||
[Op.or]: filter.assigned_to.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
} : {},
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.full_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'full_name',
|
|
||||||
filter.full_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.email) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'email',
|
|
||||||
filter.email,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.company_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'company_name',
|
|
||||||
filter.company_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.subject) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'subject',
|
|
||||||
filter.subject,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.message) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'message',
|
|
||||||
filter.message,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.source_page) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'source_page',
|
|
||||||
filter.source_page,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.fiverr_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'fiverr_url',
|
|
||||||
filter.fiverr_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.received_atRange) {
|
|
||||||
const [start, end] = filter.received_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
received_at: {
|
|
||||||
...where.received_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
received_at: {
|
|
||||||
...where.received_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.replied_atRange) {
|
|
||||||
const [start, end] = filter.replied_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
replied_at: {
|
|
||||||
...where.replied_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
replied_at: {
|
|
||||||
...where.replied_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.status) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
status: filter.status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.inquiries.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'inquiries',
|
|
||||||
'subject',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.inquiries.findAll({
|
|
||||||
attributes: [ 'id', 'subject' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['subject', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.subject,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,665 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class Page_sectionsDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_sections = await db.page_sections.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
section_type: data.section_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
section_label: data.section_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
headline: data.headline
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
subheadline: data.subheadline
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
body: data.body
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_button_label: data.primary_button_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_button_url: data.primary_button_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
secondary_button_label: data.secondary_button_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
secondary_button_url: data.secondary_button_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: data.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_visible: data.is_visible
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
await page_sections.setPage( data.page || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.page_sections.getTableName(),
|
|
||||||
belongsToColumn: 'background_images',
|
|
||||||
belongsToId: page_sections.id,
|
|
||||||
},
|
|
||||||
data.background_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return page_sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const page_sectionsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
section_type: item.section_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
section_label: item.section_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
headline: item.headline
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
subheadline: item.subheadline
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
body: item.body
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_button_label: item.primary_button_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_button_url: item.primary_button_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
secondary_button_label: item.secondary_button_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
secondary_button_url: item.secondary_button_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_visible: item.is_visible
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const page_sections = await db.page_sections.bulkCreate(page_sectionsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
for (let i = 0; i < page_sections.length; i++) {
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.page_sections.getTableName(),
|
|
||||||
belongsToColumn: 'background_images',
|
|
||||||
belongsToId: page_sections[i].id,
|
|
||||||
},
|
|
||||||
data[i].background_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return page_sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const page_sections = await db.page_sections.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.section_type !== undefined) updatePayload.section_type = data.section_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.section_label !== undefined) updatePayload.section_label = data.section_label;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.headline !== undefined) updatePayload.headline = data.headline;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.subheadline !== undefined) updatePayload.subheadline = data.subheadline;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.body !== undefined) updatePayload.body = data.body;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.primary_button_label !== undefined) updatePayload.primary_button_label = data.primary_button_label;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.primary_button_url !== undefined) updatePayload.primary_button_url = data.primary_button_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.secondary_button_label !== undefined) updatePayload.secondary_button_label = data.secondary_button_label;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.secondary_button_url !== undefined) updatePayload.secondary_button_url = data.secondary_button_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_visible !== undefined) updatePayload.is_visible = data.is_visible;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await page_sections.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.page !== undefined) {
|
|
||||||
await page_sections.setPage(
|
|
||||||
|
|
||||||
data.page,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.page_sections.getTableName(),
|
|
||||||
belongsToColumn: 'background_images',
|
|
||||||
belongsToId: page_sections.id,
|
|
||||||
},
|
|
||||||
data.background_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return page_sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_sections = await db.page_sections.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of page_sections) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of page_sections) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return page_sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_sections = await db.page_sections.findByPk(id, options);
|
|
||||||
|
|
||||||
await page_sections.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await page_sections.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return page_sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_sections = await db.page_sections.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!page_sections) {
|
|
||||||
return page_sections;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = page_sections.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.page = await page_sections.getPage({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.background_images = await page_sections.getBackground_images({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.pages,
|
|
||||||
as: 'page',
|
|
||||||
|
|
||||||
where: filter.page ? {
|
|
||||||
[Op.or]: [
|
|
||||||
{ id: { [Op.in]: filter.page.split('|').map(term => Utils.uuid(term)) } },
|
|
||||||
{
|
|
||||||
title: {
|
|
||||||
[Op.or]: filter.page.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
} : {},
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.file,
|
|
||||||
as: 'background_images',
|
|
||||||
},
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.section_label) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'section_label',
|
|
||||||
filter.section_label,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.headline) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'headline',
|
|
||||||
filter.headline,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.subheadline) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'subheadline',
|
|
||||||
filter.subheadline,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.body) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'body',
|
|
||||||
filter.body,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.primary_button_label) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'primary_button_label',
|
|
||||||
filter.primary_button_label,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.primary_button_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'primary_button_url',
|
|
||||||
filter.primary_button_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.secondary_button_label) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'secondary_button_label',
|
|
||||||
filter.secondary_button_label,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.secondary_button_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'secondary_button_url',
|
|
||||||
filter.secondary_button_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.section_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
section_type: filter.section_type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_visible) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_visible: filter.is_visible,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.page_sections.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'page_sections',
|
|
||||||
'section_label',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.page_sections.findAll({
|
|
||||||
attributes: [ 'id', 'section_label' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['section_label', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.section_label,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,553 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class PagesDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const pages = await db.pages.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
title: data.title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
slug: data.slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
status: data.status
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: data.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
meta_title: data.meta_title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
meta_description: data.meta_description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
show_in_header_nav: data.show_in_header_nav
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
show_in_footer_nav: data.show_in_footer_nav
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
await pages.setAuthor( data.author || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const pagesData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
title: item.title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
slug: item.slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
status: item.status
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
meta_title: item.meta_title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
meta_description: item.meta_description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
show_in_header_nav: item.show_in_header_nav
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
show_in_footer_nav: item.show_in_footer_nav
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const pages = await db.pages.bulkCreate(pagesData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const pages = await db.pages.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.title !== undefined) updatePayload.title = data.title;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.slug !== undefined) updatePayload.slug = data.slug;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.status !== undefined) updatePayload.status = data.status;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.meta_title !== undefined) updatePayload.meta_title = data.meta_title;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.meta_description !== undefined) updatePayload.meta_description = data.meta_description;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.show_in_header_nav !== undefined) updatePayload.show_in_header_nav = data.show_in_header_nav;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.show_in_footer_nav !== undefined) updatePayload.show_in_footer_nav = data.show_in_footer_nav;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await pages.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.author !== undefined) {
|
|
||||||
await pages.setAuthor(
|
|
||||||
|
|
||||||
data.author,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const pages = await db.pages.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of pages) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of pages) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const pages = await db.pages.findByPk(id, options);
|
|
||||||
|
|
||||||
await pages.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await pages.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const pages = await db.pages.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!pages) {
|
|
||||||
return pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = pages.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.page_sections_page = await pages.getPage_sections_page({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.author = await pages.getAuthor({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.users,
|
|
||||||
as: 'author',
|
|
||||||
|
|
||||||
where: filter.author ? {
|
|
||||||
[Op.or]: [
|
|
||||||
{ id: { [Op.in]: filter.author.split('|').map(term => Utils.uuid(term)) } },
|
|
||||||
{
|
|
||||||
firstName: {
|
|
||||||
[Op.or]: filter.author.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
} : {},
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.title) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'pages',
|
|
||||||
'title',
|
|
||||||
filter.title,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.slug) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'pages',
|
|
||||||
'slug',
|
|
||||||
filter.slug,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.meta_title) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'pages',
|
|
||||||
'meta_title',
|
|
||||||
filter.meta_title,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.meta_description) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'pages',
|
|
||||||
'meta_description',
|
|
||||||
filter.meta_description,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.status) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
status: filter.status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.show_in_header_nav) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
show_in_header_nav: filter.show_in_header_nav,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.show_in_footer_nav) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
show_in_footer_nav: filter.show_in_footer_nav,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.pages.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'pages',
|
|
||||||
'title',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.pages.findAll({
|
|
||||||
attributes: [ 'id', 'title' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['title', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.title,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,339 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class PermissionsDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const permissions = await db.permissions.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
name: data.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const permissionsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const permissions = await db.permissions.bulkCreate(permissionsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await permissions.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of permissions) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of permissions) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findByPk(id, options);
|
|
||||||
|
|
||||||
await permissions.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await permissions.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!permissions) {
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = permissions.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'permissions',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.permissions.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'permissions',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.permissions.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,644 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class Portfolio_itemsDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const portfolio_items = await db.portfolio_items.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
title: data.title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
work_type: data.work_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
client_name: data.client_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
summary: data.summary
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
case_study: data.case_study
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
external_url: data.external_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
tech_stack: data.tech_stack
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
published_on: data.published_on
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: data.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
is_public: data.is_public
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'screenshots',
|
|
||||||
belongsToId: portfolio_items.id,
|
|
||||||
},
|
|
||||||
data.screenshots,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'attachments',
|
|
||||||
belongsToId: portfolio_items.id,
|
|
||||||
},
|
|
||||||
data.attachments,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return portfolio_items;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const portfolio_itemsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
title: item.title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
work_type: item.work_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
client_name: item.client_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
summary: item.summary
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
case_study: item.case_study
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
external_url: item.external_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
tech_stack: item.tech_stack
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
published_on: item.published_on
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: item.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
is_public: item.is_public
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const portfolio_items = await db.portfolio_items.bulkCreate(portfolio_itemsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
for (let i = 0; i < portfolio_items.length; i++) {
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'screenshots',
|
|
||||||
belongsToId: portfolio_items[i].id,
|
|
||||||
},
|
|
||||||
data[i].screenshots,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < portfolio_items.length; i++) {
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'attachments',
|
|
||||||
belongsToId: portfolio_items[i].id,
|
|
||||||
},
|
|
||||||
data[i].attachments,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return portfolio_items;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const portfolio_items = await db.portfolio_items.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.title !== undefined) updatePayload.title = data.title;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.work_type !== undefined) updatePayload.work_type = data.work_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.client_name !== undefined) updatePayload.client_name = data.client_name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.summary !== undefined) updatePayload.summary = data.summary;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.case_study !== undefined) updatePayload.case_study = data.case_study;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.external_url !== undefined) updatePayload.external_url = data.external_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.tech_stack !== undefined) updatePayload.tech_stack = data.tech_stack;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.published_on !== undefined) updatePayload.published_on = data.published_on;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_featured !== undefined) updatePayload.is_featured = data.is_featured;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_public !== undefined) updatePayload.is_public = data.is_public;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await portfolio_items.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'screenshots',
|
|
||||||
belongsToId: portfolio_items.id,
|
|
||||||
},
|
|
||||||
data.screenshots,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'attachments',
|
|
||||||
belongsToId: portfolio_items.id,
|
|
||||||
},
|
|
||||||
data.attachments,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return portfolio_items;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const portfolio_items = await db.portfolio_items.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of portfolio_items) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of portfolio_items) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return portfolio_items;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const portfolio_items = await db.portfolio_items.findByPk(id, options);
|
|
||||||
|
|
||||||
await portfolio_items.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await portfolio_items.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return portfolio_items;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const portfolio_items = await db.portfolio_items.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!portfolio_items) {
|
|
||||||
return portfolio_items;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = portfolio_items.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.screenshots = await portfolio_items.getScreenshots({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.attachments = await portfolio_items.getAttachments({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.file,
|
|
||||||
as: 'screenshots',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.file,
|
|
||||||
as: 'attachments',
|
|
||||||
},
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.title) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'portfolio_items',
|
|
||||||
'title',
|
|
||||||
filter.title,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.client_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'portfolio_items',
|
|
||||||
'client_name',
|
|
||||||
filter.client_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.summary) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'portfolio_items',
|
|
||||||
'summary',
|
|
||||||
filter.summary,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.case_study) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'portfolio_items',
|
|
||||||
'case_study',
|
|
||||||
filter.case_study,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.external_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'portfolio_items',
|
|
||||||
'external_url',
|
|
||||||
filter.external_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.tech_stack) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'portfolio_items',
|
|
||||||
'tech_stack',
|
|
||||||
filter.tech_stack,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.published_onRange) {
|
|
||||||
const [start, end] = filter.published_onRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
published_on: {
|
|
||||||
...where.published_on,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
published_on: {
|
|
||||||
...where.published_on,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.work_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
work_type: filter.work_type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_featured) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_featured: filter.is_featured,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_public) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_public: filter.is_public,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.portfolio_items.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'portfolio_items',
|
|
||||||
'title',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.portfolio_items.findAll({
|
|
||||||
attributes: [ 'id', 'title' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['title', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.title,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,409 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class RolesDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const roles = await db.roles.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
name: data.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
role_customization: data.role_customization
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await roles.setPermissions(data.permissions || [], {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const rolesData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
role_customization: item.role_customization
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const roles = await db.roles.bulkCreate(rolesData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const roles = await db.roles.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.role_customization !== undefined) updatePayload.role_customization = data.role_customization;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await roles.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.permissions !== undefined) {
|
|
||||||
await roles.setPermissions(data.permissions, { transaction });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const roles = await db.roles.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of roles) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of roles) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const roles = await db.roles.findByPk(id, options);
|
|
||||||
|
|
||||||
await roles.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await roles.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const roles = await db.roles.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!roles) {
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = roles.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
output.users_app_role = await roles.getUsers_app_role({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.permissions = await roles.getPermissions({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.permissions,
|
|
||||||
as: 'permissions',
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'roles',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.role_customization) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'roles',
|
|
||||||
'role_customization',
|
|
||||||
filter.role_customization,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.permissions) {
|
|
||||||
const searchTerms = filter.permissions.split('|');
|
|
||||||
|
|
||||||
include = [
|
|
||||||
{
|
|
||||||
model: db.permissions,
|
|
||||||
as: 'permissions_filter',
|
|
||||||
required: searchTerms.length > 0,
|
|
||||||
where: searchTerms.length > 0 ? {
|
|
||||||
[Op.or]: [
|
|
||||||
{ id: { [Op.in]: searchTerms.map(term => Utils.uuid(term)) } },
|
|
||||||
{
|
|
||||||
name: {
|
|
||||||
[Op.or]: searchTerms.map(term => ({ [Op.iLike]: `%${term}%` }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} : undefined
|
|
||||||
},
|
|
||||||
...include,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.roles.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'roles',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.roles.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,560 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class ServicesDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const services = await db.services.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
name: data.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
short_description: data.short_description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
details: data.details
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
category: data.category
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: data.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: data.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: data.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
cta_label: data.cta_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
cta_url: data.cta_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
icon_name: data.icon_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const servicesData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
short_description: item.short_description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
details: item.details
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
category: item.category
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: item.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: item.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
cta_label: item.cta_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
cta_url: item.cta_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
icon_name: item.icon_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const services = await db.services.bulkCreate(servicesData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const services = await db.services.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.short_description !== undefined) updatePayload.short_description = data.short_description;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.details !== undefined) updatePayload.details = data.details;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.category !== undefined) updatePayload.category = data.category;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_featured !== undefined) updatePayload.is_featured = data.is_featured;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_active !== undefined) updatePayload.is_active = data.is_active;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.cta_label !== undefined) updatePayload.cta_label = data.cta_label;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.cta_url !== undefined) updatePayload.cta_url = data.cta_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.icon_name !== undefined) updatePayload.icon_name = data.icon_name;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await services.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const services = await db.services.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of services) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of services) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const services = await db.services.findByPk(id, options);
|
|
||||||
|
|
||||||
await services.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await services.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const services = await db.services.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!services) {
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = services.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'services',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.short_description) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'services',
|
|
||||||
'short_description',
|
|
||||||
filter.short_description,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.details) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'services',
|
|
||||||
'details',
|
|
||||||
filter.details,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.cta_label) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'services',
|
|
||||||
'cta_label',
|
|
||||||
filter.cta_label,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.cta_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'services',
|
|
||||||
'cta_url',
|
|
||||||
filter.cta_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.icon_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'services',
|
|
||||||
'icon_name',
|
|
||||||
filter.icon_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.category) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
category: filter.category,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_featured) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_featured: filter.is_featured,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_active) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_active: filter.is_active,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.services.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'services',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.services.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,663 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class Site_settingsDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const site_settings = await db.site_settings.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
site_name: data.site_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
tagline: data.tagline
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_domain: data.primary_domain
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_cta_label: data.primary_cta_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_cta_url: data.primary_cta_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
contact_email: data.contact_email
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
contact_phone: data.contact_phone
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
location: data.location
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
accent_color_hex: data.accent_color_hex
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
seo_title: data.seo_title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
seo_description: data.seo_description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'logo_images',
|
|
||||||
belongsToId: site_settings.id,
|
|
||||||
},
|
|
||||||
data.logo_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'favicon_images',
|
|
||||||
belongsToId: site_settings.id,
|
|
||||||
},
|
|
||||||
data.favicon_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return site_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const site_settingsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
site_name: item.site_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
tagline: item.tagline
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_domain: item.primary_domain
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_cta_label: item.primary_cta_label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
primary_cta_url: item.primary_cta_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
contact_email: item.contact_email
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
contact_phone: item.contact_phone
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
location: item.location
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
accent_color_hex: item.accent_color_hex
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
seo_title: item.seo_title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
seo_description: item.seo_description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const site_settings = await db.site_settings.bulkCreate(site_settingsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
for (let i = 0; i < site_settings.length; i++) {
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'logo_images',
|
|
||||||
belongsToId: site_settings[i].id,
|
|
||||||
},
|
|
||||||
data[i].logo_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < site_settings.length; i++) {
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'favicon_images',
|
|
||||||
belongsToId: site_settings[i].id,
|
|
||||||
},
|
|
||||||
data[i].favicon_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return site_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const site_settings = await db.site_settings.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.site_name !== undefined) updatePayload.site_name = data.site_name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.tagline !== undefined) updatePayload.tagline = data.tagline;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.primary_domain !== undefined) updatePayload.primary_domain = data.primary_domain;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.primary_cta_label !== undefined) updatePayload.primary_cta_label = data.primary_cta_label;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.primary_cta_url !== undefined) updatePayload.primary_cta_url = data.primary_cta_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.contact_email !== undefined) updatePayload.contact_email = data.contact_email;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.contact_phone !== undefined) updatePayload.contact_phone = data.contact_phone;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.location !== undefined) updatePayload.location = data.location;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.accent_color_hex !== undefined) updatePayload.accent_color_hex = data.accent_color_hex;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.seo_title !== undefined) updatePayload.seo_title = data.seo_title;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.seo_description !== undefined) updatePayload.seo_description = data.seo_description;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await site_settings.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'logo_images',
|
|
||||||
belongsToId: site_settings.id,
|
|
||||||
},
|
|
||||||
data.logo_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'favicon_images',
|
|
||||||
belongsToId: site_settings.id,
|
|
||||||
},
|
|
||||||
data.favicon_images,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return site_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const site_settings = await db.site_settings.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of site_settings) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of site_settings) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return site_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const site_settings = await db.site_settings.findByPk(id, options);
|
|
||||||
|
|
||||||
await site_settings.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await site_settings.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return site_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const site_settings = await db.site_settings.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!site_settings) {
|
|
||||||
return site_settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = site_settings.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.logo_images = await site_settings.getLogo_images({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.favicon_images = await site_settings.getFavicon_images({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.file,
|
|
||||||
as: 'logo_images',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.file,
|
|
||||||
as: 'favicon_images',
|
|
||||||
},
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.site_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'site_name',
|
|
||||||
filter.site_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.tagline) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'tagline',
|
|
||||||
filter.tagline,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.primary_domain) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'primary_domain',
|
|
||||||
filter.primary_domain,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.primary_cta_label) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'primary_cta_label',
|
|
||||||
filter.primary_cta_label,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.primary_cta_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'primary_cta_url',
|
|
||||||
filter.primary_cta_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.contact_email) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'contact_email',
|
|
||||||
filter.contact_email,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.contact_phone) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'contact_phone',
|
|
||||||
filter.contact_phone,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.location) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'location',
|
|
||||||
filter.location,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.accent_color_hex) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'accent_color_hex',
|
|
||||||
filter.accent_color_hex,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.seo_title) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'seo_title',
|
|
||||||
filter.seo_title,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.seo_description) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'seo_description',
|
|
||||||
filter.seo_description,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.site_settings.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'site_settings',
|
|
||||||
'site_name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.site_settings.findAll({
|
|
||||||
attributes: [ 'id', 'site_name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['site_name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.site_name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,455 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class SkillsDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const skills = await db.skills.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
name: data.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
category: data.category
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
proficiency_level: data.proficiency_level
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: data.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: data.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return skills;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const skillsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
category: item.category
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
proficiency_level: item.proficiency_level
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: item.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const skills = await db.skills.bulkCreate(skillsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return skills;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const skills = await db.skills.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.category !== undefined) updatePayload.category = data.category;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.proficiency_level !== undefined) updatePayload.proficiency_level = data.proficiency_level;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_featured !== undefined) updatePayload.is_featured = data.is_featured;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await skills.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return skills;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const skills = await db.skills.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of skills) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of skills) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return skills;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const skills = await db.skills.findByPk(id, options);
|
|
||||||
|
|
||||||
await skills.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await skills.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return skills;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const skills = await db.skills.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!skills) {
|
|
||||||
return skills;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = skills.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'skills',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.proficiency_levelRange) {
|
|
||||||
const [start, end] = filter.proficiency_levelRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
proficiency_level: {
|
|
||||||
...where.proficiency_level,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
proficiency_level: {
|
|
||||||
...where.proficiency_level,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.category) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
category: filter.category,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_featured) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_featured: filter.is_featured,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.skills.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'skills',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.skills.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,442 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class Social_linksDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const social_links = await db.social_links.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
platform: data.platform
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
label: data.label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
url: data.url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: data.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: data.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return social_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const social_linksData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
platform: item.platform
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
label: item.label
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
url: item.url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: item.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const social_links = await db.social_links.bulkCreate(social_linksData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return social_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const social_links = await db.social_links.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.platform !== undefined) updatePayload.platform = data.platform;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.label !== undefined) updatePayload.label = data.label;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.url !== undefined) updatePayload.url = data.url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_active !== undefined) updatePayload.is_active = data.is_active;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await social_links.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return social_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const social_links = await db.social_links.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of social_links) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of social_links) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return social_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const social_links = await db.social_links.findByPk(id, options);
|
|
||||||
|
|
||||||
await social_links.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await social_links.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return social_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const social_links = await db.social_links.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!social_links) {
|
|
||||||
return social_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = social_links.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.label) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'social_links',
|
|
||||||
'label',
|
|
||||||
filter.label,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'social_links',
|
|
||||||
'url',
|
|
||||||
filter.url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.platform) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
platform: filter.platform,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_active) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_active: filter.is_active,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.social_links.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'social_links',
|
|
||||||
'label',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.social_links.findAll({
|
|
||||||
attributes: [ 'id', 'label' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['label', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.label,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,619 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class TestimonialsDBApi {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const testimonials = await db.testimonials.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
|
|
||||||
client_name: data.client_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
client_title: data.client_title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
company_name: data.company_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
quote: data.quote
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
rating: data.rating
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source: data.source
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source_url: data.source_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
testimonial_date: data.testimonial_date
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: data.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
is_public: data.is_public
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.testimonials.getTableName(),
|
|
||||||
belongsToColumn: 'client_avatars',
|
|
||||||
belongsToId: testimonials.id,
|
|
||||||
},
|
|
||||||
data.client_avatars,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return testimonials;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const testimonialsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
client_name: item.client_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
client_title: item.client_title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
company_name: item.company_name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
quote: item.quote
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
rating: item.rating
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source: item.source
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source_url: item.source_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
testimonial_date: item.testimonial_date
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_featured: item.is_featured
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
is_public: item.is_public
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const testimonials = await db.testimonials.bulkCreate(testimonialsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
for (let i = 0; i < testimonials.length; i++) {
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.testimonials.getTableName(),
|
|
||||||
belongsToColumn: 'client_avatars',
|
|
||||||
belongsToId: testimonials[i].id,
|
|
||||||
},
|
|
||||||
data[i].client_avatars,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return testimonials;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const testimonials = await db.testimonials.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.client_name !== undefined) updatePayload.client_name = data.client_name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.client_title !== undefined) updatePayload.client_title = data.client_title;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.company_name !== undefined) updatePayload.company_name = data.company_name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.quote !== undefined) updatePayload.quote = data.quote;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.rating !== undefined) updatePayload.rating = data.rating;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.source !== undefined) updatePayload.source = data.source;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.source_url !== undefined) updatePayload.source_url = data.source_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.testimonial_date !== undefined) updatePayload.testimonial_date = data.testimonial_date;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_featured !== undefined) updatePayload.is_featured = data.is_featured;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_public !== undefined) updatePayload.is_public = data.is_public;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await testimonials.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.testimonials.getTableName(),
|
|
||||||
belongsToColumn: 'client_avatars',
|
|
||||||
belongsToId: testimonials.id,
|
|
||||||
},
|
|
||||||
data.client_avatars,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return testimonials;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const testimonials = await db.testimonials.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of testimonials) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of testimonials) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return testimonials;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const testimonials = await db.testimonials.findByPk(id, options);
|
|
||||||
|
|
||||||
await testimonials.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await testimonials.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return testimonials;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const testimonials = await db.testimonials.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!testimonials) {
|
|
||||||
return testimonials;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = testimonials.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.client_avatars = await testimonials.getClient_avatars({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.file,
|
|
||||||
as: 'client_avatars',
|
|
||||||
},
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.client_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'testimonials',
|
|
||||||
'client_name',
|
|
||||||
filter.client_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.client_title) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'testimonials',
|
|
||||||
'client_title',
|
|
||||||
filter.client_title,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.company_name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'testimonials',
|
|
||||||
'company_name',
|
|
||||||
filter.company_name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.quote) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'testimonials',
|
|
||||||
'quote',
|
|
||||||
filter.quote,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.source) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'testimonials',
|
|
||||||
'source',
|
|
||||||
filter.source,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.source_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'testimonials',
|
|
||||||
'source_url',
|
|
||||||
filter.source_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.ratingRange) {
|
|
||||||
const [start, end] = filter.ratingRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
rating: {
|
|
||||||
...where.rating,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
rating: {
|
|
||||||
...where.rating,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.testimonial_dateRange) {
|
|
||||||
const [start, end] = filter.testimonial_dateRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
testimonial_date: {
|
|
||||||
...where.testimonial_date,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
testimonial_date: {
|
|
||||||
...where.testimonial_date,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.is_featured) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_featured: filter.is_featured,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_public) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_public: filter.is_public,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.testimonials.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'testimonials',
|
|
||||||
'client_name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.testimonials.findAll({
|
|
||||||
attributes: [ 'id', 'client_name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['client_name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.client_name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,945 +0,0 @@
|
|||||||
|
|
||||||
const db = require('../models');
|
|
||||||
const FileDBApi = require('./file');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const config = require('../../config');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class UsersDBApi {
|
|
||||||
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const users = await db.users.create(
|
|
||||||
{
|
|
||||||
id: data.data.id || undefined,
|
|
||||||
|
|
||||||
firstName: data.data.firstName
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
lastName: data.data.lastName
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
phoneNumber: data.data.phoneNumber
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
email: data.data.email
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
disabled: data.data.disabled
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
password: data.data.password
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
emailVerified: data.data.emailVerified
|
|
||||||
||
|
|
||||||
true
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
emailVerificationToken: data.data.emailVerificationToken
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
emailVerificationTokenExpiresAt: data.data.emailVerificationTokenExpiresAt
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
passwordResetToken: data.data.passwordResetToken
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
passwordResetTokenExpiresAt: data.data.passwordResetTokenExpiresAt
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
provider: data.data.provider
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!data.data.app_role) {
|
|
||||||
const role = await db.roles.findOne({
|
|
||||||
where: { name: 'User' },
|
|
||||||
});
|
|
||||||
if (role) {
|
|
||||||
await users.setApp_role(role, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
await users.setApp_role(data.data.app_role || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await users.setCustom_permissions(data.data.custom_permissions || [], {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.users.getTableName(),
|
|
||||||
belongsToColumn: 'avatar',
|
|
||||||
belongsToId: users.id,
|
|
||||||
},
|
|
||||||
data.data.avatar,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const usersData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
firstName: item.firstName
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
lastName: item.lastName
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
phoneNumber: item.phoneNumber
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
email: item.email
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
disabled: item.disabled
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
password: item.password
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
emailVerified: item.emailVerified
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
emailVerificationToken: item.emailVerificationToken
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
emailVerificationTokenExpiresAt: item.emailVerificationTokenExpiresAt
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
passwordResetToken: item.passwordResetToken
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
passwordResetTokenExpiresAt: item.passwordResetTokenExpiresAt
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
provider: item.provider
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const users = await db.users.bulkCreate(usersData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
for (let i = 0; i < users.length; i++) {
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.users.getTableName(),
|
|
||||||
belongsToColumn: 'avatar',
|
|
||||||
belongsToId: users[i].id,
|
|
||||||
},
|
|
||||||
data[i].avatar,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const users = await db.users.findByPk(id, {}, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!data?.app_role) {
|
|
||||||
data.app_role = users?.app_role?.id;
|
|
||||||
}
|
|
||||||
if (!data?.custom_permissions) {
|
|
||||||
data.custom_permissions = users?.custom_permissions?.map(item => item.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.password) {
|
|
||||||
data.password = bcrypt.hashSync(
|
|
||||||
data.password,
|
|
||||||
config.bcrypt.saltRounds,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
data.password = users.password;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.firstName !== undefined) updatePayload.firstName = data.firstName;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.lastName !== undefined) updatePayload.lastName = data.lastName;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.phoneNumber !== undefined) updatePayload.phoneNumber = data.phoneNumber;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.email !== undefined) updatePayload.email = data.email;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.disabled !== undefined) updatePayload.disabled = data.disabled;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.password !== undefined) updatePayload.password = data.password;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.emailVerified !== undefined) updatePayload.emailVerified = data.emailVerified;
|
|
||||||
|
|
||||||
else updatePayload.emailVerified = true;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.emailVerificationToken !== undefined) updatePayload.emailVerificationToken = data.emailVerificationToken;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.emailVerificationTokenExpiresAt !== undefined) updatePayload.emailVerificationTokenExpiresAt = data.emailVerificationTokenExpiresAt;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.passwordResetToken !== undefined) updatePayload.passwordResetToken = data.passwordResetToken;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.passwordResetTokenExpiresAt !== undefined) updatePayload.passwordResetTokenExpiresAt = data.passwordResetTokenExpiresAt;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.provider !== undefined) updatePayload.provider = data.provider;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await users.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.app_role !== undefined) {
|
|
||||||
await users.setApp_role(
|
|
||||||
|
|
||||||
data.app_role,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.custom_permissions !== undefined) {
|
|
||||||
await users.setCustom_permissions(data.custom_permissions, { transaction });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
|
||||||
{
|
|
||||||
belongsTo: db.users.getTableName(),
|
|
||||||
belongsToColumn: 'avatar',
|
|
||||||
belongsToId: users.id,
|
|
||||||
},
|
|
||||||
data.avatar,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const users = await db.users.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of users) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of users) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const users = await db.users.findByPk(id, options);
|
|
||||||
|
|
||||||
await users.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await users.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const users = await db.users.findOne(
|
|
||||||
{ where },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!users) {
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = users.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.pages_author = await users.getPages_author({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.inquiries_assigned_to = await users.getInquiries_assigned_to({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.avatar = await users.getAvatar({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.app_role = await users.getApp_role({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
if (output.app_role) {
|
|
||||||
output.app_role_permissions = await output.app_role.getPermissions({
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
output.custom_permissions = await users.getCustom_permissions({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
const orderBy = null;
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.roles,
|
|
||||||
as: 'app_role',
|
|
||||||
|
|
||||||
where: filter.app_role ? {
|
|
||||||
[Op.or]: [
|
|
||||||
{ id: { [Op.in]: filter.app_role.split('|').map(term => Utils.uuid(term)) } },
|
|
||||||
{
|
|
||||||
name: {
|
|
||||||
[Op.or]: filter.app_role.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
} : {},
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.permissions,
|
|
||||||
as: 'custom_permissions',
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
model: db.file,
|
|
||||||
as: 'avatar',
|
|
||||||
},
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.firstName) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'firstName',
|
|
||||||
filter.firstName,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.lastName) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'lastName',
|
|
||||||
filter.lastName,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.phoneNumber) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'phoneNumber',
|
|
||||||
filter.phoneNumber,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.email) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'email',
|
|
||||||
filter.email,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.password) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'password',
|
|
||||||
filter.password,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.emailVerificationToken) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'emailVerificationToken',
|
|
||||||
filter.emailVerificationToken,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.passwordResetToken) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'passwordResetToken',
|
|
||||||
filter.passwordResetToken,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.provider) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'provider',
|
|
||||||
filter.provider,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.emailVerificationTokenExpiresAtRange) {
|
|
||||||
const [start, end] = filter.emailVerificationTokenExpiresAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
emailVerificationTokenExpiresAt: {
|
|
||||||
...where.emailVerificationTokenExpiresAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
emailVerificationTokenExpiresAt: {
|
|
||||||
...where.emailVerificationTokenExpiresAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.passwordResetTokenExpiresAtRange) {
|
|
||||||
const [start, end] = filter.passwordResetTokenExpiresAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
passwordResetTokenExpiresAt: {
|
|
||||||
...where.passwordResetTokenExpiresAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
passwordResetTokenExpiresAt: {
|
|
||||||
...where.passwordResetTokenExpiresAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.disabled) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
disabled: filter.disabled,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.emailVerified) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
emailVerified: filter.emailVerified,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.custom_permissions) {
|
|
||||||
const searchTerms = filter.custom_permissions.split('|');
|
|
||||||
|
|
||||||
include = [
|
|
||||||
{
|
|
||||||
model: db.permissions,
|
|
||||||
as: 'custom_permissions_filter',
|
|
||||||
required: searchTerms.length > 0,
|
|
||||||
where: searchTerms.length > 0 ? {
|
|
||||||
[Op.or]: [
|
|
||||||
{ id: { [Op.in]: searchTerms.map(term => Utils.uuid(term)) } },
|
|
||||||
{
|
|
||||||
name: {
|
|
||||||
[Op.or]: searchTerms.map(term => ({ [Op.iLike]: `%${term}%` }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} : undefined
|
|
||||||
},
|
|
||||||
...include,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.users.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'users',
|
|
||||||
'firstName',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.users.findAll({
|
|
||||||
attributes: [ 'id', 'firstName' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['firstName', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.firstName,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async createFromAuth(data, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const users = await db.users.create(
|
|
||||||
{
|
|
||||||
email: data.email,
|
|
||||||
firstName: data.firstName,
|
|
||||||
authenticationUid: data.authenticationUid,
|
|
||||||
password: data.password,
|
|
||||||
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
const app_role = await db.roles.findOne({
|
|
||||||
where: { name: config.roles?.user || "User" },
|
|
||||||
});
|
|
||||||
if (app_role?.id) {
|
|
||||||
await users.setApp_role(app_role?.id || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await users.update(
|
|
||||||
{
|
|
||||||
authenticationUid: users.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
delete users.password;
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async updatePassword(id, password, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const users = await db.users.findByPk(id, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await users.update(
|
|
||||||
{
|
|
||||||
password,
|
|
||||||
authenticationUid: id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async generateEmailVerificationToken(email, options) {
|
|
||||||
return this._generateToken(['emailVerificationToken', 'emailVerificationTokenExpiresAt'], email, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async generatePasswordResetToken(email, options) {
|
|
||||||
return this._generateToken(['passwordResetToken', 'passwordResetTokenExpiresAt'], email, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findByPasswordResetToken(token, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
return db.users.findOne(
|
|
||||||
{
|
|
||||||
where: {
|
|
||||||
passwordResetToken: token,
|
|
||||||
passwordResetTokenExpiresAt: {
|
|
||||||
[db.Sequelize.Op.gt]: Date.now(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findByEmailVerificationToken(
|
|
||||||
token,
|
|
||||||
options,
|
|
||||||
) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
return db.users.findOne(
|
|
||||||
{
|
|
||||||
where: {
|
|
||||||
emailVerificationToken: token,
|
|
||||||
emailVerificationTokenExpiresAt: {
|
|
||||||
[db.Sequelize.Op.gt]: Date.now(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async markEmailVerified(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const users = await db.users.findByPk(id, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await users.update(
|
|
||||||
{
|
|
||||||
emailVerified: true,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async _generateToken(keyNames, email, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const users = await db.users.findOne(
|
|
||||||
{
|
|
||||||
where: { email: email.toLowerCase() },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const token = crypto
|
|
||||||
.randomBytes(20)
|
|
||||||
.toString('hex');
|
|
||||||
const tokenExpiresAt = Date.now() + 360000;
|
|
||||||
|
|
||||||
if(users){
|
|
||||||
await users.update(
|
|
||||||
{
|
|
||||||
[keyNames[0]]: token,
|
|
||||||
[keyNames[1]]: tokenExpiresAt,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
production: {
|
|
||||||
dialect: 'postgres',
|
|
||||||
username: process.env.DB_USER,
|
|
||||||
password: process.env.DB_PASS,
|
|
||||||
database: process.env.DB_NAME,
|
|
||||||
host: process.env.DB_HOST,
|
|
||||||
port: process.env.DB_PORT,
|
|
||||||
logging: console.log,
|
|
||||||
seederStorage: 'sequelize',
|
|
||||||
},
|
|
||||||
development: {
|
|
||||||
username: 'postgres',
|
|
||||||
dialect: 'postgres',
|
|
||||||
password: '',
|
|
||||||
database: 'db_blackness_studio_website',
|
|
||||||
host: process.env.DB_HOST || 'localhost',
|
|
||||||
logging: console.log,
|
|
||||||
seederStorage: 'sequelize',
|
|
||||||
},
|
|
||||||
dev_stage: {
|
|
||||||
dialect: 'postgres',
|
|
||||||
username: process.env.DB_USER,
|
|
||||||
password: process.env.DB_PASS,
|
|
||||||
database: process.env.DB_NAME,
|
|
||||||
host: process.env.DB_HOST,
|
|
||||||
port: process.env.DB_PORT,
|
|
||||||
logging: console.log,
|
|
||||||
seederStorage: 'sequelize',
|
|
||||||
}
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,109 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const benefits = sequelize.define(
|
|
||||||
'benefits',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
title: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
description: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
icon_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
sort_order: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_active: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
benefits.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.benefits.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.benefits.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return benefits;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const file = sequelize.define(
|
|
||||||
'file',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
belongsTo: DataTypes.STRING(255),
|
|
||||||
belongsToId: DataTypes.UUID,
|
|
||||||
belongsToColumn: DataTypes.STRING(255),
|
|
||||||
name: {
|
|
||||||
type: DataTypes.STRING(2083),
|
|
||||||
allowNull: false,
|
|
||||||
validate: {
|
|
||||||
notEmpty: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sizeInBytes: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
privateUrl: {
|
|
||||||
type: DataTypes.STRING(2083),
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
publicUrl: {
|
|
||||||
type: DataTypes.STRING(2083),
|
|
||||||
allowNull: false,
|
|
||||||
validate: {
|
|
||||||
notEmpty: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
file.associate = (db) => {
|
|
||||||
db.file.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.file.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return file;
|
|
||||||
};
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const Sequelize = require('sequelize');
|
|
||||||
const basename = path.basename(__filename);
|
|
||||||
const env = process.env.NODE_ENV || 'development';
|
|
||||||
const config = require("../db.config")[env];
|
|
||||||
const db = {};
|
|
||||||
|
|
||||||
let sequelize;
|
|
||||||
console.log(env);
|
|
||||||
if (config.use_env_variable) {
|
|
||||||
sequelize = new Sequelize(process.env[config.use_env_variable], config);
|
|
||||||
} else {
|
|
||||||
sequelize = new Sequelize(config.database, config.username, config.password, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs
|
|
||||||
.readdirSync(__dirname)
|
|
||||||
.filter(file => {
|
|
||||||
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
|
|
||||||
})
|
|
||||||
.forEach(file => {
|
|
||||||
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes)
|
|
||||||
db[model.name] = model;
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(db).forEach(modelName => {
|
|
||||||
if (db[modelName].associate) {
|
|
||||||
db[modelName].associate(db);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
db.sequelize = sequelize;
|
|
||||||
db.Sequelize = Sequelize;
|
|
||||||
|
|
||||||
module.exports = db;
|
|
||||||
@ -1,164 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const inquiries = sequelize.define(
|
|
||||||
'inquiries',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
full_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
email: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
company_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
subject: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
message: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
source_page: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
status: {
|
|
||||||
type: DataTypes.ENUM,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
values: [
|
|
||||||
|
|
||||||
"new",
|
|
||||||
|
|
||||||
|
|
||||||
"in_review",
|
|
||||||
|
|
||||||
|
|
||||||
"replied",
|
|
||||||
|
|
||||||
|
|
||||||
"archived"
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
received_at: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
replied_at: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
fiverr_url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
inquiries.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.inquiries.belongsTo(db.users, {
|
|
||||||
as: 'assigned_to',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'assigned_toId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.inquiries.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.inquiries.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return inquiries;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,196 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const page_sections = sequelize.define(
|
|
||||||
'page_sections',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
section_type: {
|
|
||||||
type: DataTypes.ENUM,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
values: [
|
|
||||||
|
|
||||||
"hero",
|
|
||||||
|
|
||||||
|
|
||||||
"about",
|
|
||||||
|
|
||||||
|
|
||||||
"services",
|
|
||||||
|
|
||||||
|
|
||||||
"portfolio",
|
|
||||||
|
|
||||||
|
|
||||||
"why_choose_me",
|
|
||||||
|
|
||||||
|
|
||||||
"testimonials",
|
|
||||||
|
|
||||||
|
|
||||||
"final_cta",
|
|
||||||
|
|
||||||
|
|
||||||
"footer"
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
section_label: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
headline: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
subheadline: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
body: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
primary_button_label: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
primary_button_url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
secondary_button_label: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
secondary_button_url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
sort_order: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_visible: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
page_sections.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.page_sections.belongsTo(db.pages, {
|
|
||||||
as: 'page',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'pageId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.page_sections.hasMany(db.file, {
|
|
||||||
as: 'background_images',
|
|
||||||
foreignKey: 'belongsToId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
belongsTo: db.page_sections.getTableName(),
|
|
||||||
belongsToColumn: 'background_images',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
db.page_sections.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.page_sections.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return page_sections;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,158 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const pages = sequelize.define(
|
|
||||||
'pages',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
title: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
slug: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
status: {
|
|
||||||
type: DataTypes.ENUM,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
values: [
|
|
||||||
|
|
||||||
"draft",
|
|
||||||
|
|
||||||
|
|
||||||
"published"
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
sort_order: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
meta_title: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
meta_description: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
show_in_header_nav: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
show_in_footer_nav: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
pages.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.pages.hasMany(db.page_sections, {
|
|
||||||
as: 'page_sections_page',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'pageId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.pages.belongsTo(db.users, {
|
|
||||||
as: 'author',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'authorId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.pages.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.pages.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return pages;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const permissions = sequelize.define(
|
|
||||||
'permissions',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
permissions.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.permissions.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.permissions.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,191 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const portfolio_items = sequelize.define(
|
|
||||||
'portfolio_items',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
title: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
work_type: {
|
|
||||||
type: DataTypes.ENUM,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
values: [
|
|
||||||
|
|
||||||
"blog",
|
|
||||||
|
|
||||||
|
|
||||||
"documentation",
|
|
||||||
|
|
||||||
|
|
||||||
"tutorial",
|
|
||||||
|
|
||||||
|
|
||||||
"review",
|
|
||||||
|
|
||||||
|
|
||||||
"guide",
|
|
||||||
|
|
||||||
|
|
||||||
"case_study",
|
|
||||||
|
|
||||||
|
|
||||||
"other"
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
client_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
summary: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
case_study: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
external_url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
tech_stack: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
published_on: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_featured: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_public: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
portfolio_items.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.portfolio_items.hasMany(db.file, {
|
|
||||||
as: 'screenshots',
|
|
||||||
foreignKey: 'belongsToId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'screenshots',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
db.portfolio_items.hasMany(db.file, {
|
|
||||||
as: 'attachments',
|
|
||||||
foreignKey: 'belongsToId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
belongsTo: db.portfolio_items.getTableName(),
|
|
||||||
belongsToColumn: 'attachments',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
db.portfolio_items.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.portfolio_items.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return portfolio_items;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,111 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const roles = sequelize.define(
|
|
||||||
'roles',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
role_customization: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
roles.associate = (db) => {
|
|
||||||
|
|
||||||
db.roles.belongsToMany(db.permissions, {
|
|
||||||
as: 'permissions',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'roles_permissionsId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
through: 'rolesPermissionsPermissions',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.roles.belongsToMany(db.permissions, {
|
|
||||||
as: 'permissions_filter',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'roles_permissionsId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
through: 'rolesPermissionsPermissions',
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
db.roles.hasMany(db.users, {
|
|
||||||
as: 'users_app_role',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'app_roleId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.roles.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.roles.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const services = sequelize.define(
|
|
||||||
'services',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
short_description: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
details: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
category: {
|
|
||||||
type: DataTypes.ENUM,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
values: [
|
|
||||||
|
|
||||||
"blog_writing",
|
|
||||||
|
|
||||||
|
|
||||||
"technical_documentation",
|
|
||||||
|
|
||||||
|
|
||||||
"tutorials",
|
|
||||||
|
|
||||||
|
|
||||||
"product_reviews",
|
|
||||||
|
|
||||||
|
|
||||||
"guides",
|
|
||||||
|
|
||||||
|
|
||||||
"other"
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
sort_order: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_featured: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_active: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
cta_label: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
cta_url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
icon_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
services.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.services.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.services.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return services;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const site_settings = sequelize.define(
|
|
||||||
'site_settings',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
site_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
tagline: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
primary_domain: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
primary_cta_label: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
primary_cta_url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
contact_email: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
contact_phone: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
location: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
accent_color_hex: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
seo_title: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
seo_description: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
site_settings.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.site_settings.hasMany(db.file, {
|
|
||||||
as: 'logo_images',
|
|
||||||
foreignKey: 'belongsToId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'logo_images',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
db.site_settings.hasMany(db.file, {
|
|
||||||
as: 'favicon_images',
|
|
||||||
foreignKey: 'belongsToId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
belongsTo: db.site_settings.getTableName(),
|
|
||||||
belongsToColumn: 'favicon_images',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
db.site_settings.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.site_settings.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return site_settings;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const skills = sequelize.define(
|
|
||||||
'skills',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
category: {
|
|
||||||
type: DataTypes.ENUM,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
values: [
|
|
||||||
|
|
||||||
"writing",
|
|
||||||
|
|
||||||
|
|
||||||
"technical",
|
|
||||||
|
|
||||||
|
|
||||||
"tools",
|
|
||||||
|
|
||||||
|
|
||||||
"domain"
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
proficiency_level: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
sort_order: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_featured: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
skills.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.skills.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.skills.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return skills;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,133 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const social_links = sequelize.define(
|
|
||||||
'social_links',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
platform: {
|
|
||||||
type: DataTypes.ENUM,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
values: [
|
|
||||||
|
|
||||||
"linkedin",
|
|
||||||
|
|
||||||
|
|
||||||
"github",
|
|
||||||
|
|
||||||
|
|
||||||
"x",
|
|
||||||
|
|
||||||
|
|
||||||
"medium",
|
|
||||||
|
|
||||||
|
|
||||||
"youtube",
|
|
||||||
|
|
||||||
|
|
||||||
"website",
|
|
||||||
|
|
||||||
|
|
||||||
"other"
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
label: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
sort_order: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_active: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
social_links.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.social_links.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.social_links.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return social_links;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,157 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const testimonials = sequelize.define(
|
|
||||||
'testimonials',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
client_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
client_title: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
company_name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
quote: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
rating: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
source: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
source_url: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
testimonial_date: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_featured: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
is_public: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testimonials.associate = (db) => {
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.testimonials.hasMany(db.file, {
|
|
||||||
as: 'client_avatars',
|
|
||||||
foreignKey: 'belongsToId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
belongsTo: db.testimonials.getTableName(),
|
|
||||||
belongsToColumn: 'client_avatars',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
db.testimonials.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.testimonials.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return testimonials;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,252 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const providers = config.providers;
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const moment = require('moment');
|
|
||||||
|
|
||||||
module.exports = function(sequelize, DataTypes) {
|
|
||||||
const users = sequelize.define(
|
|
||||||
'users',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
firstName: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
lastName: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
phoneNumber: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
email: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
disabled: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
password: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
emailVerified: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
emailVerificationToken: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
emailVerificationTokenExpiresAt: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
passwordResetToken: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
passwordResetTokenExpiresAt: {
|
|
||||||
type: DataTypes.DATE,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
provider: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
users.associate = (db) => {
|
|
||||||
|
|
||||||
db.users.belongsToMany(db.permissions, {
|
|
||||||
as: 'custom_permissions',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'users_custom_permissionsId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
through: 'usersCustom_permissionsPermissions',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.users.belongsToMany(db.permissions, {
|
|
||||||
as: 'custom_permissions_filter',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'users_custom_permissionsId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
through: 'usersCustom_permissionsPermissions',
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.users.hasMany(db.pages, {
|
|
||||||
as: 'pages_author',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'authorId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.users.hasMany(db.inquiries, {
|
|
||||||
as: 'inquiries_assigned_to',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'assigned_toId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//end loop
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.users.belongsTo(db.roles, {
|
|
||||||
as: 'app_role',
|
|
||||||
foreignKey: {
|
|
||||||
name: 'app_roleId',
|
|
||||||
},
|
|
||||||
constraints: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
db.users.hasMany(db.file, {
|
|
||||||
as: 'avatar',
|
|
||||||
foreignKey: 'belongsToId',
|
|
||||||
constraints: false,
|
|
||||||
scope: {
|
|
||||||
belongsTo: db.users.getTableName(),
|
|
||||||
belongsToColumn: 'avatar',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
db.users.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.users.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
users.beforeCreate((users, options) => {
|
|
||||||
users = trimStringFields(users);
|
|
||||||
|
|
||||||
if (users.provider !== providers.LOCAL && Object.values(providers).indexOf(users.provider) > -1) {
|
|
||||||
users.emailVerified = true;
|
|
||||||
|
|
||||||
if (!users.password) {
|
|
||||||
const password = crypto
|
|
||||||
.randomBytes(20)
|
|
||||||
.toString('hex');
|
|
||||||
|
|
||||||
const hashedPassword = bcrypt.hashSync(
|
|
||||||
password,
|
|
||||||
config.bcrypt.saltRounds,
|
|
||||||
);
|
|
||||||
|
|
||||||
users.password = hashedPassword
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
users.beforeUpdate((users, options) => {
|
|
||||||
users = trimStringFields(users);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return users;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function trimStringFields(users) {
|
|
||||||
users.email = users.email.trim();
|
|
||||||
|
|
||||||
users.firstName = users.firstName
|
|
||||||
? users.firstName.trim()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
users.lastName = users.lastName
|
|
||||||
? users.lastName.trim()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
const db = require('./models');
|
|
||||||
const {execSync} = require("child_process");
|
|
||||||
|
|
||||||
console.log('Resetting Database');
|
|
||||||
|
|
||||||
db.sequelize
|
|
||||||
.sync({ force: true })
|
|
||||||
.then(() => {
|
|
||||||
execSync("sequelize db:seed:all");
|
|
||||||
console.log('OK');
|
|
||||||
process.exit();
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const bcrypt = require("bcrypt");
|
|
||||||
const config = require("../../config");
|
|
||||||
|
|
||||||
const ids = [
|
|
||||||
'193bf4b5-9f07-4bd5-9a43-e7e41f3e96af',
|
|
||||||
'af5a87be-8f9c-4630-902a-37a60b7005ba',
|
|
||||||
'5bc531ab-611f-41f3-9373-b7cc5d09c93d',
|
|
||||||
]
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
up: async (queryInterface, Sequelize) => {
|
|
||||||
let admin_hash = bcrypt.hashSync(config.admin_pass, config.bcrypt.saltRounds);
|
|
||||||
let user_hash = bcrypt.hashSync(config.user_pass, config.bcrypt.saltRounds);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await queryInterface.bulkInsert('users', [
|
|
||||||
{
|
|
||||||
id: ids[0],
|
|
||||||
firstName: 'Admin',
|
|
||||||
email: config.admin_email,
|
|
||||||
emailVerified: true,
|
|
||||||
provider: config.providers.LOCAL,
|
|
||||||
password: admin_hash,
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: ids[1],
|
|
||||||
firstName: 'John',
|
|
||||||
email: 'john@doe.com',
|
|
||||||
emailVerified: true,
|
|
||||||
provider: config.providers.LOCAL,
|
|
||||||
password: user_hash,
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: ids[2],
|
|
||||||
firstName: 'Client',
|
|
||||||
email: 'client@hello.com',
|
|
||||||
emailVerified: true,
|
|
||||||
provider: config.providers.LOCAL,
|
|
||||||
password: user_hash,
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error during bulkInsert:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
|
||||||
try {
|
|
||||||
await queryInterface.bulkDelete('users', {
|
|
||||||
id: {
|
|
||||||
[Sequelize.Op.in]: ids,
|
|
||||||
},
|
|
||||||
}, {});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error during bulkDelete:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
|||||||
const validator = require('validator');
|
|
||||||
const { v4: uuid } = require('uuid');
|
|
||||||
const Sequelize = require('./models').Sequelize;
|
|
||||||
|
|
||||||
module.exports = class Utils {
|
|
||||||
static uuid(value) {
|
|
||||||
let id = value;
|
|
||||||
|
|
||||||
if (!validator.isUUID(id)) {
|
|
||||||
id = uuid();
|
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ilike(model, column, value) {
|
|
||||||
return Sequelize.where(
|
|
||||||
Sequelize.fn(
|
|
||||||
'lower',
|
|
||||||
Sequelize.col(`${model}.${column}`),
|
|
||||||
),
|
|
||||||
{
|
|
||||||
[Sequelize.Op.like]: `%${value}%`.toLowerCase(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
const jwt = require('jsonwebtoken');
|
|
||||||
const config = require('./config');
|
|
||||||
|
|
||||||
module.exports = class Helpers {
|
|
||||||
static wrapAsync(fn) {
|
|
||||||
return function (req, res, next) {
|
|
||||||
fn(req, res, next).catch(next);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static commonErrorHandler(error, req, res, next) {
|
|
||||||
if ([400, 403, 404].includes(error.code)) {
|
|
||||||
return res.status(error.code).send(error.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error(error);
|
|
||||||
return res.status(500).send(error.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jwtSign(data) {
|
|
||||||
return jwt.sign(data, config.secret_key, {expiresIn: '6h'});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1,178 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
const cors = require('cors');
|
|
||||||
const app = express();
|
|
||||||
const passport = require('passport');
|
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
const bodyParser = require('body-parser');
|
|
||||||
const db = require('./db/models');
|
|
||||||
const config = require('./config');
|
|
||||||
const swaggerUI = require('swagger-ui-express');
|
|
||||||
const swaggerJsDoc = require('swagger-jsdoc');
|
|
||||||
|
|
||||||
const authRoutes = require('./routes/auth');
|
|
||||||
const fileRoutes = require('./routes/file');
|
|
||||||
const searchRoutes = require('./routes/search');
|
|
||||||
const sqlRoutes = require('./routes/sql');
|
|
||||||
const pexelsRoutes = require('./routes/pexels');
|
|
||||||
|
|
||||||
const openaiRoutes = require('./routes/openai');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const usersRoutes = require('./routes/users');
|
|
||||||
|
|
||||||
const rolesRoutes = require('./routes/roles');
|
|
||||||
|
|
||||||
const permissionsRoutes = require('./routes/permissions');
|
|
||||||
|
|
||||||
const site_settingsRoutes = require('./routes/site_settings');
|
|
||||||
|
|
||||||
const pagesRoutes = require('./routes/pages');
|
|
||||||
|
|
||||||
const page_sectionsRoutes = require('./routes/page_sections');
|
|
||||||
|
|
||||||
const servicesRoutes = require('./routes/services');
|
|
||||||
|
|
||||||
const portfolio_itemsRoutes = require('./routes/portfolio_items');
|
|
||||||
|
|
||||||
const testimonialsRoutes = require('./routes/testimonials');
|
|
||||||
|
|
||||||
const skillsRoutes = require('./routes/skills');
|
|
||||||
|
|
||||||
const benefitsRoutes = require('./routes/benefits');
|
|
||||||
|
|
||||||
const social_linksRoutes = require('./routes/social_links');
|
|
||||||
|
|
||||||
const inquiriesRoutes = require('./routes/inquiries');
|
|
||||||
|
|
||||||
|
|
||||||
const getBaseUrl = (url) => {
|
|
||||||
if (!url) return '';
|
|
||||||
return url.endsWith('/api') ? url.slice(0, -4) : url;
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
definition: {
|
|
||||||
openapi: "3.0.0",
|
|
||||||
info: {
|
|
||||||
version: "1.0.0",
|
|
||||||
title: "Blackness Studio Website",
|
|
||||||
description: "Blackness Studio Website Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.",
|
|
||||||
},
|
|
||||||
servers: [
|
|
||||||
{
|
|
||||||
url: getBaseUrl(process.env.NEXT_PUBLIC_BACK_API) || config.swaggerUrl,
|
|
||||||
description: "Development server",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
components: {
|
|
||||||
securitySchemes: {
|
|
||||||
bearerAuth: {
|
|
||||||
type: 'http',
|
|
||||||
scheme: 'bearer',
|
|
||||||
bearerFormat: 'JWT',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
responses: {
|
|
||||||
UnauthorizedError: {
|
|
||||||
description: "Access token is missing or invalid"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
security: [{
|
|
||||||
bearerAuth: []
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
apis: ["./src/routes/*.js"],
|
|
||||||
};
|
|
||||||
|
|
||||||
const specs = swaggerJsDoc(options);
|
|
||||||
app.use('/api-docs', function (req, res, next) {
|
|
||||||
swaggerUI.host = getBaseUrl(process.env.NEXT_PUBLIC_BACK_API) || req.get('host');
|
|
||||||
next()
|
|
||||||
}, swaggerUI.serve, swaggerUI.setup(specs))
|
|
||||||
|
|
||||||
app.use(cors({origin: true}));
|
|
||||||
require('./auth/auth');
|
|
||||||
|
|
||||||
app.use(bodyParser.json());
|
|
||||||
|
|
||||||
app.use('/api/auth', authRoutes);
|
|
||||||
app.use('/api/file', fileRoutes);
|
|
||||||
app.use('/api/pexels', pexelsRoutes);
|
|
||||||
app.enable('trust proxy');
|
|
||||||
|
|
||||||
|
|
||||||
app.use('/api/users', passport.authenticate('jwt', {session: false}), usersRoutes);
|
|
||||||
|
|
||||||
app.use('/api/roles', passport.authenticate('jwt', {session: false}), rolesRoutes);
|
|
||||||
|
|
||||||
app.use('/api/permissions', passport.authenticate('jwt', {session: false}), permissionsRoutes);
|
|
||||||
|
|
||||||
app.use('/api/site_settings', passport.authenticate('jwt', {session: false}), site_settingsRoutes);
|
|
||||||
|
|
||||||
app.use('/api/pages', passport.authenticate('jwt', {session: false}), pagesRoutes);
|
|
||||||
|
|
||||||
app.use('/api/page_sections', passport.authenticate('jwt', {session: false}), page_sectionsRoutes);
|
|
||||||
|
|
||||||
app.use('/api/services', passport.authenticate('jwt', {session: false}), servicesRoutes);
|
|
||||||
|
|
||||||
app.use('/api/portfolio_items', passport.authenticate('jwt', {session: false}), portfolio_itemsRoutes);
|
|
||||||
|
|
||||||
app.use('/api/testimonials', passport.authenticate('jwt', {session: false}), testimonialsRoutes);
|
|
||||||
|
|
||||||
app.use('/api/skills', passport.authenticate('jwt', {session: false}), skillsRoutes);
|
|
||||||
|
|
||||||
app.use('/api/benefits', passport.authenticate('jwt', {session: false}), benefitsRoutes);
|
|
||||||
|
|
||||||
app.use('/api/social_links', passport.authenticate('jwt', {session: false}), social_linksRoutes);
|
|
||||||
|
|
||||||
app.use('/api/inquiries', passport.authenticate('jwt', {session: false}), inquiriesRoutes);
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
'/api/openai',
|
|
||||||
passport.authenticate('jwt', { session: false }),
|
|
||||||
openaiRoutes,
|
|
||||||
);
|
|
||||||
app.use(
|
|
||||||
'/api/ai',
|
|
||||||
passport.authenticate('jwt', { session: false }),
|
|
||||||
openaiRoutes,
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
'/api/search',
|
|
||||||
passport.authenticate('jwt', { session: false }),
|
|
||||||
searchRoutes);
|
|
||||||
app.use(
|
|
||||||
'/api/sql',
|
|
||||||
passport.authenticate('jwt', { session: false }),
|
|
||||||
sqlRoutes);
|
|
||||||
|
|
||||||
|
|
||||||
const publicDir = path.join(
|
|
||||||
__dirname,
|
|
||||||
'../public',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (fs.existsSync(publicDir)) {
|
|
||||||
app.use('/', express.static(publicDir));
|
|
||||||
|
|
||||||
app.get('*', function(request, response) {
|
|
||||||
response.sendFile(
|
|
||||||
path.resolve(publicDir, 'index.html'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const PORT = process.env.NODE_ENV === 'dev_stage' ? 3000 : 8080;
|
|
||||||
|
|
||||||
db.sequelize.sync().then(function () {
|
|
||||||
app.listen(PORT, () => {
|
|
||||||
console.log(`Listening on port ${PORT}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = app;
|
|
||||||
@ -1,149 +0,0 @@
|
|||||||
|
|
||||||
const ValidationError = require('../services/notifications/errors/validation');
|
|
||||||
const RolesDBApi = require('../db/api/roles');
|
|
||||||
|
|
||||||
// Cache for the 'Public' role object
|
|
||||||
let publicRoleCache = null;
|
|
||||||
|
|
||||||
// Function to asynchronously fetch and cache the 'Public' role
|
|
||||||
async function fetchAndCachePublicRole() {
|
|
||||||
try {
|
|
||||||
// Use RolesDBApi to find the role by name 'Public'
|
|
||||||
publicRoleCache = await RolesDBApi.findBy({ name: 'Public' });
|
|
||||||
|
|
||||||
if (!publicRoleCache) {
|
|
||||||
console.error("WARNING: Role 'Public' not found in database during middleware startup. Check your migrations.");
|
|
||||||
// The system might not function correctly without this role. May need to throw an error or use a fallback stub.
|
|
||||||
} else {
|
|
||||||
console.log("'Public' role successfully loaded and cached.");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching 'Public' role during middleware startup:", error);
|
|
||||||
// Handle the error during startup fetch
|
|
||||||
throw error; // Important to know if the app can proceed without the Public role
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger the role fetching when the check-permissions.js module is imported/loaded
|
|
||||||
// This should happen during application startup when routes are being configured.
|
|
||||||
fetchAndCachePublicRole().catch(error => {
|
|
||||||
// Handle the case where the fetchAndCachePublicRole promise is rejected
|
|
||||||
console.error("Critical error during permissions middleware initialization:", error);
|
|
||||||
// Decide here if the process should exit if the Public role is essential.
|
|
||||||
// process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware creator to check if the current user (or Public role) has a specific permission.
|
|
||||||
* @param {string} permission - The name of the required permission.
|
|
||||||
* @return {import("express").RequestHandler} Express middleware function.
|
|
||||||
*/
|
|
||||||
function checkPermissions(permission) {
|
|
||||||
return async (req, res, next) => {
|
|
||||||
const { currentUser } = req;
|
|
||||||
|
|
||||||
// 1. Check self-access bypass (only if the user is authenticated)
|
|
||||||
if (currentUser && (currentUser.id === req.params.id || currentUser.id === req.body.id)) {
|
|
||||||
return next(); // User has access to their own resource
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Check Custom Permissions (only if the user is authenticated)
|
|
||||||
if (currentUser) {
|
|
||||||
// Ensure custom_permissions is an array before using find
|
|
||||||
const customPermissions = Array.isArray(currentUser.custom_permissions)
|
|
||||||
? currentUser.custom_permissions
|
|
||||||
: [];
|
|
||||||
const userPermission = customPermissions.find(
|
|
||||||
(cp) => cp.name === permission,
|
|
||||||
);
|
|
||||||
if (userPermission) {
|
|
||||||
return next(); // User has a custom permission
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Determine the "effective" role for permission check
|
|
||||||
let effectiveRole = null;
|
|
||||||
try {
|
|
||||||
if (currentUser && currentUser.app_role) {
|
|
||||||
// User is authenticated and has an assigned role
|
|
||||||
effectiveRole = currentUser.app_role;
|
|
||||||
} else {
|
|
||||||
// User is NOT authenticated OR is authenticated but has no role
|
|
||||||
// Use the cached 'Public' role
|
|
||||||
if (!publicRoleCache) {
|
|
||||||
// If the cache is unexpectedly empty (e.g., startup error caught),
|
|
||||||
// we can try fetching the role again synchronously (less ideal) or just deny access.
|
|
||||||
console.error("Public role cache is empty. Attempting synchronous fetch...");
|
|
||||||
// Less efficient fallback option:
|
|
||||||
effectiveRole = await RolesDBApi.findBy({ name: 'Public' }); // Could be slow
|
|
||||||
if (!effectiveRole) {
|
|
||||||
// If even the synchronous attempt failed
|
|
||||||
return next(new Error("Internal Server Error: Public role missing and cannot be fetched."));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
effectiveRole = publicRoleCache; // Use the cached object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we got a valid role object
|
|
||||||
if (!effectiveRole) {
|
|
||||||
return next(new Error("Internal Server Error: Could not determine effective role."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Check Permissions on the "effective" role
|
|
||||||
// Assume the effectiveRole object (from app_role or RolesDBApi) has a getPermissions() method
|
|
||||||
// or a 'permissions' property (if permissions are eagerly loaded).
|
|
||||||
let rolePermissions = [];
|
|
||||||
if (typeof effectiveRole.getPermissions === 'function') {
|
|
||||||
rolePermissions = await effectiveRole.getPermissions(); // Get permissions asynchronously if the method exists
|
|
||||||
} else if (Array.isArray(effectiveRole.permissions)) {
|
|
||||||
rolePermissions = effectiveRole.permissions; // Or take from property if permissions are pre-loaded
|
|
||||||
} else {
|
|
||||||
console.error("Role object lacks getPermissions() method or permissions property:", effectiveRole);
|
|
||||||
return next(new Error("Internal Server Error: Invalid role object format."));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (rolePermissions.find((p) => p.name === permission)) {
|
|
||||||
next(); // The "effective" role has the required permission
|
|
||||||
} else {
|
|
||||||
// The "effective" role does not have the required permission
|
|
||||||
const roleName = effectiveRole.name || 'unknown role';
|
|
||||||
next(new ValidationError('auth.forbidden', `Role '${roleName}' denied access to '${permission}'.`));
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
// Handle errors during role or permission fetching
|
|
||||||
console.error("Error during permission check:", e);
|
|
||||||
next(e); // Pass the error to the next middleware
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const METHOD_MAP = {
|
|
||||||
POST: 'CREATE',
|
|
||||||
GET: 'READ',
|
|
||||||
PUT: 'UPDATE',
|
|
||||||
PATCH: 'UPDATE',
|
|
||||||
DELETE: 'DELETE',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware creator to check standard CRUD permissions based on HTTP method and entity name.
|
|
||||||
* @param {string} name - The name of the entity.
|
|
||||||
* @return {import("express").RequestHandler} Express middleware function.
|
|
||||||
*/
|
|
||||||
function checkCrudPermissions(name) {
|
|
||||||
return (req, res, next) => {
|
|
||||||
// Dynamically determine the permission name (e.g., 'READ_USERS')
|
|
||||||
const permissionName = `${METHOD_MAP[req.method]}_${name.toUpperCase()}`;
|
|
||||||
// Call the checkPermissions middleware with the determined permission
|
|
||||||
checkPermissions(permissionName)(req, res, next);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
checkPermissions,
|
|
||||||
checkCrudPermissions,
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
const util = require('util');
|
|
||||||
const Multer = require('multer');
|
|
||||||
const maxSize = 10 * 1024 * 1024;
|
|
||||||
|
|
||||||
let processFile = Multer({
|
|
||||||
storage: Multer.memoryStorage(),
|
|
||||||
limits: { fileSize: maxSize },
|
|
||||||
}).single("file");
|
|
||||||
|
|
||||||
let processFileMiddleware = util.promisify(processFile);
|
|
||||||
module.exports = processFileMiddleware;
|
|
||||||
@ -1,207 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const passport = require('passport');
|
|
||||||
|
|
||||||
const config = require('../config');
|
|
||||||
const AuthService = require('../services/auth');
|
|
||||||
const ForbiddenError = require('../services/notifications/errors/forbidden');
|
|
||||||
const EmailSender = require('../services/email');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Auth:
|
|
||||||
* type: object
|
|
||||||
* required:
|
|
||||||
* - email
|
|
||||||
* - password
|
|
||||||
* properties:
|
|
||||||
* email:
|
|
||||||
* type: string
|
|
||||||
* default: admin@flatlogic.com
|
|
||||||
* description: User email
|
|
||||||
* password:
|
|
||||||
* type: string
|
|
||||||
* default: password
|
|
||||||
* description: User password
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Auth
|
|
||||||
* description: Authorization operations
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/auth/signin/local:
|
|
||||||
* post:
|
|
||||||
* tags: [Auth]
|
|
||||||
* summary: Logs user into the system
|
|
||||||
* description: Logs user into the system
|
|
||||||
* requestBody:
|
|
||||||
* description: Set valid user email and password
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Auth"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Successful login
|
|
||||||
* 400:
|
|
||||||
* description: Invalid username/password supplied
|
|
||||||
* x-codegen-request-body-name: body
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.post('/signin/local', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await AuthService.signin(req.body.email, req.body.password, req,);
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/auth/me:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Auth]
|
|
||||||
* summary: Get current authorized user info
|
|
||||||
* description: Get current authorized user info
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Successful retrieval of current authorized user data
|
|
||||||
* 400:
|
|
||||||
* description: Invalid username/password supplied
|
|
||||||
* x-codegen-request-body-name: body
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.get('/me', passport.authenticate('jwt', {session: false}), (req, res) => {
|
|
||||||
if (!req.currentUser || !req.currentUser.id) {
|
|
||||||
throw new ForbiddenError();
|
|
||||||
}
|
|
||||||
|
|
||||||
const payload = req.currentUser;
|
|
||||||
delete payload.password;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.put('/password-reset', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await AuthService.passwordReset(req.body.token, req.body.password, req,);
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.put('/password-update', passport.authenticate('jwt', {session: false}), wrapAsync(async (req, res) => {
|
|
||||||
const payload = await AuthService.passwordUpdate(req.body.currentPassword, req.body.newPassword, req);
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.post('/send-email-address-verification-email', passport.authenticate('jwt', {session: false}), wrapAsync(async (req, res) => {
|
|
||||||
if (!req.currentUser) {
|
|
||||||
throw new ForbiddenError();
|
|
||||||
}
|
|
||||||
|
|
||||||
await AuthService.sendEmailAddressVerificationEmail(req.currentUser.email);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.post('/send-password-reset-email', wrapAsync(async (req, res) => {
|
|
||||||
const link = new URL(req.headers.referer);
|
|
||||||
await AuthService.sendPasswordResetEmail(req.body.email, 'register', link.host,);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/auth/signup:
|
|
||||||
* post:
|
|
||||||
* tags: [Auth]
|
|
||||||
* summary: Register new user into the system
|
|
||||||
* description: Register new user into the system
|
|
||||||
* requestBody:
|
|
||||||
* description: Set valid user email and password
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Auth"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: New user successfully signed up
|
|
||||||
* 400:
|
|
||||||
* description: Invalid username/password supplied
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
* x-codegen-request-body-name: body
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.post('/signup', wrapAsync(async (req, res) => {
|
|
||||||
const link = new URL(req.headers.referer);
|
|
||||||
const payload = await AuthService.signup(
|
|
||||||
req.body.email,
|
|
||||||
req.body.password,
|
|
||||||
|
|
||||||
req,
|
|
||||||
link.host,
|
|
||||||
)
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.put('/profile', passport.authenticate('jwt', {session: false}), wrapAsync(async (req, res) => {
|
|
||||||
if (!req.currentUser || !req.currentUser.id) {
|
|
||||||
throw new ForbiddenError();
|
|
||||||
}
|
|
||||||
|
|
||||||
await AuthService.updateProfile(req.body.profile, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.put('/verify-email', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await AuthService.verifyEmail(req.body.token, req, req.headers.referer)
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.get('/email-configured', (req, res) => {
|
|
||||||
const payload = EmailSender.isConfigured;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/signin/google', (req, res, next) => {
|
|
||||||
passport.authenticate("google", {scope: ["profile", "email"], state: req.query.app})(req, res, next);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/signin/google/callback', passport.authenticate("google", {failureRedirect: "/login", session: false}),
|
|
||||||
|
|
||||||
function (req, res) {
|
|
||||||
socialRedirect(res, req.query.state, req.user.token, config);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get('/signin/microsoft', (req, res, next) => {
|
|
||||||
passport.authenticate("microsoft", {
|
|
||||||
scope: ["https://graph.microsoft.com/user.read openid"],
|
|
||||||
state: req.query.app
|
|
||||||
})(req, res, next);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/signin/microsoft/callback', passport.authenticate("microsoft", {
|
|
||||||
failureRedirect: "/login",
|
|
||||||
session: false
|
|
||||||
}),
|
|
||||||
function (req, res) {
|
|
||||||
socialRedirect(res, req.query.state, req.user.token, config);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
function socialRedirect(res, state, token, config) {
|
|
||||||
res.redirect(config.uiUrl + "/login?token=" + token);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,438 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const BenefitsService = require('../services/benefits');
|
|
||||||
const BenefitsDBApi = require('../db/api/benefits');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('benefits'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Benefits:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* title:
|
|
||||||
* type: string
|
|
||||||
* default: title
|
|
||||||
* description:
|
|
||||||
* type: string
|
|
||||||
* default: description
|
|
||||||
* icon_name:
|
|
||||||
* type: string
|
|
||||||
* default: icon_name
|
|
||||||
|
|
||||||
* sort_order:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Benefits
|
|
||||||
* description: The Benefits managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await BenefitsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await BenefitsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await BenefitsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await BenefitsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await BenefitsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Get all benefits
|
|
||||||
* description: Get all benefits
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Benefits list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await BenefitsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','title','description','icon_name',
|
|
||||||
'sort_order',
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Count all benefits
|
|
||||||
* description: Count all benefits
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Benefits count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await BenefitsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Find all benefits that match search criteria
|
|
||||||
* description: Find all benefits that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Benefits list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await BenefitsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/benefits/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Benefits]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Benefits"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await BenefitsDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const config = require('../config');
|
|
||||||
const path = require('path');
|
|
||||||
const passport = require('passport');
|
|
||||||
const services = require('../services/file');
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.get('/download', (req, res) => {
|
|
||||||
if (process.env.NODE_ENV == "production" || process.env.NEXT_PUBLIC_BACK_API) {
|
|
||||||
services.downloadGCloud(req, res);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
services.downloadLocal(req, res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.post('/upload/:table/:field', passport.authenticate('jwt', {session: false}), (req, res) => {
|
|
||||||
const fileName = `${req.params.table}/${req.params.field}`;
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV == "production" || process.env.NEXT_PUBLIC_BACK_API) {
|
|
||||||
services.uploadGCloud(fileName, req, res);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
services.uploadLocal(fileName, {
|
|
||||||
entity: null,
|
|
||||||
maxFileSize: 10 * 1024 * 1024,
|
|
||||||
folderIncludesAuthenticationUid: false,
|
|
||||||
})(req, res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,448 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const InquiriesService = require('../services/inquiries');
|
|
||||||
const InquiriesDBApi = require('../db/api/inquiries');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('inquiries'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Inquiries:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* full_name:
|
|
||||||
* type: string
|
|
||||||
* default: full_name
|
|
||||||
* email:
|
|
||||||
* type: string
|
|
||||||
* default: email
|
|
||||||
* company_name:
|
|
||||||
* type: string
|
|
||||||
* default: company_name
|
|
||||||
* subject:
|
|
||||||
* type: string
|
|
||||||
* default: subject
|
|
||||||
* message:
|
|
||||||
* type: string
|
|
||||||
* default: message
|
|
||||||
* source_page:
|
|
||||||
* type: string
|
|
||||||
* default: source_page
|
|
||||||
* fiverr_url:
|
|
||||||
* type: string
|
|
||||||
* default: fiverr_url
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Inquiries
|
|
||||||
* description: The Inquiries managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await InquiriesService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await InquiriesService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await InquiriesService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await InquiriesService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await InquiriesService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Get all inquiries
|
|
||||||
* description: Get all inquiries
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Inquiries list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await InquiriesDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','full_name','email','company_name','subject','message','source_page','fiverr_url',
|
|
||||||
|
|
||||||
|
|
||||||
'received_at','replied_at',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Count all inquiries
|
|
||||||
* description: Count all inquiries
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Inquiries count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await InquiriesDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Find all inquiries that match search criteria
|
|
||||||
* description: Find all inquiries that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Inquiries list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await InquiriesDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/inquiries/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Inquiries]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Inquiries"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await InquiriesDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,328 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const db = require('../db/models');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
const router = express.Router();
|
|
||||||
const sjs = require('sequelize-json-schema');
|
|
||||||
const { getWidget, askGpt } = require('../services/openai');
|
|
||||||
const { LocalAIApi } = require('../ai/LocalAIApi');
|
|
||||||
|
|
||||||
const loadRolesModules = () => {
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
RolesService: require('../services/roles'),
|
|
||||||
RolesDBApi: require('../db/api/roles'),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Roles modules are missing. Advanced roles are required for this endpoint.', error);
|
|
||||||
const err = new Error('Roles modules are missing. Advanced roles are required for this endpoint.');
|
|
||||||
err.originalError = error;
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/roles-info/{infoId}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Remove role information by ID
|
|
||||||
* description: Remove specific role information by ID
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: infoId
|
|
||||||
* description: ID of role information to remove
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* - in: query
|
|
||||||
* name: userId
|
|
||||||
* description: ID of the user
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* - in: query
|
|
||||||
* name: key
|
|
||||||
* description: Key of the role information to remove
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Role information successfully removed
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* user:
|
|
||||||
* type: string
|
|
||||||
* description: The user information
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID or key supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Role not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.delete(
|
|
||||||
'/roles-info/:infoId',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const { RolesService } = loadRolesModules();
|
|
||||||
const role = await RolesService.removeRoleInfoById(
|
|
||||||
req.query.infoId,
|
|
||||||
req.query.roleId,
|
|
||||||
req.query.key,
|
|
||||||
req.currentUser,
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(role);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/role-info/{roleId}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Get role information by key
|
|
||||||
* description: Get specific role information by key
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: roleId
|
|
||||||
* description: ID of role to get information for
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* - in: query
|
|
||||||
* name: key
|
|
||||||
* description: Key of the role information to retrieve
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Role information successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* info:
|
|
||||||
* type: string
|
|
||||||
* description: The role information
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID or key supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Role not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
'/info-by-key',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const { RolesService, RolesDBApi } = loadRolesModules();
|
|
||||||
const roleId = req.query.roleId;
|
|
||||||
const key = req.query.key;
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
let info = await RolesService.getRoleInfoByKey(
|
|
||||||
key,
|
|
||||||
roleId,
|
|
||||||
currentUser,
|
|
||||||
);
|
|
||||||
const role = await RolesDBApi.findBy({ id: roleId });
|
|
||||||
if (!role?.role_customization) {
|
|
||||||
await Promise.all(["pie", "bar"].map(async (e) => {
|
|
||||||
const schema = await sjs.getSequelizeSchema(db.sequelize, {});
|
|
||||||
const payload = {
|
|
||||||
description: `Create some cool ${e} chart`,
|
|
||||||
modelDefinition: schema.definitions,
|
|
||||||
};
|
|
||||||
const widgetId = await getWidget(payload, currentUser?.id, roleId);
|
|
||||||
if (widgetId) {
|
|
||||||
await RolesService.addRoleInfo(
|
|
||||||
roleId,
|
|
||||||
currentUser?.id,
|
|
||||||
'widgets',
|
|
||||||
widgetId,
|
|
||||||
req.currentUser,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
info = await RolesService.getRoleInfoByKey(
|
|
||||||
key,
|
|
||||||
roleId,
|
|
||||||
currentUser,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
res.status(200).send(info);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
'/create_widget',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const { RolesService } = loadRolesModules();
|
|
||||||
const { description, userId, roleId } = req.body;
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const schema = await sjs.getSequelizeSchema(db.sequelize, {});
|
|
||||||
const payload = {
|
|
||||||
description,
|
|
||||||
modelDefinition: schema.definitions,
|
|
||||||
};
|
|
||||||
|
|
||||||
const widgetId = await getWidget(payload, userId, roleId);
|
|
||||||
|
|
||||||
if (widgetId) {
|
|
||||||
await RolesService.addRoleInfo(
|
|
||||||
roleId,
|
|
||||||
userId,
|
|
||||||
'widgets',
|
|
||||||
widgetId,
|
|
||||||
currentUser,
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(200).send(widgetId);
|
|
||||||
} else {
|
|
||||||
return res.status(400).send(widgetId);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/openai/response:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [OpenAI]
|
|
||||||
* summary: Proxy a Responses API request
|
|
||||||
* description: Sends the payload to the Flatlogic AI proxy and returns the response.
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* input:
|
|
||||||
* type: array
|
|
||||||
* description: List of messages with roles and content.
|
|
||||||
* items:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* role:
|
|
||||||
* type: string
|
|
||||||
* content:
|
|
||||||
* type: string
|
|
||||||
* options:
|
|
||||||
* type: object
|
|
||||||
* description: Optional polling controls.
|
|
||||||
* properties:
|
|
||||||
* poll_interval:
|
|
||||||
* type: number
|
|
||||||
* poll_timeout:
|
|
||||||
* type: number
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: AI response received
|
|
||||||
* 400:
|
|
||||||
* description: Invalid request
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 502:
|
|
||||||
* description: Proxy error
|
|
||||||
*/
|
|
||||||
router.post(
|
|
||||||
'/response',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const body = req.body || {};
|
|
||||||
const options = body.options || {};
|
|
||||||
const payload = { ...body };
|
|
||||||
delete payload.options;
|
|
||||||
|
|
||||||
const response = await LocalAIApi.createResponse(payload, options);
|
|
||||||
|
|
||||||
if (response.success) {
|
|
||||||
return res.status(200).send(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error('AI proxy error:', response);
|
|
||||||
const status = response.error === 'input_missing' ? 400 : 502;
|
|
||||||
return res.status(status).send(response);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/openai/ask:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [OpenAI]
|
|
||||||
* summary: Ask a question to ChatGPT
|
|
||||||
* description: Send a question through the Flatlogic AI proxy and get a response
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* prompt:
|
|
||||||
* type: string
|
|
||||||
* description: The question to ask ChatGPT
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Question successfully answered
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* success:
|
|
||||||
* type: boolean
|
|
||||||
* description: Whether the request was successful
|
|
||||||
* data:
|
|
||||||
* type: string
|
|
||||||
* description: The answer from ChatGPT
|
|
||||||
* 400:
|
|
||||||
* description: Invalid request
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post(
|
|
||||||
'/ask-gpt',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const { prompt } = req.body;
|
|
||||||
if (!prompt) {
|
|
||||||
return res.status(400).send({
|
|
||||||
success: false,
|
|
||||||
error: 'Prompt is required',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await askGpt(prompt);
|
|
||||||
|
|
||||||
if (response.success) {
|
|
||||||
return res.status(200).send(response);
|
|
||||||
} else {
|
|
||||||
return res.status(500).send(response);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
@ -1,454 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Page_sectionsService = require('../services/page_sections');
|
|
||||||
const Page_sectionsDBApi = require('../db/api/page_sections');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('page_sections'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Page_sections:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* section_label:
|
|
||||||
* type: string
|
|
||||||
* default: section_label
|
|
||||||
* headline:
|
|
||||||
* type: string
|
|
||||||
* default: headline
|
|
||||||
* subheadline:
|
|
||||||
* type: string
|
|
||||||
* default: subheadline
|
|
||||||
* body:
|
|
||||||
* type: string
|
|
||||||
* default: body
|
|
||||||
* primary_button_label:
|
|
||||||
* type: string
|
|
||||||
* default: primary_button_label
|
|
||||||
* primary_button_url:
|
|
||||||
* type: string
|
|
||||||
* default: primary_button_url
|
|
||||||
* secondary_button_label:
|
|
||||||
* type: string
|
|
||||||
* default: secondary_button_label
|
|
||||||
* secondary_button_url:
|
|
||||||
* type: string
|
|
||||||
* default: secondary_button_url
|
|
||||||
|
|
||||||
* sort_order:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Page_sections
|
|
||||||
* description: The Page_sections managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Page_sectionsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Page_sectionsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Page_sectionsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Page_sectionsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Page_sectionsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Get all page_sections
|
|
||||||
* description: Get all page_sections
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Page_sections list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Page_sectionsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','section_label','headline','subheadline','body','primary_button_label','primary_button_url','secondary_button_label','secondary_button_url',
|
|
||||||
'sort_order',
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Count all page_sections
|
|
||||||
* description: Count all page_sections
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Page_sections count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Page_sectionsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Find all page_sections that match search criteria
|
|
||||||
* description: Find all page_sections that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Page_sections list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Page_sectionsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_sections/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_sections]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_sections"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await Page_sectionsDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,442 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const PagesService = require('../services/pages');
|
|
||||||
const PagesDBApi = require('../db/api/pages');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('pages'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Pages:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* title:
|
|
||||||
* type: string
|
|
||||||
* default: title
|
|
||||||
* slug:
|
|
||||||
* type: string
|
|
||||||
* default: slug
|
|
||||||
* meta_title:
|
|
||||||
* type: string
|
|
||||||
* default: meta_title
|
|
||||||
* meta_description:
|
|
||||||
* type: string
|
|
||||||
* default: meta_description
|
|
||||||
|
|
||||||
* sort_order:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Pages
|
|
||||||
* description: The Pages managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await PagesService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await PagesService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await PagesService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await PagesService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await PagesService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Get all pages
|
|
||||||
* description: Get all pages
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Pages list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await PagesDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','title','slug','meta_title','meta_description',
|
|
||||||
'sort_order',
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Count all pages
|
|
||||||
* description: Count all pages
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Pages count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await PagesDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Find all pages that match search criteria
|
|
||||||
* description: Find all pages that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Pages list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await PagesDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pages/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pages]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pages"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await PagesDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,429 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const PermissionsService = require('../services/permissions');
|
|
||||||
const PermissionsDBApi = require('../db/api/permissions');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('permissions'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Permissions:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* name:
|
|
||||||
* type: string
|
|
||||||
* default: name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Permissions
|
|
||||||
* description: The Permissions managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await PermissionsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await PermissionsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await PermissionsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await PermissionsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await PermissionsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Get all permissions
|
|
||||||
* description: Get all permissions
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Permissions list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await PermissionsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Count all permissions
|
|
||||||
* description: Count all permissions
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Permissions count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await PermissionsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Find all permissions that match search criteria
|
|
||||||
* description: Find all permissions that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Permissions list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await PermissionsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await PermissionsDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const { pexelsKey, pexelsQuery } = require('../config');
|
|
||||||
const fetch = require('node-fetch');
|
|
||||||
|
|
||||||
const KEY = pexelsKey;
|
|
||||||
|
|
||||||
router.get('/image', async (req, res) => {
|
|
||||||
const headers = {
|
|
||||||
Authorization: `${KEY}`,
|
|
||||||
};
|
|
||||||
const query = pexelsQuery || 'nature';
|
|
||||||
const orientation = 'portrait';
|
|
||||||
const perPage = 1;
|
|
||||||
const url = `https://api.pexels.com/v1/search?query=${query}&orientation=${orientation}&per_page=${perPage}&page=1`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, { headers });
|
|
||||||
const data = await response.json();
|
|
||||||
res.status(200).json(data.photos[0]);
|
|
||||||
} catch (error) {
|
|
||||||
res.status(200).json({ error: 'Failed to fetch image' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/video', async (req, res) => {
|
|
||||||
const headers = {
|
|
||||||
Authorization: `${KEY}`,
|
|
||||||
};
|
|
||||||
const query = pexelsQuery || 'nature';
|
|
||||||
const orientation = 'portrait';
|
|
||||||
const perPage = 1;
|
|
||||||
const url = `https://api.pexels.com/videos/search?query=${query}&orientation=${orientation}&per_page=${perPage}&page=1`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, { headers });
|
|
||||||
const data = await response.json();
|
|
||||||
res.status(200).json(data.videos[0]);
|
|
||||||
} catch (error) {
|
|
||||||
res.status(200).json({ error: 'Failed to fetch video' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/multiple-images', async (req, res) => {
|
|
||||||
const headers = {
|
|
||||||
Authorization: `${KEY}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
const queries = req.query.queries
|
|
||||||
? req.query.queries.split(',')
|
|
||||||
: ['home', 'apple', 'pizza', 'mountains', 'cat'];
|
|
||||||
const orientation = 'square';
|
|
||||||
const perPage = 1;
|
|
||||||
|
|
||||||
const fallbackImage = {
|
|
||||||
src: 'https://images.pexels.com/photos/8199252/pexels-photo-8199252.jpeg',
|
|
||||||
photographer: 'Yan Krukau',
|
|
||||||
photographer_url: 'https://www.pexels.com/@yankrukov',
|
|
||||||
};
|
|
||||||
const fetchFallbackImage = async () => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('https://picsum.photos/600');
|
|
||||||
return {
|
|
||||||
src: response.url,
|
|
||||||
photographer: 'Random Picsum',
|
|
||||||
photographer_url: 'https://picsum.photos/',
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return fallbackImage;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const fetchImage = async (query) => {
|
|
||||||
const url = `https://api.pexels.com/v1/search?query=${query}&orientation=${orientation}&per_page=${perPage}&page=1`;
|
|
||||||
const response = await fetch(url, { headers });
|
|
||||||
const data = await response.json();
|
|
||||||
return data.photos[0] || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const imagePromises = queries.map((query) => fetchImage(query));
|
|
||||||
const imagesResults = await Promise.allSettled(imagePromises);
|
|
||||||
|
|
||||||
const formattedImages = await Promise.all(imagesResults.map(async (result) => {
|
|
||||||
if (result.status === 'fulfilled' && result.value) {
|
|
||||||
const image = result.value;
|
|
||||||
return {
|
|
||||||
src: image.src?.original || fallbackImage.src,
|
|
||||||
photographer: image.photographer || fallbackImage.photographer,
|
|
||||||
photographer_url: image.photographer_url || fallbackImage.photographer_url,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const fallback = await fetchFallbackImage();
|
|
||||||
return {
|
|
||||||
src: fallback.src || '',
|
|
||||||
photographer: fallback.photographer || 'Unknown',
|
|
||||||
photographer_url: fallback.photographer_url || '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
res.json(formattedImages);
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,445 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Portfolio_itemsService = require('../services/portfolio_items');
|
|
||||||
const Portfolio_itemsDBApi = require('../db/api/portfolio_items');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('portfolio_items'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Portfolio_items:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* title:
|
|
||||||
* type: string
|
|
||||||
* default: title
|
|
||||||
* client_name:
|
|
||||||
* type: string
|
|
||||||
* default: client_name
|
|
||||||
* summary:
|
|
||||||
* type: string
|
|
||||||
* default: summary
|
|
||||||
* case_study:
|
|
||||||
* type: string
|
|
||||||
* default: case_study
|
|
||||||
* external_url:
|
|
||||||
* type: string
|
|
||||||
* default: external_url
|
|
||||||
* tech_stack:
|
|
||||||
* type: string
|
|
||||||
* default: tech_stack
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Portfolio_items
|
|
||||||
* description: The Portfolio_items managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Portfolio_itemsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Portfolio_itemsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Portfolio_itemsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Portfolio_itemsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Portfolio_itemsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Get all portfolio_items
|
|
||||||
* description: Get all portfolio_items
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Portfolio_items list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Portfolio_itemsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','title','client_name','summary','case_study','external_url','tech_stack',
|
|
||||||
|
|
||||||
|
|
||||||
'published_on',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Count all portfolio_items
|
|
||||||
* description: Count all portfolio_items
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Portfolio_items count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Portfolio_itemsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Find all portfolio_items that match search criteria
|
|
||||||
* description: Find all portfolio_items that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Portfolio_items list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Portfolio_itemsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/portfolio_items/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Portfolio_items]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Portfolio_items"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await Portfolio_itemsDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,429 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const RolesService = require('../services/roles');
|
|
||||||
const RolesDBApi = require('../db/api/roles');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('roles'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Roles:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* name:
|
|
||||||
* type: string
|
|
||||||
* default: name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Roles
|
|
||||||
* description: The Roles managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await RolesService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await RolesService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await RolesService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await RolesService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await RolesService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Get all roles
|
|
||||||
* description: Get all roles
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Roles list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await RolesDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Count all roles
|
|
||||||
* description: Count all roles
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Roles count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await RolesDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Find all roles that match search criteria
|
|
||||||
* description: Find all roles that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Roles list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await RolesDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await RolesDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const SearchService = require('../services/search');
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { checkCrudPermissions } = require('../middlewares/check-permissions');
|
|
||||||
router.use(checkCrudPermissions('search'));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* path:
|
|
||||||
* /api/search:
|
|
||||||
* post:
|
|
||||||
* summary: Search
|
|
||||||
* description: Search results across multiple tables
|
|
||||||
* requestBody:
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* searchQuery:
|
|
||||||
* type: string
|
|
||||||
* required:
|
|
||||||
* - searchQuery
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Successful request
|
|
||||||
* 400:
|
|
||||||
* description: Invalid request
|
|
||||||
* 500:
|
|
||||||
* description: Internal server error
|
|
||||||
*/
|
|
||||||
|
|
||||||
router.post('/', async (req, res) => {
|
|
||||||
const { searchQuery } = req.body;
|
|
||||||
|
|
||||||
if (!searchQuery) {
|
|
||||||
return res.status(400).json({ error: 'Please enter a search query' });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const foundMatches = await SearchService.search(searchQuery, req.currentUser );
|
|
||||||
res.json(foundMatches);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Internal Server Error', error);
|
|
||||||
res.status(500).json({ error: 'Internal Server Error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,448 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const ServicesService = require('../services/services');
|
|
||||||
const ServicesDBApi = require('../db/api/services');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('services'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Services:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* name:
|
|
||||||
* type: string
|
|
||||||
* default: name
|
|
||||||
* short_description:
|
|
||||||
* type: string
|
|
||||||
* default: short_description
|
|
||||||
* details:
|
|
||||||
* type: string
|
|
||||||
* default: details
|
|
||||||
* cta_label:
|
|
||||||
* type: string
|
|
||||||
* default: cta_label
|
|
||||||
* cta_url:
|
|
||||||
* type: string
|
|
||||||
* default: cta_url
|
|
||||||
* icon_name:
|
|
||||||
* type: string
|
|
||||||
* default: icon_name
|
|
||||||
|
|
||||||
* sort_order:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Services
|
|
||||||
* description: The Services managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await ServicesService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await ServicesService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await ServicesService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await ServicesService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await ServicesService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Get all services
|
|
||||||
* description: Get all services
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Services list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await ServicesDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name','short_description','details','cta_label','cta_url','icon_name',
|
|
||||||
'sort_order',
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Count all services
|
|
||||||
* description: Count all services
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Services count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await ServicesDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Find all services that match search criteria
|
|
||||||
* description: Find all services that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Services list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await ServicesDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/services/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Services]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Services"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await ServicesDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,459 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Site_settingsService = require('../services/site_settings');
|
|
||||||
const Site_settingsDBApi = require('../db/api/site_settings');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('site_settings'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Site_settings:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* site_name:
|
|
||||||
* type: string
|
|
||||||
* default: site_name
|
|
||||||
* tagline:
|
|
||||||
* type: string
|
|
||||||
* default: tagline
|
|
||||||
* primary_domain:
|
|
||||||
* type: string
|
|
||||||
* default: primary_domain
|
|
||||||
* primary_cta_label:
|
|
||||||
* type: string
|
|
||||||
* default: primary_cta_label
|
|
||||||
* primary_cta_url:
|
|
||||||
* type: string
|
|
||||||
* default: primary_cta_url
|
|
||||||
* contact_email:
|
|
||||||
* type: string
|
|
||||||
* default: contact_email
|
|
||||||
* contact_phone:
|
|
||||||
* type: string
|
|
||||||
* default: contact_phone
|
|
||||||
* location:
|
|
||||||
* type: string
|
|
||||||
* default: location
|
|
||||||
* accent_color_hex:
|
|
||||||
* type: string
|
|
||||||
* default: accent_color_hex
|
|
||||||
* seo_title:
|
|
||||||
* type: string
|
|
||||||
* default: seo_title
|
|
||||||
* seo_description:
|
|
||||||
* type: string
|
|
||||||
* default: seo_description
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Site_settings
|
|
||||||
* description: The Site_settings managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Site_settingsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Site_settingsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Site_settingsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Site_settingsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Site_settingsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Get all site_settings
|
|
||||||
* description: Get all site_settings
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Site_settings list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Site_settingsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','site_name','tagline','primary_domain','primary_cta_label','primary_cta_url','contact_email','contact_phone','location','accent_color_hex','seo_title','seo_description',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Count all site_settings
|
|
||||||
* description: Count all site_settings
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Site_settings count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Site_settingsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Find all site_settings that match search criteria
|
|
||||||
* description: Find all site_settings that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Site_settings list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Site_settingsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/site_settings/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Site_settings]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Site_settings"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await Site_settingsDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,436 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const SkillsService = require('../services/skills');
|
|
||||||
const SkillsDBApi = require('../db/api/skills');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('skills'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Skills:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* name:
|
|
||||||
* type: string
|
|
||||||
* default: name
|
|
||||||
|
|
||||||
* proficiency_level:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
* sort_order:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Skills
|
|
||||||
* description: The Skills managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await SkillsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await SkillsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await SkillsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await SkillsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await SkillsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Get all skills
|
|
||||||
* description: Get all skills
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Skills list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await SkillsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name',
|
|
||||||
'proficiency_level','sort_order',
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Count all skills
|
|
||||||
* description: Count all skills
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Skills count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await SkillsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Find all skills that match search criteria
|
|
||||||
* description: Find all skills that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Skills list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await SkillsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/skills/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Skills]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Skills"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await SkillsDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,436 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Social_linksService = require('../services/social_links');
|
|
||||||
const Social_linksDBApi = require('../db/api/social_links');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('social_links'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Social_links:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* label:
|
|
||||||
* type: string
|
|
||||||
* default: label
|
|
||||||
* url:
|
|
||||||
* type: string
|
|
||||||
* default: url
|
|
||||||
|
|
||||||
* sort_order:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Social_links
|
|
||||||
* description: The Social_links managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Social_linksService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Social_linksService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Social_linksService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Social_linksService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Social_linksService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Get all social_links
|
|
||||||
* description: Get all social_links
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Social_links list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Social_linksDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','label','url',
|
|
||||||
'sort_order',
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Count all social_links
|
|
||||||
* description: Count all social_links
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Social_links count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Social_linksDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Find all social_links that match search criteria
|
|
||||||
* description: Find all social_links that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Social_links list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Social_linksDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/social_links/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Social_links]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Social_links"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await Social_linksDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const db = require('../db/models');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/sql:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* summary: Execute a SELECT-only SQL query
|
|
||||||
* description: Executes a read-only SQL query and returns rows.
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
* sql:
|
|
||||||
* type: string
|
|
||||||
* required:
|
|
||||||
* - sql
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Query result
|
|
||||||
* 400:
|
|
||||||
* description: Invalid SQL
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 500:
|
|
||||||
* description: Internal server error
|
|
||||||
*/
|
|
||||||
router.post(
|
|
||||||
'/',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const { sql } = req.body;
|
|
||||||
if (typeof sql !== 'string' || !sql.trim()) {
|
|
||||||
return res.status(400).json({ error: 'SQL is required' });
|
|
||||||
}
|
|
||||||
|
|
||||||
const normalized = sql.trim().replace(/;+\s*$/, '');
|
|
||||||
if (!/^select\b/i.test(normalized)) {
|
|
||||||
return res.status(400).json({ error: 'Only SELECT statements are allowed' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalized.includes(';')) {
|
|
||||||
return res.status(400).json({ error: 'Only a single SELECT statement is allowed' });
|
|
||||||
}
|
|
||||||
|
|
||||||
const rows = await db.sequelize.query(normalized, {
|
|
||||||
type: db.Sequelize.QueryTypes.SELECT,
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.status(200).json({ rows });
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,447 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const TestimonialsService = require('../services/testimonials');
|
|
||||||
const TestimonialsDBApi = require('../db/api/testimonials');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('testimonials'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Testimonials:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* client_name:
|
|
||||||
* type: string
|
|
||||||
* default: client_name
|
|
||||||
* client_title:
|
|
||||||
* type: string
|
|
||||||
* default: client_title
|
|
||||||
* company_name:
|
|
||||||
* type: string
|
|
||||||
* default: company_name
|
|
||||||
* quote:
|
|
||||||
* type: string
|
|
||||||
* default: quote
|
|
||||||
* source:
|
|
||||||
* type: string
|
|
||||||
* default: source
|
|
||||||
* source_url:
|
|
||||||
* type: string
|
|
||||||
* default: source_url
|
|
||||||
|
|
||||||
* rating:
|
|
||||||
* type: integer
|
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Testimonials
|
|
||||||
* description: The Testimonials managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await TestimonialsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await TestimonialsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await TestimonialsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await TestimonialsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await TestimonialsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Get all testimonials
|
|
||||||
* description: Get all testimonials
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Testimonials list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await TestimonialsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','client_name','client_title','company_name','quote','source','source_url',
|
|
||||||
'rating',
|
|
||||||
|
|
||||||
'testimonial_date',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Count all testimonials
|
|
||||||
* description: Count all testimonials
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Testimonials count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await TestimonialsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Find all testimonials that match search criteria
|
|
||||||
* description: Find all testimonials that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Testimonials list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await TestimonialsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/testimonials/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Testimonials]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Testimonials"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await TestimonialsDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,440 +0,0 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const UsersService = require('../services/users');
|
|
||||||
const UsersDBApi = require('../db/api/users');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('users'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* components:
|
|
||||||
* schemas:
|
|
||||||
* Users:
|
|
||||||
* type: object
|
|
||||||
* properties:
|
|
||||||
|
|
||||||
* firstName:
|
|
||||||
* type: string
|
|
||||||
* default: firstName
|
|
||||||
* lastName:
|
|
||||||
* type: string
|
|
||||||
* default: lastName
|
|
||||||
* phoneNumber:
|
|
||||||
* type: string
|
|
||||||
* default: phoneNumber
|
|
||||||
* email:
|
|
||||||
* type: string
|
|
||||||
* default: email
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* tags:
|
|
||||||
* name: Users
|
|
||||||
* description: The Users managing API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await UsersService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await UsersService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await UsersService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await UsersService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await UsersService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Get all users
|
|
||||||
* description: Get all users
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Users list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await UsersDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','firstName','lastName','phoneNumber','email',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users/count:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Count all users
|
|
||||||
* description: Count all users
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Users count successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await UsersDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users/autocomplete:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Find all users that match search criteria
|
|
||||||
* description: Find all users that match search criteria
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Users list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await UsersDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/users/{id}:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Users]
|
|
||||||
* summary: Get selected item
|
|
||||||
* description: Get selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: ID of item to get
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Selected item successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Users"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
|
||||||
const payload = await UsersDBApi.findBy(
|
|
||||||
{ id: req.params.id },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
delete payload.password;
|
|
||||||
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,312 +0,0 @@
|
|||||||
const UsersDBApi = require('../db/api/users');
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const ForbiddenError = require('./notifications/errors/forbidden');
|
|
||||||
const bcrypt = require('bcrypt');
|
|
||||||
const EmailAddressVerificationEmail = require('./email/list/addressVerification');
|
|
||||||
const InvitationEmail = require("./email/list/invitation");
|
|
||||||
const PasswordResetEmail = require('./email/list/passwordReset');
|
|
||||||
const EmailSender = require('./email');
|
|
||||||
const config = require('../config');
|
|
||||||
const helpers = require('../helpers');
|
|
||||||
|
|
||||||
class Auth {
|
|
||||||
static async signup(email, password, options = {}, host) {
|
|
||||||
const user = await UsersDBApi.findBy({email});
|
|
||||||
|
|
||||||
const hashedPassword = await bcrypt.hash(
|
|
||||||
password,
|
|
||||||
config.bcrypt.saltRounds,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
if (user.authenticationUid) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.emailAlreadyInUse',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.disabled) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.userDisabled',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await UsersDBApi.updatePassword(
|
|
||||||
user.id,
|
|
||||||
hashedPassword,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (EmailSender.isConfigured) {
|
|
||||||
await this.sendEmailAddressVerificationEmail(
|
|
||||||
user.email,
|
|
||||||
host,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
user: {
|
|
||||||
id: user.id,
|
|
||||||
email: user.email
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return helpers.jwtSign(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const newUser = await UsersDBApi.createFromAuth(
|
|
||||||
{
|
|
||||||
firstName: email.split('@')[0],
|
|
||||||
password: hashedPassword,
|
|
||||||
email: email,
|
|
||||||
|
|
||||||
},
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (EmailSender.isConfigured) {
|
|
||||||
await this.sendEmailAddressVerificationEmail(
|
|
||||||
newUser.email,
|
|
||||||
host,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
user: {
|
|
||||||
id: newUser.id,
|
|
||||||
email: newUser.email
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return helpers.jwtSign(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async signin(email, password, options = {}) {
|
|
||||||
const user = await UsersDBApi.findBy({email});
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.userNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.disabled) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.userDisabled',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.password) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.wrongPassword',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EmailSender.isConfigured) {
|
|
||||||
user.emailVerified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.emailVerified) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.userNotVerified',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const passwordsMatch = await bcrypt.compare(
|
|
||||||
password,
|
|
||||||
user.password,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!passwordsMatch) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.wrongPassword',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
user: {
|
|
||||||
id: user.id,
|
|
||||||
email: user.email
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return helpers.jwtSign(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async sendEmailAddressVerificationEmail(
|
|
||||||
email,
|
|
||||||
host,
|
|
||||||
) {
|
|
||||||
|
|
||||||
|
|
||||||
let link;
|
|
||||||
try {
|
|
||||||
const token = await UsersDBApi.generateEmailVerificationToken(
|
|
||||||
email,
|
|
||||||
);
|
|
||||||
link = `${host}/verify-email?token=${token}`;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.emailAddressVerificationEmail.error',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailAddressVerificationEmail = new EmailAddressVerificationEmail(
|
|
||||||
email,
|
|
||||||
link,
|
|
||||||
);
|
|
||||||
|
|
||||||
return new EmailSender(
|
|
||||||
emailAddressVerificationEmail,
|
|
||||||
).send();
|
|
||||||
}
|
|
||||||
|
|
||||||
static async sendPasswordResetEmail(email, type = 'register', host) {
|
|
||||||
|
|
||||||
|
|
||||||
let link;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const token = await UsersDBApi.generatePasswordResetToken(
|
|
||||||
email,
|
|
||||||
);
|
|
||||||
link = `${host}/password-reset?token=${token}`;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.passwordReset.error',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let passwordResetEmail;
|
|
||||||
if (type === 'register') {
|
|
||||||
passwordResetEmail = new PasswordResetEmail(
|
|
||||||
email,
|
|
||||||
link,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (type === 'invitation') {
|
|
||||||
passwordResetEmail = new InvitationEmail(
|
|
||||||
email,
|
|
||||||
link,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new EmailSender(passwordResetEmail).send();
|
|
||||||
}
|
|
||||||
|
|
||||||
static async verifyEmail(token, options = {}) {
|
|
||||||
const user = await UsersDBApi.findByEmailVerificationToken(
|
|
||||||
token,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.emailAddressVerificationEmail.invalidToken',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return UsersDBApi.markEmailVerified(
|
|
||||||
user.id,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async passwordUpdate(currentPassword, newPassword, options) {
|
|
||||||
const currentUser = options.currentUser || null;
|
|
||||||
if (!currentUser) {
|
|
||||||
throw new ForbiddenError();
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentPasswordMatch = await bcrypt.compare(
|
|
||||||
currentPassword,
|
|
||||||
currentUser.password,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!currentPasswordMatch) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.wrongPassword'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const newPasswordMatch = await bcrypt.compare(
|
|
||||||
newPassword,
|
|
||||||
currentUser.password,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (newPasswordMatch) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.passwordUpdate.samePassword'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const hashedPassword = await bcrypt.hash(
|
|
||||||
newPassword,
|
|
||||||
config.bcrypt.saltRounds,
|
|
||||||
);
|
|
||||||
|
|
||||||
return UsersDBApi.updatePassword(
|
|
||||||
currentUser.id,
|
|
||||||
hashedPassword,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async passwordReset(
|
|
||||||
token,
|
|
||||||
password,
|
|
||||||
options = {},
|
|
||||||
) {
|
|
||||||
const user = await UsersDBApi.findByPasswordResetToken(
|
|
||||||
token,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'auth.passwordReset.invalidToken',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const hashedPassword = await bcrypt.hash(
|
|
||||||
password,
|
|
||||||
config.bcrypt.saltRounds,
|
|
||||||
);
|
|
||||||
|
|
||||||
return UsersDBApi.updatePassword(
|
|
||||||
user.id,
|
|
||||||
hashedPassword,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async updateProfile(data, currentUser) {
|
|
||||||
let transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await UsersDBApi.findBy(
|
|
||||||
{id: currentUser.id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
await UsersDBApi.update(
|
|
||||||
currentUser.id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Auth;
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const BenefitsDBApi = require('../db/api/benefits');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class BenefitsService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await BenefitsDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await BenefitsDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let benefits = await BenefitsDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!benefits) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'benefitsNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedBenefits = await BenefitsDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedBenefits;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await BenefitsDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await BenefitsDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
.email-container {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: auto;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.email-header {
|
|
||||||
background-color: #3498db;
|
|
||||||
color: #fff;
|
|
||||||
padding: 16px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.email-body {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
.email-footer {
|
|
||||||
padding: 16px;
|
|
||||||
background-color: #f7fafc;
|
|
||||||
text-align: center;
|
|
||||||
color: #4a5568;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.link-primary {
|
|
||||||
color: #3498db;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="email-container">
|
|
||||||
<div class="email-header">
|
|
||||||
Verify your email for {appTitle}!
|
|
||||||
</div>
|
|
||||||
<div class="email-body">
|
|
||||||
<p>Hello,</p>
|
|
||||||
<p>Follow this link to verify your email address.</p>
|
|
||||||
<p>If you didn't ask to verify this address, you can ignore this email.</p>
|
|
||||||
<p><a href="{signupUrl}" class="link-primary">{signupUrl}</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="email-footer">
|
|
||||||
Thanks,<br/>
|
|
||||||
The {appTitle} Team
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
.email-container {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: auto;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.email-header {
|
|
||||||
background-color: #3498db;
|
|
||||||
color: #fff;
|
|
||||||
padding: 16px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.email-body {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
.email-footer {
|
|
||||||
padding: 16px;
|
|
||||||
background-color: #f7fafc;
|
|
||||||
text-align: center;
|
|
||||||
color: #4a5568;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.btn-primary {
|
|
||||||
background-color: #3498db;
|
|
||||||
color: #fff!important;
|
|
||||||
padding: 8px 16px;
|
|
||||||
border-radius: 4px;
|
|
||||||
text-decoration: none;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="email-container">
|
|
||||||
<div class="email-header">
|
|
||||||
Welcome to {appTitle}!
|
|
||||||
</div>
|
|
||||||
<div class="email-body">
|
|
||||||
<p>Hello,</p>
|
|
||||||
<p>You've been invited to join {appTitle}. Please click the button below to set up your account.</p>
|
|
||||||
<a href="{signupUrl}" class="btn-primary">Set up account</a>
|
|
||||||
</div>
|
|
||||||
<div class="email-footer">
|
|
||||||
Thanks,<br/>
|
|
||||||
The {appTitle} Team
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
.email-container {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: auto;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.email-header {
|
|
||||||
background-color: #3498db;
|
|
||||||
color: #fff;
|
|
||||||
padding: 16px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.email-body {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
.email-footer {
|
|
||||||
padding: 16px;
|
|
||||||
background-color: #f7fafc;
|
|
||||||
text-align: center;
|
|
||||||
color: #4a5568;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.link-primary {
|
|
||||||
color: #3498db;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="email-container">
|
|
||||||
<div class="email-header">
|
|
||||||
Reset your password for {appTitle}
|
|
||||||
</div>
|
|
||||||
<div class="email-body">
|
|
||||||
<p>Hello,</p>
|
|
||||||
<p>Follow this link to reset your {appTitle} password for your {accountName} account.</p>
|
|
||||||
<p><a href="{resetUrl}" class="link-primary">{resetUrl}</a></p>
|
|
||||||
<p>If you didn't ask to reset your password, you can ignore this email.</p>
|
|
||||||
</div>
|
|
||||||
<div class="email-footer">
|
|
||||||
Thanks,<br/>
|
|
||||||
The {appTitle} Team
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
const config = require('../../config');
|
|
||||||
const assert = require('assert');
|
|
||||||
const nodemailer = require('nodemailer');
|
|
||||||
|
|
||||||
module.exports = class EmailSender {
|
|
||||||
constructor(email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
async send() {
|
|
||||||
assert(this.email, 'email is required');
|
|
||||||
assert(this.email.to, 'email.to is required');
|
|
||||||
assert(this.email.subject, 'email.subject is required');
|
|
||||||
assert(this.email.html, 'email.html is required');
|
|
||||||
|
|
||||||
const htmlContent = await this.email.html();
|
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport(this.transportConfig);
|
|
||||||
|
|
||||||
const mailOptions = {
|
|
||||||
from: this.from,
|
|
||||||
to: this.email.to,
|
|
||||||
subject: this.email.subject,
|
|
||||||
html: htmlContent,
|
|
||||||
headers: {
|
|
||||||
'X-SES-CONFIGURATION-SET': 'flatlogic-app',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return transporter.sendMail(mailOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
static get isConfigured() {
|
|
||||||
return !!config.email?.auth?.pass && !!config.email?.auth?.user;
|
|
||||||
}
|
|
||||||
|
|
||||||
get transportConfig() {
|
|
||||||
return config.email;
|
|
||||||
}
|
|
||||||
|
|
||||||
get from() {
|
|
||||||
return config.email.from;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
const { getNotification } = require('../../notifications/helpers');
|
|
||||||
const fs = require('fs').promises;
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
module.exports = class EmailAddressVerificationEmail {
|
|
||||||
constructor(to, link) {
|
|
||||||
this.to = to;
|
|
||||||
this.link = link;
|
|
||||||
}
|
|
||||||
|
|
||||||
get subject() {
|
|
||||||
return getNotification(
|
|
||||||
'emails.emailAddressVerification.subject',
|
|
||||||
getNotification('app.title'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async html() {
|
|
||||||
try {
|
|
||||||
const templatePath = path.join(__dirname, '../../email/htmlTemplates/addressVerification/emailAddressVerification.html');
|
|
||||||
|
|
||||||
const template = await fs.readFile(templatePath, 'utf8');
|
|
||||||
|
|
||||||
const appTitle = getNotification('app.title');
|
|
||||||
const signupUrl = this.link;
|
|
||||||
|
|
||||||
let html = template.replace(/{appTitle}/g, appTitle)
|
|
||||||
.replace(/{signupUrl}/g, signupUrl)
|
|
||||||
.replace(/{to}/g, this.to);
|
|
||||||
|
|
||||||
return html;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error generating invitation email HTML:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
const fs = require('fs').promises;
|
|
||||||
const path = require('path');
|
|
||||||
const { getNotification } = require('../../notifications/helpers');
|
|
||||||
|
|
||||||
module.exports = class InvitationEmail {
|
|
||||||
constructor(to, host) {
|
|
||||||
this.to = to;
|
|
||||||
this.host = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
get subject() {
|
|
||||||
return getNotification(
|
|
||||||
'emails.invitation.subject',
|
|
||||||
getNotification('app.title'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async html() {
|
|
||||||
try {
|
|
||||||
const templatePath = path.join(__dirname, '../../email/htmlTemplates/invitation/invitationTemplate.html');
|
|
||||||
|
|
||||||
const template = await fs.readFile(templatePath, 'utf8');
|
|
||||||
|
|
||||||
const appTitle = getNotification('app.title');
|
|
||||||
const signupUrl = `${this.host}&invitation=true`;
|
|
||||||
|
|
||||||
let html = template.replace(/{appTitle}/g, appTitle)
|
|
||||||
.replace(/{signupUrl}/g, signupUrl)
|
|
||||||
.replace(/{to}/g, this.to);
|
|
||||||
|
|
||||||
return html;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error generating invitation email HTML:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
const { getNotification } = require('../../notifications/helpers');
|
|
||||||
const path = require("path");
|
|
||||||
const {promises: fs} = require("fs");
|
|
||||||
|
|
||||||
module.exports = class PasswordResetEmail {
|
|
||||||
constructor(to, link) {
|
|
||||||
this.to = to;
|
|
||||||
this.link = link;
|
|
||||||
}
|
|
||||||
|
|
||||||
get subject() {
|
|
||||||
return getNotification(
|
|
||||||
'emails.passwordReset.subject',
|
|
||||||
getNotification('app.title'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async html() {
|
|
||||||
try {
|
|
||||||
const templatePath = path.join(__dirname, '../../email/htmlTemplates/passwordReset/passwordResetEmail.html');
|
|
||||||
|
|
||||||
const template = await fs.readFile(templatePath, 'utf8');
|
|
||||||
|
|
||||||
const appTitle = getNotification('app.title');
|
|
||||||
const resetUrl = this.link;
|
|
||||||
const accountName = this.to;
|
|
||||||
|
|
||||||
let html = template.replace(/{appTitle}/g, appTitle)
|
|
||||||
.replace(/{resetUrl}/g, resetUrl)
|
|
||||||
.replace(/{accountName}/g, accountName);
|
|
||||||
|
|
||||||
return html;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error generating invitation email HTML:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,213 +0,0 @@
|
|||||||
const formidable = require('formidable');
|
|
||||||
const fs = require('fs');
|
|
||||||
const config = require('../config');
|
|
||||||
const path = require('path');
|
|
||||||
const { format } = require("util");
|
|
||||||
|
|
||||||
const ensureDirectoryExistence = (filePath) => {
|
|
||||||
const dirname = path.dirname(filePath);
|
|
||||||
|
|
||||||
if (fs.existsSync(dirname)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureDirectoryExistence(dirname);
|
|
||||||
fs.mkdirSync(dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uploadLocal = (
|
|
||||||
folder,
|
|
||||||
validations = {
|
|
||||||
entity: null,
|
|
||||||
maxFileSize: null,
|
|
||||||
folderIncludesAuthenticationUid: false,
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
return (req, res) => {
|
|
||||||
if (!req.currentUser) {
|
|
||||||
res.sendStatus(403);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
validations.entity
|
|
||||||
) {
|
|
||||||
res.sendStatus(403);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validations.folderIncludesAuthenticationUid) {
|
|
||||||
folder = folder.replace(
|
|
||||||
':userId',
|
|
||||||
req.currentUser.authenticationUid,
|
|
||||||
);
|
|
||||||
if (
|
|
||||||
!req.currentUser.authenticationUid ||
|
|
||||||
!folder.includes(req.currentUser.authenticationUid)
|
|
||||||
) {
|
|
||||||
res.sendStatus(403);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const form = new formidable.IncomingForm();
|
|
||||||
form.uploadDir = config.uploadDir;
|
|
||||||
|
|
||||||
if (validations && validations.maxFileSize) {
|
|
||||||
form.maxFileSize = validations.maxFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
form.parse(req, function (err, fields, files) {
|
|
||||||
const filename = String(fields.filename);
|
|
||||||
const fileTempUrl = files.file.path;
|
|
||||||
|
|
||||||
if (!filename) {
|
|
||||||
fs.unlinkSync(fileTempUrl);
|
|
||||||
res.sendStatus(500);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const privateUrl = path.join(
|
|
||||||
form.uploadDir,
|
|
||||||
folder,
|
|
||||||
filename,
|
|
||||||
);
|
|
||||||
ensureDirectoryExistence(privateUrl);
|
|
||||||
fs.renameSync(fileTempUrl, privateUrl);
|
|
||||||
res.sendStatus(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
form.on('error', function (err) {
|
|
||||||
res.status(500).send(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const downloadLocal = async (req, res) => {
|
|
||||||
const privateUrl = req.query.privateUrl;
|
|
||||||
if (!privateUrl) {
|
|
||||||
return res.sendStatus(404);
|
|
||||||
}
|
|
||||||
res.download(path.join(config.uploadDir, privateUrl));
|
|
||||||
}
|
|
||||||
|
|
||||||
const initGCloud = () => {
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const { Storage } = require("@google-cloud/storage");
|
|
||||||
|
|
||||||
const crypto = require('crypto')
|
|
||||||
const hash = config.gcloud.hash
|
|
||||||
|
|
||||||
const privateKey = process.env.GC_PRIVATE_KEY.replace(/\\\n/g, "\n");
|
|
||||||
|
|
||||||
const storage = new Storage({
|
|
||||||
projectId: process.env.GC_PROJECT_ID,
|
|
||||||
credentials: {
|
|
||||||
client_email: process.env.GC_CLIENT_EMAIL,
|
|
||||||
private_key: privateKey
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const bucket = storage.bucket(config.gcloud.bucket);
|
|
||||||
return {hash, bucket, processFile};
|
|
||||||
}
|
|
||||||
|
|
||||||
const uploadGCloud = async (folder, req, res) => {
|
|
||||||
try {
|
|
||||||
const {hash, bucket, processFile} = initGCloud();
|
|
||||||
await processFile(req, res);
|
|
||||||
let buffer = await req.file.buffer;
|
|
||||||
let filename = await req.body.filename;
|
|
||||||
|
|
||||||
if (!req.file) {
|
|
||||||
return res.status(400).send({ message: "Please upload a file!" });
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = `${hash}/${folder}/${filename}`;
|
|
||||||
let blob = bucket.file(path);
|
|
||||||
|
|
||||||
console.log(path);
|
|
||||||
|
|
||||||
const blobStream = blob.createWriteStream({
|
|
||||||
resumable: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
blobStream.on("error", (err) => {
|
|
||||||
console.log('Upload error');
|
|
||||||
console.log(err.message);
|
|
||||||
res.status(500).send({ message: err.message });
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`https://storage.googleapis.com/${bucket.name}/${blob.name}`);
|
|
||||||
|
|
||||||
blobStream.on("finish", async (data) => {
|
|
||||||
const publicUrl = format(
|
|
||||||
`https://storage.googleapis.com/${bucket.name}/${blob.name}`
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send({
|
|
||||||
message: "Uploaded the file successfully: " + path,
|
|
||||||
url: publicUrl,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
blobStream.end(buffer)
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
|
|
||||||
res.status(500).send({
|
|
||||||
message: `Could not upload the file. ${err}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const downloadGCloud = async (req, res) => {
|
|
||||||
try {
|
|
||||||
const {hash, bucket, processFile} = initGCloud();
|
|
||||||
|
|
||||||
const privateUrl = await req.query.privateUrl;
|
|
||||||
const filePath = `${hash}/${privateUrl}`;
|
|
||||||
const file = bucket.file(filePath)
|
|
||||||
const fileExists = await file.exists();
|
|
||||||
|
|
||||||
if (fileExists[0]) {
|
|
||||||
const stream = file.createReadStream();
|
|
||||||
stream.pipe(res);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res.status(404).send({
|
|
||||||
message: "Could not download the file. " + err,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
res.status(404).send({
|
|
||||||
message: "Could not download the file. " + err,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteGCloud = async (privateUrl) => {
|
|
||||||
try {
|
|
||||||
const {hash, bucket, processFile} = initGCloud();
|
|
||||||
const filePath = `${hash}/${privateUrl}`;
|
|
||||||
|
|
||||||
const file = bucket.file(filePath)
|
|
||||||
const fileExists = await file.exists();
|
|
||||||
|
|
||||||
if (fileExists[0]) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(`Cannot find the file ${privateUrl}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
initGCloud,
|
|
||||||
uploadLocal,
|
|
||||||
downloadLocal,
|
|
||||||
deleteGCloud,
|
|
||||||
uploadGCloud,
|
|
||||||
downloadGCloud
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const InquiriesDBApi = require('../db/api/inquiries');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class InquiriesService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await InquiriesDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await InquiriesDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let inquiries = await InquiriesDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!inquiries) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'inquiriesNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedInquiries = await InquiriesDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedInquiries;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await InquiriesDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await InquiriesDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
const { getNotification, isNotification } = require('../helpers');
|
|
||||||
|
|
||||||
module.exports = class ForbiddenError extends Error {
|
|
||||||
constructor(messageCode) {
|
|
||||||
let message;
|
|
||||||
|
|
||||||
if (messageCode && isNotification(messageCode)) {
|
|
||||||
message = getNotification(messageCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
message =
|
|
||||||
message || getNotification('errors.forbidden.message');
|
|
||||||
|
|
||||||
super(message);
|
|
||||||
this.code = 403;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
const { getNotification, isNotification } = require('../helpers');
|
|
||||||
|
|
||||||
module.exports = class ValidationError extends Error {
|
|
||||||
constructor(messageCode) {
|
|
||||||
let message;
|
|
||||||
|
|
||||||
if (messageCode && isNotification(messageCode)) {
|
|
||||||
message = getNotification(messageCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
message =
|
|
||||||
message ||
|
|
||||||
getNotification('errors.validation.message');
|
|
||||||
|
|
||||||
super(message);
|
|
||||||
this.code = 400;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
const _get = require('lodash/get');
|
|
||||||
const errors = require('./list');
|
|
||||||
|
|
||||||
function format(message, args) {
|
|
||||||
if (!message) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return message.replace(/{(\d+)}/g, function (
|
|
||||||
match,
|
|
||||||
number,
|
|
||||||
) {
|
|
||||||
return typeof args[number] != 'undefined'
|
|
||||||
? args[number]
|
|
||||||
: match;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const isNotification = (key) => {
|
|
||||||
const message = _get(errors, key);
|
|
||||||
return !!message;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNotification = (key, ...args) => {
|
|
||||||
const message = _get(errors, key);
|
|
||||||
|
|
||||||
if (!message) {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return format(message, args);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getNotification = getNotification;
|
|
||||||
exports.isNotification = isNotification;
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
const errors = {
|
|
||||||
app: {
|
|
||||||
title: 'Blackness Studio Website',
|
|
||||||
},
|
|
||||||
|
|
||||||
auth: {
|
|
||||||
userDisabled: 'Your account is disabled',
|
|
||||||
forbidden: 'Forbidden',
|
|
||||||
unauthorized: 'Unauthorized',
|
|
||||||
userNotFound: `Sorry, we don't recognize your credentials`,
|
|
||||||
wrongPassword: `Sorry, we don't recognize your credentials`,
|
|
||||||
weakPassword: 'This password is too weak',
|
|
||||||
emailAlreadyInUse: 'Email is already in use',
|
|
||||||
invalidEmail: 'Please provide a valid email',
|
|
||||||
passwordReset: {
|
|
||||||
invalidToken:
|
|
||||||
'Password reset link is invalid or has expired',
|
|
||||||
error: `Email not recognized`,
|
|
||||||
},
|
|
||||||
passwordUpdate: {
|
|
||||||
samePassword: `You can't use the same password. Please create new password`
|
|
||||||
},
|
|
||||||
userNotVerified: `Sorry, your email has not been verified yet`,
|
|
||||||
emailAddressVerificationEmail: {
|
|
||||||
invalidToken:
|
|
||||||
'Email verification link is invalid or has expired',
|
|
||||||
error: `Email not recognized`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
iam: {
|
|
||||||
errors: {
|
|
||||||
userAlreadyExists:
|
|
||||||
'User with this email already exists',
|
|
||||||
userNotFound: 'User not found',
|
|
||||||
disablingHimself: `You can't disable yourself`,
|
|
||||||
revokingOwnPermission: `You can't revoke your own owner permission`,
|
|
||||||
deletingHimself: `You can't delete yourself`,
|
|
||||||
emailRequired: 'Email is required',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
importer: {
|
|
||||||
errors: {
|
|
||||||
invalidFileEmpty: 'The file is empty',
|
|
||||||
invalidFileExcel:
|
|
||||||
'Only excel (.xlsx) files are allowed',
|
|
||||||
invalidFileUpload:
|
|
||||||
'Invalid file. Make sure you are using the last version of the template.',
|
|
||||||
importHashRequired: 'Import hash is required',
|
|
||||||
importHashExistent: 'Data has already been imported',
|
|
||||||
userEmailMissing: 'Some items in the CSV do not have an email',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
errors: {
|
|
||||||
forbidden: {
|
|
||||||
message: 'Forbidden',
|
|
||||||
},
|
|
||||||
validation: {
|
|
||||||
message: 'An error occurred',
|
|
||||||
},
|
|
||||||
searchQueryRequired: {
|
|
||||||
message: 'Search query is required',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emails: {
|
|
||||||
invitation: {
|
|
||||||
subject: `You've been invited to {0}`,
|
|
||||||
body: `
|
|
||||||
<p>Hello,</p>
|
|
||||||
<p>You've been invited to {0} set password for your {1} account.</p>
|
|
||||||
<p><a href='{2}'>{2}</a></p>
|
|
||||||
<p>Thanks,</p>
|
|
||||||
<p>Your {0} team</p>
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
emailAddressVerification: {
|
|
||||||
subject: `Verify your email for {0}`,
|
|
||||||
body: `
|
|
||||||
<p>Hello,</p>
|
|
||||||
<p>Follow this link to verify your email address.</p>
|
|
||||||
<p><a href='{0}'>{0}</a></p>
|
|
||||||
<p>If you didn't ask to verify this address, you can ignore this email.</p>
|
|
||||||
<p>Thanks,</p>
|
|
||||||
<p>Your {1} team</p>
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
passwordReset: {
|
|
||||||
subject: `Reset your password for {0}`,
|
|
||||||
body: `
|
|
||||||
<p>Hello,</p>
|
|
||||||
<p>Follow this link to reset your {0} password for your {1} account.</p>
|
|
||||||
<p><a href='{2}'>{2}</a></p>
|
|
||||||
<p>If you didn't ask to reset your password, you can ignore this email.</p>
|
|
||||||
<p>Thanks,</p>
|
|
||||||
<p>Your {0} team</p>
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = errors;
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const { LocalAIApi } = require('../ai/LocalAIApi');
|
|
||||||
|
|
||||||
const loadRoleService = () => {
|
|
||||||
try {
|
|
||||||
return require('./roles');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Role service is missing. Advanced roles are required for this operation.', error);
|
|
||||||
const err = new Error('Role service is missing. Advanced roles are required for this operation.');
|
|
||||||
err.originalError = error;
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = class OpenAiService {
|
|
||||||
static async getWidget(payload, userId, roleId) {
|
|
||||||
const RoleService = loadRoleService();
|
|
||||||
const response = await axios.post(
|
|
||||||
`${config.flHost}/${config.project_uuid}/project_customization_widgets.json`,
|
|
||||||
payload,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.status >= 200 && response.status < 300) {
|
|
||||||
const { widget_id } = await response.data;
|
|
||||||
await RoleService.addRoleInfo(roleId, userId, 'widgets', widget_id);
|
|
||||||
return widget_id;
|
|
||||||
} else {
|
|
||||||
console.error('=======error=======', response.data);
|
|
||||||
return { value: null, error: response.data };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async askGpt(prompt) {
|
|
||||||
if (!prompt) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: 'Prompt is required'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await LocalAIApi.createResponse(
|
|
||||||
{
|
|
||||||
input: [{ role: 'user', content: prompt }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
poll_interval: 5,
|
|
||||||
poll_timeout: 300,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.success) {
|
|
||||||
let text = LocalAIApi.extractText(response);
|
|
||||||
if (!text) {
|
|
||||||
try {
|
|
||||||
const decoded = LocalAIApi.decodeJsonFromResponse(response);
|
|
||||||
text = JSON.stringify(decoded);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('AI JSON decode failed:', error);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: 'AI response parsing failed',
|
|
||||||
details: error.message || String(error),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: text,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error('AI proxy error:', response);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: response.error || response.message || 'AI proxy error',
|
|
||||||
response,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const Page_sectionsDBApi = require('../db/api/page_sections');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class Page_sectionsService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await Page_sectionsDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await Page_sectionsDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let page_sections = await Page_sectionsDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!page_sections) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'page_sectionsNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedPage_sections = await Page_sectionsDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedPage_sections;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Page_sectionsDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Page_sectionsDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const PagesDBApi = require('../db/api/pages');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class PagesService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await PagesDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await PagesDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let pages = await PagesDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!pages) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'pagesNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedPages = await PagesDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedPages;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await PagesDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await PagesDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const PermissionsDBApi = require('../db/api/permissions');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class PermissionsService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await PermissionsDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await PermissionsDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let permissions = await PermissionsDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!permissions) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'permissionsNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedPermissions = await PermissionsDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedPermissions;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await PermissionsDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await PermissionsDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const Portfolio_itemsDBApi = require('../db/api/portfolio_items');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class Portfolio_itemsService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await Portfolio_itemsDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await Portfolio_itemsDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let portfolio_items = await Portfolio_itemsDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!portfolio_items) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'portfolio_itemsNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedPortfolio_items = await Portfolio_itemsDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedPortfolio_items;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Portfolio_itemsDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Portfolio_itemsDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,437 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const RolesDBApi = require('../db/api/roles');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function buildWidgetResult(widget, queryResult, queryString) {
|
|
||||||
if (queryResult[0] && queryResult[0].length) {
|
|
||||||
const key = Object.keys(queryResult[0][0])[0];
|
|
||||||
const value = widget.widget_type === 'scalar' ? queryResult[0][0][key] : queryResult[0];
|
|
||||||
const widgetData = JSON.parse(widget.data);
|
|
||||||
return { ...widget, ...widgetData, value, query: queryString };
|
|
||||||
} else {
|
|
||||||
return { ...widget, value: [], query: queryString };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function executeQuery(queryString, currentUser) {
|
|
||||||
try {
|
|
||||||
return await db.sequelize.query(queryString, {
|
|
||||||
replacements: { organizationId: currentUser.organizationId },
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function insertWhereConditions(queryString, whereConditions) {
|
|
||||||
if (!whereConditions) return queryString;
|
|
||||||
|
|
||||||
const whereIndex = queryString.toLowerCase().indexOf('where');
|
|
||||||
const groupByIndex = queryString.toLowerCase().indexOf('group by');
|
|
||||||
const insertIndex = whereIndex === -1
|
|
||||||
? (groupByIndex !== -1 ? groupByIndex : queryString.length)
|
|
||||||
: whereIndex + 5;
|
|
||||||
|
|
||||||
const prefix = queryString.substring(0, insertIndex);
|
|
||||||
const suffix = queryString.substring(insertIndex);
|
|
||||||
const conditionString = whereIndex === -1 ? ` WHERE ${whereConditions} ` : ` ${whereConditions} AND `;
|
|
||||||
|
|
||||||
return `${prefix}${conditionString}${suffix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function constructWhereConditions(mainTable, currentUser, replacements) {
|
|
||||||
const { organizationId, app_role: { globalAccess } } = currentUser;
|
|
||||||
const tablesWithoutOrgId = ['permissions', 'roles'];
|
|
||||||
let whereConditions = '';
|
|
||||||
|
|
||||||
if (!globalAccess && !tablesWithoutOrgId.includes(mainTable)) {
|
|
||||||
whereConditions += `"${mainTable}"."organizationId" = :organizationId`;
|
|
||||||
replacements.organizationId = organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
whereConditions += whereConditions ? ' AND ' : '';
|
|
||||||
whereConditions += `"${mainTable}"."deletedAt" IS NULL`;
|
|
||||||
|
|
||||||
return whereConditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractTableName(queryString) {
|
|
||||||
const tableNameRegex = /FROM\s+("?)([^"\s]+)\1\s*/i;
|
|
||||||
const match = tableNameRegex.exec(queryString);
|
|
||||||
return match ? match[2] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildQueryString(widget, currentUser) {
|
|
||||||
let queryString = widget?.query || '';
|
|
||||||
const tableName = extractTableName(queryString);
|
|
||||||
const mainTable = JSON.parse(widget?.data)?.main_table || tableName;
|
|
||||||
const replacements = {};
|
|
||||||
const whereConditions = constructWhereConditions(mainTable, currentUser, replacements);
|
|
||||||
queryString = insertWhereConditions(queryString, whereConditions);
|
|
||||||
console.log(queryString, 'queryString');
|
|
||||||
return queryString;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function constructWidgetsResults(widgets, currentUser) {
|
|
||||||
const widgetsResults = [];
|
|
||||||
for (const widget of widgets) {
|
|
||||||
if (!widget) continue;
|
|
||||||
const queryString = buildQueryString(widget, currentUser);
|
|
||||||
const queryResult = await executeQuery(queryString, currentUser);
|
|
||||||
widgetsResults.push(buildWidgetResult(widget, queryResult, queryString));
|
|
||||||
}
|
|
||||||
return widgetsResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchWidgetsData(widgets) {
|
|
||||||
const widgetPromises = (widgets || []).map(widgetId =>
|
|
||||||
axios.get(`${config.flHost}/${config.project_uuid}/project_customization_widgets/${widgetId}.json`)
|
|
||||||
);
|
|
||||||
const widgetResults = widgetPromises ? await Promise.allSettled(widgetPromises) : [];
|
|
||||||
return widgetResults
|
|
||||||
.filter(result => result.status === 'fulfilled')
|
|
||||||
.map(result => result.value.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function processWidgets(widgets, currentUser) {
|
|
||||||
const widgetData = await fetchWidgetsData(widgets);
|
|
||||||
return constructWidgetsResults(widgetData, currentUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseCustomization(role) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(role.role_customization || '{}');
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findRole(roleId, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
const role = roleId
|
|
||||||
? await RolesDBApi.findBy({ id: roleId }, { transaction })
|
|
||||||
: await RolesDBApi.findBy({ name: 'User' }, { transaction });
|
|
||||||
await transaction.commit();
|
|
||||||
return role;
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class RolesService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await RolesDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await RolesDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let roles = await RolesDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!roles) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'rolesNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedRoles = await RolesDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedRoles;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await RolesDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await RolesDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async addRoleInfo(roleId, userId, key, widgetId, currentUser) {
|
|
||||||
const regexExpForUuid = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi;
|
|
||||||
const widgetIdIsUUID = regexExpForUuid.test(widgetId);
|
|
||||||
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
let role;
|
|
||||||
if (roleId) {
|
|
||||||
role = await RolesDBApi.findBy({ id: roleId }, { transaction });
|
|
||||||
} else {
|
|
||||||
role = await RolesDBApi.findBy({ name: 'User' }, { transaction });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!role) {
|
|
||||||
throw new ValidationError('rolesNotFound');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
let customization = {};
|
|
||||||
try {
|
|
||||||
customization = JSON.parse(role.role_customization || '{}');
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (widgetIdIsUUID && Array.isArray(customization[key])) {
|
|
||||||
const el = customization[key].find((e) => e === widgetId);
|
|
||||||
!el ? customization[key].unshift(widgetId) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (widgetIdIsUUID && !customization[key]) {
|
|
||||||
customization[key] = [widgetId];
|
|
||||||
}
|
|
||||||
|
|
||||||
const newRole = await RolesDBApi.update(
|
|
||||||
role.id,
|
|
||||||
{
|
|
||||||
role_customization: JSON.stringify(customization),
|
|
||||||
name: role.name,
|
|
||||||
permissions: role.permissions,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
|
|
||||||
return newRole;
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async removeRoleInfoById(infoId, roleId, key, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
let role;
|
|
||||||
if (roleId) {
|
|
||||||
role = await RolesDBApi.findBy({ id: roleId }, { transaction });
|
|
||||||
} else {
|
|
||||||
role = await RolesDBApi.findBy({ name: 'User' }, { transaction });
|
|
||||||
}
|
|
||||||
if (!role) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw new ValidationError('rolesNotFound');
|
|
||||||
}
|
|
||||||
|
|
||||||
let customization = {};
|
|
||||||
try {
|
|
||||||
customization = JSON.parse(role.role_customization || '{}');
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
customization[key] = customization[key].filter(
|
|
||||||
(item) => item !== infoId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const response = await axios.delete(`${config.flHost}/${config.project_uuid}/project_customization_widgets/${infoId}.json`);
|
|
||||||
const { status } = await response;
|
|
||||||
try {
|
|
||||||
const result = await RolesDBApi.update(
|
|
||||||
role.id,
|
|
||||||
{
|
|
||||||
role_customization: JSON.stringify(customization),
|
|
||||||
name: role.name,
|
|
||||||
permissions: role.permissions,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getRoleInfoByKey(key, roleId, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
const organizationId = currentUser.organizationId;
|
|
||||||
let globalAccess = currentUser.app_role?.globalAccess;
|
|
||||||
let queryString = '';
|
|
||||||
|
|
||||||
|
|
||||||
let role;
|
|
||||||
try {
|
|
||||||
if (roleId) {
|
|
||||||
role = await RolesDBApi.findBy({ id: roleId }, { transaction });
|
|
||||||
} else {
|
|
||||||
role = await RolesDBApi.findBy({ name: 'User' }, { transaction });
|
|
||||||
}
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
let customization = '{}';
|
|
||||||
|
|
||||||
try {
|
|
||||||
customization = JSON.parse(role.role_customization || '{}');
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === 'widgets') {
|
|
||||||
const widgets = (customization[key] || []);
|
|
||||||
const widgetArray = widgets.map(widget => {
|
|
||||||
return axios.get(`${config.flHost}/${config.project_uuid}/project_customization_widgets/${widget}.json`)
|
|
||||||
})
|
|
||||||
const widgetResults = await Promise.allSettled(widgetArray);
|
|
||||||
|
|
||||||
const fulfilledWidgets = widgetResults.map(result => {
|
|
||||||
if (result.status === 'fulfilled') {
|
|
||||||
return result.value.data;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const widgetsResults = [];
|
|
||||||
|
|
||||||
if (Array.isArray(fulfilledWidgets)) {
|
|
||||||
for (const widget of fulfilledWidgets) {
|
|
||||||
let result = [];
|
|
||||||
try {
|
|
||||||
result = await db.sequelize.query(widget.query);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result[0] && result[0].length) {
|
|
||||||
const key = Object.keys(result[0][0])[0];
|
|
||||||
const value =
|
|
||||||
widget.widget_type === 'scalar' ? result[0][0][key] : result[0];
|
|
||||||
const widgetData = JSON.parse(widget.data);
|
|
||||||
widgetsResults.push({ ...widget, ...widgetData, value });
|
|
||||||
} else {
|
|
||||||
widgetsResults.push({ ...widget, value: null });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return widgetsResults;
|
|
||||||
}
|
|
||||||
return customization[key];
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,424 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} permission
|
|
||||||
* @param {object} currentUser
|
|
||||||
*/
|
|
||||||
async function checkPermissions(permission, currentUser) {
|
|
||||||
|
|
||||||
if (!currentUser) {
|
|
||||||
throw new ValidationError('auth.unauthorized');
|
|
||||||
}
|
|
||||||
|
|
||||||
const userPermission = currentUser.custom_permissions.find(
|
|
||||||
(cp) => cp.name === permission,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (userPermission) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!currentUser.app_role) {
|
|
||||||
throw new ValidationError('auth.forbidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
const permissions = await currentUser.app_role.getPermissions();
|
|
||||||
|
|
||||||
return !!permissions.find((p) => p.name === permission);
|
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = class SearchService {
|
|
||||||
static async search(searchQuery, currentUser ) {
|
|
||||||
try {
|
|
||||||
if (!searchQuery) {
|
|
||||||
throw new ValidationError('iam.errors.searchQueryRequired');
|
|
||||||
}
|
|
||||||
const tableColumns = {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"users": [
|
|
||||||
|
|
||||||
"firstName",
|
|
||||||
|
|
||||||
"lastName",
|
|
||||||
|
|
||||||
"phoneNumber",
|
|
||||||
|
|
||||||
"email",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"site_settings": [
|
|
||||||
|
|
||||||
"site_name",
|
|
||||||
|
|
||||||
"tagline",
|
|
||||||
|
|
||||||
"primary_domain",
|
|
||||||
|
|
||||||
"primary_cta_label",
|
|
||||||
|
|
||||||
"primary_cta_url",
|
|
||||||
|
|
||||||
"contact_email",
|
|
||||||
|
|
||||||
"contact_phone",
|
|
||||||
|
|
||||||
"location",
|
|
||||||
|
|
||||||
"accent_color_hex",
|
|
||||||
|
|
||||||
"seo_title",
|
|
||||||
|
|
||||||
"seo_description",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"pages": [
|
|
||||||
|
|
||||||
"title",
|
|
||||||
|
|
||||||
"slug",
|
|
||||||
|
|
||||||
"meta_title",
|
|
||||||
|
|
||||||
"meta_description",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"page_sections": [
|
|
||||||
|
|
||||||
"section_label",
|
|
||||||
|
|
||||||
"headline",
|
|
||||||
|
|
||||||
"subheadline",
|
|
||||||
|
|
||||||
"body",
|
|
||||||
|
|
||||||
"primary_button_label",
|
|
||||||
|
|
||||||
"primary_button_url",
|
|
||||||
|
|
||||||
"secondary_button_label",
|
|
||||||
|
|
||||||
"secondary_button_url",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"services": [
|
|
||||||
|
|
||||||
"name",
|
|
||||||
|
|
||||||
"short_description",
|
|
||||||
|
|
||||||
"details",
|
|
||||||
|
|
||||||
"cta_label",
|
|
||||||
|
|
||||||
"cta_url",
|
|
||||||
|
|
||||||
"icon_name",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"portfolio_items": [
|
|
||||||
|
|
||||||
"title",
|
|
||||||
|
|
||||||
"client_name",
|
|
||||||
|
|
||||||
"summary",
|
|
||||||
|
|
||||||
"case_study",
|
|
||||||
|
|
||||||
"external_url",
|
|
||||||
|
|
||||||
"tech_stack",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"testimonials": [
|
|
||||||
|
|
||||||
"client_name",
|
|
||||||
|
|
||||||
"client_title",
|
|
||||||
|
|
||||||
"company_name",
|
|
||||||
|
|
||||||
"quote",
|
|
||||||
|
|
||||||
"source",
|
|
||||||
|
|
||||||
"source_url",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"skills": [
|
|
||||||
|
|
||||||
"name",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"benefits": [
|
|
||||||
|
|
||||||
"title",
|
|
||||||
|
|
||||||
"description",
|
|
||||||
|
|
||||||
"icon_name",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"social_links": [
|
|
||||||
|
|
||||||
"label",
|
|
||||||
|
|
||||||
"url",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"inquiries": [
|
|
||||||
|
|
||||||
"full_name",
|
|
||||||
|
|
||||||
"email",
|
|
||||||
|
|
||||||
"company_name",
|
|
||||||
|
|
||||||
"subject",
|
|
||||||
|
|
||||||
"message",
|
|
||||||
|
|
||||||
"source_page",
|
|
||||||
|
|
||||||
"fiverr_url",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
const columnsInt = {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"pages": [
|
|
||||||
|
|
||||||
"sort_order",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"page_sections": [
|
|
||||||
|
|
||||||
"sort_order",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"services": [
|
|
||||||
|
|
||||||
"sort_order",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"testimonials": [
|
|
||||||
|
|
||||||
"rating",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"skills": [
|
|
||||||
|
|
||||||
"proficiency_level",
|
|
||||||
|
|
||||||
"sort_order",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"benefits": [
|
|
||||||
|
|
||||||
"sort_order",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"social_links": [
|
|
||||||
|
|
||||||
"sort_order",
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
let allFoundRecords = [];
|
|
||||||
|
|
||||||
for (const tableName in tableColumns) {
|
|
||||||
if (tableColumns.hasOwnProperty(tableName)) {
|
|
||||||
const attributesToSearch = tableColumns[tableName];
|
|
||||||
const attributesIntToSearch = columnsInt[tableName] || [];
|
|
||||||
const whereCondition = {
|
|
||||||
[Op.or]: [
|
|
||||||
...attributesToSearch.map(attribute => ({
|
|
||||||
[attribute]: {
|
|
||||||
[Op.iLike] : `%${searchQuery}%`,
|
|
||||||
},
|
|
||||||
})),
|
|
||||||
...attributesIntToSearch.map(attribute => (
|
|
||||||
Sequelize.where(
|
|
||||||
Sequelize.cast(Sequelize.col(`${tableName}.${attribute}`), 'varchar'),
|
|
||||||
{ [Op.iLike]: `%${searchQuery}%` }
|
|
||||||
)
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const hasPermission = await checkPermissions(`READ_${tableName.toUpperCase()}`, currentUser);
|
|
||||||
if (!hasPermission) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const foundRecords = await db[tableName].findAll({
|
|
||||||
where: whereCondition,
|
|
||||||
attributes: [...tableColumns[tableName], 'id', ...attributesIntToSearch],
|
|
||||||
});
|
|
||||||
|
|
||||||
const modifiedRecords = foundRecords.map((record) => {
|
|
||||||
const matchAttribute = [];
|
|
||||||
|
|
||||||
for (const attribute of attributesToSearch) {
|
|
||||||
if (record[attribute]?.toLowerCase()?.includes(searchQuery.toLowerCase())) {
|
|
||||||
matchAttribute.push(attribute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const attribute of attributesIntToSearch) {
|
|
||||||
const castedValue = String(record[attribute]);
|
|
||||||
if (castedValue && castedValue.toLowerCase().includes(searchQuery.toLowerCase())) {
|
|
||||||
matchAttribute.push(attribute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...record.get(),
|
|
||||||
matchAttribute,
|
|
||||||
tableName,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
allFoundRecords = allFoundRecords.concat(modifiedRecords);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allFoundRecords;
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const ServicesDBApi = require('../db/api/services');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class ServicesService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await ServicesDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await ServicesDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let services = await ServicesDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!services) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'servicesNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedServices = await ServicesDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedServices;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await ServicesDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await ServicesDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const Site_settingsDBApi = require('../db/api/site_settings');
|
|
||||||
const processFile = require("../middlewares/upload");
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const axios = require('axios');
|
|
||||||
const config = require('../config');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = class Site_settingsService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await Site_settingsDBApi.create(
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async bulkImport(req, res, sendInvitationEmails = true, host) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
console.log('CSV results', results);
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
})
|
|
||||||
|
|
||||||
await Site_settingsDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
let site_settings = await Site_settingsDBApi.findBy(
|
|
||||||
{id},
|
|
||||||
{transaction},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!site_settings) {
|
|
||||||
throw new ValidationError(
|
|
||||||
'site_settingsNotFound',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedSite_settings = await Site_settingsDBApi.update(
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedSite_settings;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Site_settingsDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Site_settingsDBApi.remove(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user