Merge pull request #309 from shancds/upstreame-release-v2.1.4

Origin release v2.1.4
This commit is contained in:
Chamika J
2025-08-05 16:49:37 +05:30
committed by GitHub
3 changed files with 45 additions and 9 deletions

View File

@@ -5,7 +5,7 @@ import db from "../config/db";
import {ServerResponse} from "../models/server-response"; import {ServerResponse} from "../models/server-response";
import WorklenzControllerBase from "./worklenz-controller-base"; import WorklenzControllerBase from "./worklenz-controller-base";
import HandleExceptions from "../decorators/handle-exceptions"; import HandleExceptions from "../decorators/handle-exceptions";
import {TASK_PRIORITY_COLOR_ALPHA, WorklenzColorCodes} from "../shared/constants"; import {TASK_PRIORITY_COLOR_ALPHA, WorklenzColorCodes, WorklenzColorShades} from "../shared/constants";
export default class LabelsController extends WorklenzControllerBase { export default class LabelsController extends WorklenzControllerBase {
@HandleExceptions() @HandleExceptions()
@@ -73,7 +73,7 @@ export default class LabelsController extends WorklenzControllerBase {
WHERE id = $1 WHERE id = $1
AND team_id = $2;`; AND team_id = $2;`;
if (!WorklenzColorCodes.includes(req.body.color)) if (!Object.values(WorklenzColorShades).flat().includes(req.body.color))
return res.status(400).send(new ServerResponse(false, null)); return res.status(400).send(new ServerResponse(false, null));
const result = await db.query(q, [req.params.id, req.user?.team_id, req.body.color]); const result = await db.query(q, [req.params.id, req.user?.team_id, req.body.color]);
@@ -92,7 +92,7 @@ export default class LabelsController extends WorklenzControllerBase {
} }
if (req.body.color) { if (req.body.color) {
if (!WorklenzColorCodes.includes(req.body.color)) if (!Object.values(WorklenzColorShades).flat().includes(req.body.color))
return res.status(400).send(new ServerResponse(false, null)); return res.status(400).send(new ServerResponse(false, null));
updates.push(`color_code = $${paramIndex++}`); updates.push(`color_code = $${paramIndex++}`);
values.push(req.body.color); values.push(req.body.color);

View File

@@ -124,7 +124,7 @@ export default class TaskCommentsController extends WorklenzControllerBase {
const q = ` const q = `
INSERT INTO task_comment_attachments (name, type, size, task_id, comment_id, team_id, project_id) INSERT INTO task_comment_attachments (name, type, size, task_id, comment_id, team_id, project_id)
VALUES ($1, $2, $3, $4, $5, $6, $7) VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, name, type, task_id, comment_id, created_at, RETURNING id, name, type, task_id, comment_id, created_at,
CONCAT($8::TEXT, '/', team_id, '/', project_id, '/', task_id, '/', comment_id, '/', id, '.', type) AS url; CONCAT($8::TEXT, '/', team_id, '/', project_id, '/', task_id, '/', comment_id, '/', id, '.', type) AS url;
`; `;
@@ -217,7 +217,43 @@ export default class TaskCommentsController extends WorklenzControllerBase {
} }
} }
return res.status(200).send(new ServerResponse(true, data.comment)); // Get user avatar URL from database
const avatarQuery = `SELECT avatar_url FROM users WHERE id = $1`;
const avatarResult = await db.query(avatarQuery, [req.user?.id]);
const avatarUrl = avatarResult.rows[0]?.avatar_url || "";
// Get comment details including created_at
const commentQuery = `SELECT created_at FROM task_comments WHERE id = $1`;
const commentResult = await db.query(commentQuery, [response.id]);
const commentData = commentResult.rows[0];
// Get attachments if any
const attachmentsQuery = `SELECT id, name, type, size FROM task_comment_attachments WHERE comment_id = $1`;
const attachmentsResult = await db.query(attachmentsQuery, [response.id]);
const commentAttachments = attachmentsResult.rows.map(att => ({
id: att.id,
name: att.name,
type: att.type,
size: att.size
}));
const commentdata = {
attachments: commentAttachments,
avatar_url: avatarUrl,
content: req.body.content,
created_at: commentData?.created_at || new Date().toISOString(),
edit: false,
id: response.id,
member_name: req.user?.name || "",
mentions: mentions || [],
rawContent: req.body.content,
reactions: { likes: {} },
team_member_id: req.user?.team_member_id || "",
user_id: req.user?.id || ""
};
return res.status(200).send(new ServerResponse(true, commentdata));
} }
@HandleExceptions() @HandleExceptions()
@@ -530,17 +566,17 @@ export default class TaskCommentsController extends WorklenzControllerBase {
for (const attachment of attachments) { for (const attachment of attachments) {
if (req.user?.subscription_status === "free" && req.user?.owner_id) { if (req.user?.subscription_status === "free" && req.user?.owner_id) {
const limits = await getFreePlanSettings(); const limits = await getFreePlanSettings();
const usedStorage = await getUsedStorage(req.user?.owner_id); const usedStorage = await getUsedStorage(req.user?.owner_id);
if ((parseInt(usedStorage) + attachment.size) > megabytesToBytes(parseInt(limits.free_tier_storage))) { if ((parseInt(usedStorage) + attachment.size) > megabytesToBytes(parseInt(limits.free_tier_storage))) {
return res.status(200).send(new ServerResponse(false, [], `Sorry, the free plan cannot exceed ${limits.free_tier_storage}MB of storage.`)); return res.status(200).send(new ServerResponse(false, [], `Sorry, the free plan cannot exceed ${limits.free_tier_storage}MB of storage.`));
} }
} }
const q = ` const q = `
INSERT INTO task_comment_attachments (name, type, size, task_id, comment_id, team_id, project_id) INSERT INTO task_comment_attachments (name, type, size, task_id, comment_id, team_id, project_id)
VALUES ($1, $2, $3, $4, $5, $6, $7) VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, name, type, task_id, comment_id, created_at, RETURNING id, name, type, task_id, comment_id, created_at,
CONCAT($8::TEXT, '/', team_id, '/', project_id, '/', task_id, '/', comment_id, '/', id, '.', type) AS url; CONCAT($8::TEXT, '/', team_id, '/', project_id, '/', task_id, '/', comment_id, '/', id, '.', type) AS url;
`; `;

View File

@@ -8,7 +8,7 @@ import {PASSWORD_POLICY} from "../../shared/constants";
function isStrongPassword(password: string) { function isStrongPassword(password: string) {
if (!isProduction()) return true; if (!isProduction()) return true;
const strength = PasswordStrengthChecker.validate(password); const strength = PasswordStrengthChecker.validate(password);
return strength.value >= 2 && strength.length < 32; return strength.value >= 2 && strength.length <= 32;
} }
export default function (req: Request, res: Response, next: NextFunction) { export default function (req: Request, res: Response, next: NextFunction) {