Initial commit: Angular frontend and Expressjs backend
This commit is contained in:
23
worklenz-backend/src/middlewares/image-to-webp.ts
Normal file
23
worklenz-backend/src/middlewares/image-to-webp.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import {NextFunction} from "express";
|
||||
import sharp from "sharp";
|
||||
|
||||
import {IWorkLenzRequest} from "../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../models/server-response";
|
||||
|
||||
export default async function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction) {
|
||||
if (!req.body.file) return next();
|
||||
try {
|
||||
const buffer = Buffer.from(req.body.file.replace(/^data:(.*?);base64,/, ""), "base64");
|
||||
const out = await sharp(buffer)
|
||||
.webp({quality: 50})
|
||||
.toBuffer();
|
||||
|
||||
req.body.type = "webp";
|
||||
req.body.buffer = out;
|
||||
|
||||
return next();
|
||||
} catch (error) {
|
||||
return res.status(200).send(new ServerResponse(false, null, "Upload failed"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import {NextFunction} from "express";
|
||||
import {IWorkLenzRequest} from "../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../interfaces/worklenz-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction) {
|
||||
// Map string[] -> Array<{ id: string; }>
|
||||
req.body.tasks = req.body.tasks.map((id: string) => ({id}));
|
||||
return next();
|
||||
}
|
||||
15
worklenz-backend/src/middlewares/schema-validator.ts
Normal file
15
worklenz-backend/src/middlewares/schema-validator.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {NextFunction, Request, Response} from "express";
|
||||
import {Schema, Validator} from "jsonschema";
|
||||
import {ServerResponse} from "../models/server-response";
|
||||
|
||||
export default function (schema: Schema) {
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
const validator = new Validator();
|
||||
const result = validator.validate(req.body, schema);
|
||||
|
||||
if (!result.valid)
|
||||
return res.status(400).send(new ServerResponse(false, null, (result.errors[0]?.schema as any).message || null));
|
||||
|
||||
return next();
|
||||
};
|
||||
}
|
||||
26
worklenz-backend/src/middlewares/session-middleware.ts
Normal file
26
worklenz-backend/src/middlewares/session-middleware.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import session from "express-session";
|
||||
import db from "../config/db";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const pgSession = require("connect-pg-simple")(session);
|
||||
|
||||
export default session({
|
||||
name: process.env.SESSION_NAME,
|
||||
secret: process.env.SESSION_SECRET || [], // session secret
|
||||
proxy: false,
|
||||
resave: false,
|
||||
saveUninitialized: true,
|
||||
rolling: true,
|
||||
store: new pgSession({
|
||||
pool: db.pool,
|
||||
tableName: "pg_sessions"
|
||||
}),
|
||||
cookie: {
|
||||
path: "/",
|
||||
// secure: true,
|
||||
// httpOnly: true,
|
||||
// sameSite: true,
|
||||
// domain: process.env.HOSTNAME,
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days
|
||||
}
|
||||
});
|
||||
1
worklenz-backend/src/middlewares/validators/README.md
Normal file
1
worklenz-backend/src/middlewares/validators/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Validators are expressjs middlewares that validate the request body.
|
||||
@@ -0,0 +1,22 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {file, file_name, size} = req.body;
|
||||
|
||||
if (!file || !file_name || !size)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Upload failed"));
|
||||
|
||||
if (size > 200000)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Max file size 200kb.").withTitle("Upload failed!"));
|
||||
|
||||
req.body.type = file_name.split(".").pop();
|
||||
|
||||
if (req.body.type !== "png" && req.body.type !== "jpg" && req.body.type !== "jpeg")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Invalid file type"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name} = req.body;
|
||||
if (!name?.trim())
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {phase_id, tasks} = req.body;
|
||||
if (!phase_id || !Array.isArray(tasks))
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {priority_id, tasks} = req.body;
|
||||
if (!priority_id || !Array.isArray(tasks))
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {status_id, tasks} = req.body;
|
||||
if (!status_id || !Array.isArray(tasks))
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {tasks} = req.body;
|
||||
if (!Array.isArray(tasks))
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
req.body.labels = Array.isArray(req.body.labels) ? req.body.labels : [];
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name} = req.body;
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
|
||||
req.body.name = req.body.name.trim();
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {project_id} = req.query;
|
||||
if (!project_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project ID is required"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {project_id, start_date, end_date} = req.query;
|
||||
if (!project_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project ID is required"));
|
||||
|
||||
if (!start_date)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Start date is required"));
|
||||
|
||||
if (!end_date)
|
||||
return res.status(200).send(new ServerResponse(false, null, "End date is required"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import {NextFunction} from "express";
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name, end_date, project_id} = req.body;
|
||||
if (!name?.trim().length)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
if (!end_date?.trim().length)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Due date is required"));
|
||||
if (!project_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project is required"));
|
||||
|
||||
req.body.reporter_id = req.user?.id ?? null;
|
||||
req.body.team_id = req.user?.team_id ?? null;
|
||||
|
||||
req.body.inline = req.query.inline || false;
|
||||
|
||||
if (req.body.name.length > 100)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Task name length exceeded!"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
if (!req.params.id)
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
if (!req.params.id)
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
if (!req.body.length)
|
||||
return res.status(400).send(new ServerResponse(false, null, "Tasks are required!"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name} = req.body;
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
|
||||
req.body.name = req.body.name.trim();
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {status_id, task_id} = req.params;
|
||||
|
||||
if (!status_id || !task_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Updating status failed!"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
if (req.user?.owner)
|
||||
return next();
|
||||
return res.status(401).send(new ServerResponse(false, null, "You are not authorized to perform this action"));
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name} = req.body;
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import {NextFunction, Request, Response} from "express";
|
||||
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
import {isProduction} from "../../shared/utils";
|
||||
import {PasswordStrengthChecker} from "../../shared/password-strength-check";
|
||||
import {PASSWORD_POLICY} from "../../shared/constants";
|
||||
|
||||
function isStrongPassword(password: string) {
|
||||
if (!isProduction()) return true;
|
||||
const strength = PasswordStrengthChecker.validate(password);
|
||||
return strength.value >= 2 && strength.length < 32;
|
||||
}
|
||||
|
||||
export default function (req: Request, res: Response, next: NextFunction) {
|
||||
const {confirm_password, new_password, password} = req.body;
|
||||
|
||||
const psw = (password || "").trim();
|
||||
const newPws = (new_password || "").trim();
|
||||
|
||||
if (!psw)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Password is required"));
|
||||
|
||||
if (newPws) {
|
||||
if (!isStrongPassword(newPws))
|
||||
return res.status(200).send(new ServerResponse(false, null, PASSWORD_POLICY).withTitle("Please use a strong new password."));
|
||||
|
||||
if (newPws !== confirm_password)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Passwords do not match"));
|
||||
} else if (!isStrongPassword(psw)) {
|
||||
return res.status(200).send(new ServerResponse(false, null, PASSWORD_POLICY).withTitle("Please use a strong password."));
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name} = req.body;
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
import ProjectsController from "../../controllers/projects-controller";
|
||||
|
||||
export default async function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): Promise<IWorkLenzResponse | void> {
|
||||
|
||||
let is_project_manager = false;
|
||||
|
||||
if (req.query.current_project_id) {
|
||||
const result = await ProjectsController.getProjectManager(req.query.current_project_id as string);
|
||||
if (result.length)
|
||||
if (req.user && (result[0].team_member_id === req.user?.team_member_id)) is_project_manager = true;
|
||||
}
|
||||
|
||||
if (req.user && (req.user.owner || req.user.is_admin || is_project_manager))
|
||||
return next();
|
||||
return res.status(401).send(new ServerResponse(false, null, "You are not authorized to perform this action"));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
import {isValidateEmail} from "../../shared/utils";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {project_id, email} = req.body;
|
||||
if (!project_id || !isValidateEmail(email))
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { NextFunction } from "express";
|
||||
import { IWorkLenzRequest } from "../../interfaces/worklenz-request";
|
||||
import { IWorkLenzResponse } from "../../interfaces/worklenz-response";
|
||||
import { ServerResponse } from "../../models/server-response";
|
||||
import ProjectMembersController from "../../controllers/project-members-controller";
|
||||
|
||||
export default async function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): Promise<IWorkLenzResponse | void> {
|
||||
|
||||
const projectId = req.body.project_id;
|
||||
const teamMemberId = req.user?.team_member_id;
|
||||
const defaultView = req.body.default_view;
|
||||
|
||||
if (!req.body.project_id || !defaultView || !teamMemberId) {
|
||||
return res.status(401).send(new ServerResponse(false, null, "Unknown error has occured"));
|
||||
}
|
||||
|
||||
const isProjectMember = await ProjectMembersController.checkIfMemberExists(projectId, teamMemberId as string);
|
||||
|
||||
if (isProjectMember) {
|
||||
return next();
|
||||
}
|
||||
|
||||
req.body.team_member_id = teamMemberId;
|
||||
req.body.user_id = req.user?.id;
|
||||
req.body.team_id = req.user?.team_id;
|
||||
req.body.access_level = req.body.access_level ? req.body.access_level : "MEMBER";
|
||||
|
||||
const isProjectMemberAssigned = await ProjectMembersController.createOrInviteMembers(req.body);
|
||||
|
||||
if (isProjectMemberAssigned) {
|
||||
return next();
|
||||
}
|
||||
|
||||
return res.status(401).send(new ServerResponse(false, null, "Cannot assign as Project Member"));
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import {NextFunction} from "express";
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name, color_code, status_id} = req.body;
|
||||
if (!status_id || status_id.trim() === "")
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project name is required"));
|
||||
if (!color_code || color_code.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Color code is required"));
|
||||
|
||||
req.body.name = req.body.name.trim();
|
||||
|
||||
if (req.body.name.length > 100)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project name length exceeded!"));
|
||||
|
||||
if (req.body.notes && req.body.notes.length > 200)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project note length exceeded!"));
|
||||
|
||||
if (req.body.working_days && !(Number.isInteger(req.body.working_days)))
|
||||
return res.status(200).send(new ServerResponse(false, null, "Please use integer values"));
|
||||
|
||||
if (req.body.man_days && !(Number.isInteger(req.body.man_days)))
|
||||
return res.status(200).send(new ServerResponse(false, null, "Please use integer values"));
|
||||
|
||||
if (req.body.hours_per_day && !(Number.isInteger(req.body.hours_per_day)))
|
||||
return res.status(200).send(new ServerResponse(false, null, "Please use integer values"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import {NextFunction} from "express";
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name, template_id, category_id} = req.body;
|
||||
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
|
||||
if (!template_id || template_id.trim() === "")
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
if (!category_id || category_id.trim() === "")
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
req.body.color_code = req.body.color_code || "#a9a9a9";
|
||||
req.body.default_status = !!req.body.default_status;
|
||||
req.body.name = req.body.name.trim();
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name, project_id} = req.body;
|
||||
if (!name)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
if (!project_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project is required"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
import {isValidateEmail} from "../../shared/utils";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {email} = req.body;
|
||||
if (!email)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Email is required"));
|
||||
|
||||
if (!isValidateEmail(email))
|
||||
return res.status(200).send(new ServerResponse(false, null, "Invalid email address"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { NextFunction } from "express";
|
||||
|
||||
import { IWorkLenzRequest } from "../../interfaces/worklenz-request";
|
||||
import { IWorkLenzResponse } from "../../interfaces/worklenz-response";
|
||||
import { ServerResponse } from "../../models/server-response";
|
||||
import { isValidateEmail } from "../../shared/utils";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const { team_name, project_name, template_id } = req.body;
|
||||
if (template_id && team_name) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (!template_id) {
|
||||
if (!team_name)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Account name is required"));
|
||||
|
||||
if (!project_name)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project name is required"));
|
||||
|
||||
req.body.tasks = Array.isArray(req.body.tasks) ? req.body.tasks : [];
|
||||
req.body.team_members = Array.isArray(req.body.team_members) ? req.body.team_members.filter((i: string) => !!i) : [];
|
||||
|
||||
if (!req.body.tasks.length)
|
||||
return res.status(200).send(new ServerResponse(false, null, "At least one task is required"));
|
||||
|
||||
for (const email of req.body.team_members) {
|
||||
if (email && !isValidateEmail(email))
|
||||
return res.status(200).send(new ServerResponse(false, null, "One or more of your team members has invalid email addresses. Please double check and try again.").withTitle("Account setup failed!"));
|
||||
}
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {project_id} = req.body;
|
||||
if (!project_id)
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import {NextFunction, Request, Response} from "express";
|
||||
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
import {isValidateEmail} from "../../shared/utils";
|
||||
|
||||
export default function (req: Request, res: Response, next: NextFunction) {
|
||||
const {name, email} = req.body;
|
||||
if (!name) return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
if (!email) return res.status(200).send(new ServerResponse(false, null, "Email is required"));
|
||||
if (!isValidateEmail(email)) return res.status(200).send(new ServerResponse(false, null, "Invalid email address"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {project, replace} = req.query;
|
||||
if (!project)
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
req.query.replace = /null/.test(replace as string) ? null : replace as any;
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
if (!req.body.status_order)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Invalid request. Please try again. "));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {file, file_name, project_id, size} = req.body;
|
||||
|
||||
if (!file || !file_name || !project_id || !size)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Upload failed"));
|
||||
|
||||
if (size > 5.243e+7)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Max file size for attachments is 50 MB.").withTitle("Upload failed!"));
|
||||
|
||||
req.body.type = file_name.split(".").pop();
|
||||
|
||||
req.body.task_id = req.body.task_id || null;
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {content, task_id} = req.body;
|
||||
if (!content)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Comment message is required"));
|
||||
if (!task_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Unable to create comment"));
|
||||
if (content.length > 2000)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Message length exceeded"));
|
||||
|
||||
req.body.mentions = Array.isArray(req.body.mentions)
|
||||
? req.body.mentions
|
||||
: [];
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const name = (req.body.name || "").trim();
|
||||
if (!name)
|
||||
return res.status(400).send(new ServerResponse(false, null, "Invalid name"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import {NextFunction} from "express";
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name, project_id, category_id} = req.body;
|
||||
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
|
||||
if (!project_id || project_id.trim() === "")
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
if (!category_id || category_id.trim() === "")
|
||||
return res.status(400).send(new ServerResponse(false, null));
|
||||
|
||||
req.body.color_code = req.body.color_code || "#a9a9a9";
|
||||
req.body.default_status = !!req.body.default_status;
|
||||
req.body.name = req.body.name.trim();
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { NextFunction } from "express";
|
||||
|
||||
import { IWorkLenzRequest } from "../../interfaces/worklenz-request";
|
||||
import { IWorkLenzResponse } from "../../interfaces/worklenz-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
|
||||
const {id, seconds_spent, created_at, formatted_start} = req.body;
|
||||
|
||||
if (!id || !seconds_spent || !formatted_start) return res.sendStatus(400);
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
import {getRandomColorCode, sanitize, toMinutes, toRound} from "../../shared/utils";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name, priority_id, status_id, assignees, project_id, labels} = req.body;
|
||||
if (!name?.trim()?.length)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
if (!priority_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Priority is required"));
|
||||
if (!status_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Status is required"));
|
||||
if (!project_id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Project is required"));
|
||||
|
||||
req.body.total_hours = isNaN(+req.body.total_hours) || req.body.total_hours > 1000 ? 0 : toRound(req.body.total_hours);
|
||||
req.body.total_minutes = isNaN(+req.body.total_minutes) || req.body.total_minutes > 1000 ? 0 : toRound(req.body.total_minutes);
|
||||
|
||||
req.body.assignees = Array.isArray(assignees) ? assignees : [];
|
||||
req.body.labels = Array.isArray(labels) ? labels : [];
|
||||
|
||||
req.body.reporter_id = req.user?.id || null;
|
||||
req.body.total_minutes = toMinutes(req.body.total_hours, req.body.total_minutes);
|
||||
req.body.team_id = req.user?.team_id || null;
|
||||
|
||||
req.body.inline = req.query.inline || false;
|
||||
|
||||
const labelsJson = [];
|
||||
for (const label of req.body.labels) {
|
||||
labelsJson.push({
|
||||
name: label,
|
||||
color: getRandomColorCode()
|
||||
});
|
||||
}
|
||||
|
||||
req.body.labels = labelsJson;
|
||||
|
||||
if (req.body.description) {
|
||||
if (req.body.description.length > 4000)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Task description length exceeded!"));
|
||||
req.body.description = sanitize(req.body.description);
|
||||
}
|
||||
|
||||
if (req.body.name.length > 100)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Task name length exceeded!"));
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
import {isValidateEmail} from "../../shared/utils";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {emails} = req.body;
|
||||
|
||||
if (!Array.isArray(emails) || !emails.length)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Email addresses cannot be empty"));
|
||||
|
||||
for (const email of emails) {
|
||||
if (!isValidateEmail(email))
|
||||
return res.status(200).send(new ServerResponse(false, null, "Invalid email address"));
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
if (req.user && (req.user.owner || req.user.is_admin))
|
||||
return next();
|
||||
return res.status(401).send(new ServerResponse(false, null, "You are not authorized to perform this action"));
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name} = req.body;
|
||||
if (!name || name.trim() === "")
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {id} = req.body;
|
||||
if (!id)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Invalid team identifier"));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {name, color_code} = req.body;
|
||||
if (!name)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Name is required"));
|
||||
if (!color_code)
|
||||
req.body.color_code = "#767676";
|
||||
|
||||
req.body.done = !!req.body.done;
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import {NextFunction} from "express";
|
||||
|
||||
import {IWorkLenzRequest} from "../../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../../interfaces/worklenz-response";
|
||||
import {ServerResponse} from "../../models/server-response";
|
||||
|
||||
export default function (req: IWorkLenzRequest, res: IWorkLenzResponse, next: NextFunction): IWorkLenzResponse | void {
|
||||
const {hash, password, user} = req.body;
|
||||
if (!password)
|
||||
return res.status(200).send(new ServerResponse(false, null, "Password is required"));
|
||||
|
||||
if (!hash || !user)
|
||||
return res.status(200).send(new ServerResponse(false, null, "An unknown error has occurred. Please try again."));
|
||||
return next();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import {NextFunction} from "express";
|
||||
import {IWorkLenzRequest} from "../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../interfaces/worklenz-response";
|
||||
import createHttpError from "http-errors";
|
||||
import db from "../config/db";
|
||||
|
||||
export default function (projectId: string) {
|
||||
return async (req: IWorkLenzRequest, _res: IWorkLenzResponse, next: NextFunction) => {
|
||||
const userId = req.user?.id;
|
||||
const teamId = req.user?.team_id;
|
||||
|
||||
try {
|
||||
const q = `
|
||||
SELECT 1
|
||||
FROM project_members
|
||||
WHERE project_id = $1
|
||||
AND team_member_id = (SELECT id FROM team_members WHERE team_id = $2 AND user_id = $3);
|
||||
`;
|
||||
const result = await db.query(q, [projectId, teamId, userId]);
|
||||
if (result.rowCount)
|
||||
return next();
|
||||
} catch (error) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
return next(createHttpError(401));
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user