3 * @module routes/tenantIcon
4 * @description Tenant branding icon upload and retrieval endpoints.
5 * Allows tenants to upload custom .ico favicon files for white-label branding.
10 * @author RMM-PSA Development Team
11 * @copyright 2026 RMM-PSA Platform
12 * @license Proprietary
16 * @apiDefine TenantIcon Tenant Branding
17 * Custom tenant icon/favicon management
20const express = require('express');
21const multer = require('multer');
22const path = require('path');
23const fs = require('fs');
24const router = express.Router();
26// Use /tmp for DO App Platform (read-only filesystem)
27const ICONS_DIR = process.env.NODE_ENV === 'production'
29 : path.join(__dirname, '../../tenant_icons');
30if (!fs.existsSync(ICONS_DIR)) fs.mkdirSync(ICONS_DIR, { recursive: true });
32const upload = multer({
33 storage: multer.diskStorage({
34 destination: (req, file, cb) => cb(null, ICONS_DIR),
35 filename: (req, file, cb) => cb(null, `${req.params.tenantId}.ico`)
37 fileFilter: (req, file, cb) => {
38 if (file.mimetype === 'image/png' || file.mimetype === 'image/x-icon') cb(null, true);
39 else cb(new Error('Invalid file type'));
44 * @api {post} /api/tenant/:tenantId/icon Upload tenant icon
45 * @apiName UploadTenantIcon
46 * @apiGroup TenantIcon
47 * @apiDescription Upload custom favicon/icon for tenant branding (white-label).
48 * Accepts PNG or ICO format. File stored as {tenantId}.ico. Replaces existing icon.
49 * @apiParam {number} tenantId Tenant ID (path parameter)
50 * @apiParam {File} icon Icon file (multipart/form-data, PNG or ICO, field name: "icon")
51 * @apiSuccess {boolean} ok=true Upload successful
52 * @apiError (400) {String} error="Invalid file type" File not PNG or ICO
53 * @apiExample {curl} Example:
54 * curl -X POST http://localhost:3000/api/tenant/2/icon \\
55 * -F "icon=@/path/to/favicon.ico"
56 * @apiSuccessExample {json} Success-Response:
62router.post('/:tenantId/icon', upload.single('icon'), (req, res) => {
63 res.json({ ok: true });
67 * @api {get} /api/tenant/:tenantId/icon Get tenant icon
68 * @apiName GetTenantIcon
69 * @apiGroup TenantIcon
70 * @apiDescription Retrieve custom tenant icon/favicon file. Returns binary ICO/PNG file.
71 * Used for displaying custom branding in dashboard and agent applications.
72 * @apiParam {number} tenantId Tenant ID (path parameter)
73 * @apiSuccess {File} icon Binary icon file (PNG or ICO format)
74 * @apiError (404) Status=404 Icon not found for tenant
75 * @apiExample {curl} Example:
76 * curl -X GET http://localhost:3000/api/tenant/2/icon \\
78 * @apiSuccessExample {binary} Success-Response:
80 * Content-Type: image/x-icon
82 * [binary icon file content]
84router.get('/:tenantId/icon', (req, res) => {
85 const iconPath = path.join(ICONS_DIR, `${req.params.tenantId}.ico`);
86 if (fs.existsSync(iconPath)) {
87 res.sendFile(iconPath);
89 res.status(404).end();
93module.exports = router;