Files
Zumri-Backend/app/controllers/upload.controller.js
T
Sathira Sri Sathara fd4e324571 feat: implement customer profile management and business application features
- Added customer profile controller with endpoints for retrieving, updating, and deactivating user profiles.
- Introduced address model and routes for managing user addresses.
- Created business application model and service for handling business applications, including approval and rejection processes.
- Developed business contact and credit account models to support business customer functionalities.
- Implemented settlement term model for managing payment terms.
- Added email templates for business application notifications (approved, rejected, received, and status changes).
- Enhanced validation schemas for customer and business inputs to ensure data integrity.
- Created unit tests for business application service and validation schemas to ensure functionality and correctness.
- Added migration scripts to set up new database tables and columns for customer and business features.
2026-09-03 14:58:26 +05:30

46 lines
3.5 KiB
JavaScript

const db = require("../models");
const storage = require("../services/storage/storage.service");
const { validateUpload } = require("../services/storage/file-validation.service");
const BUSINESS_DOCUMENT_PURPOSES = new Set(["BUSINESS_REGISTRATION", "TAX_DOCUMENT", "IDENTITY_DOCUMENT", "OTHER_SUPPORTING_DOCUMENT"]);
const canAccess = (user, upload) => upload.visibility === "PUBLIC" || upload.owner_id === user.id || user.accountType === "superadmin" || (user.permissions || []).includes("media.read") || (BUSINESS_DOCUMENT_PURPOSES.has(upload.use_for) && (user.permissions || []).includes("business.applications.review"));
exports.uploadFile = async (req, res, next) => {
let objectKey;
try {
const details = validateUpload(req.file);
const purpose = String(req.body.use_for || "generic").replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 60);
objectKey = storage.createObjectKey({ ownerId: req.user.id, mimeType: details.mimeType, purpose });
await storage.uploadBuffer({ buffer: req.file.buffer, objectKey, mimeType: details.mimeType, checksum: details.checksum });
let record;
try {
record = await db.Upload.create({ file_path: objectKey, file_type: details.mimeType, file_size: details.size, original_name: req.file.originalname, safe_name: details.safeName, checksum: details.checksum, use_for: purpose, uploaded_by: req.user.id, owner_type: "USER", owner_id: req.user.id, visibility: "PRIVATE", status: "AVAILABLE" });
} catch (error) { await storage.deleteObject(objectKey).catch(() => undefined); throw error; }
const expiresIn = Number(process.env.S3_SIGNED_URL_TTL_SECONDS || 900);
return res.status(201).json({ success: true, data: { id: record.id, originalName: record.original_name, mimeType: record.file_type, size: record.file_size, purpose: record.use_for, status: record.status, url: await storage.createSignedDownloadUrl(objectKey, expiresIn), expiresIn } });
} catch (error) { return next(error); }
};
exports.getFileUrl = async (req, res, next) => {
try {
const upload = await db.Upload.findByPk(req.params.id);
if (!upload || upload.status === "DELETED") return res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "File not found" } });
if (!canAccess(req.user, upload)) return res.status(403).json({ success: false, error: { code: "FORBIDDEN", message: "Access denied" } });
if (upload.status !== "AVAILABLE") return res.status(409).json({ success: false, error: { code: "FILE_UNAVAILABLE", message: "File is not available" } });
const expiresIn = Number(process.env.S3_SIGNED_URL_TTL_SECONDS || 900);
return res.json({ success: true, data: { id: upload.id, url: await storage.createSignedDownloadUrl(upload.file_path, expiresIn), expiresIn } });
} catch (error) { return next(error); }
};
exports.deleteFile = async (req, res, next) => {
try {
const upload = await db.Upload.findByPk(req.params.id);
if (!upload || upload.status === "DELETED") return res.status(404).json({ success: false, error: { code: "NOT_FOUND", message: "File not found" } });
const allowed = upload.owner_id === req.user.id || req.user.accountType === "super_admin" || (req.user.permissions || []).includes("media.delete");
if (!allowed) return res.status(403).json({ success: false, error: { code: "FORBIDDEN", message: "Access denied" } });
await upload.update({ status: "DELETED", deletedAt: new Date() });
await storage.deleteObject(upload.file_path).catch(() => undefined);
return res.status(204).end();
} catch (error) { return next(error); }
};