feat(settings): implement tenant-scoped category setting endpoints for General, Notifications, Security, API Keys

This commit is contained in:
Inamul-hasan-tec
2026-08-08 16:42:28 +05:30
parent c249efd81e
commit 31f8dc1b71
4 changed files with 99 additions and 0 deletions
@@ -45,6 +45,24 @@ export class SettingController {
next(error);
}
}
async getByCategory(req, res, next) {
try {
const data = await service.getCategorySettings(req.params.category, req.user);
return res.status(200).json({ success: true, data });
} catch (error) {
next(error);
}
}
async updateByCategory(req, res, next) {
try {
const data = await service.upsertCategorySettings(req.params.category, req.body, req.user);
return res.status(200).json({ success: true, message: 'Settings saved successfully', data });
} catch (error) {
next(error);
}
}
}
export default new SettingController();
@@ -14,6 +14,23 @@ export default (sequelize) => {
primaryKey: true,
allowNull: false
},
tenant_id: {
type: DataTypes.INTEGER,
allowNull: true
},
category: {
type: DataTypes.STRING(50),
allowNull: false,
defaultValue: 'general'
},
key: {
type: DataTypes.STRING(100),
allowNull: true
},
value: {
type: DataTypes.JSONB,
allowNull: true
},
name: {
type: DataTypes.STRING,
allowNull: true
@@ -29,6 +29,18 @@ router.get(
controller.getAll
);
router.get(
'/by-category/:category',
authenticate,
controller.getByCategory
);
router.put(
'/by-category/:category',
authenticate,
controller.updateByCategory
);
/**
* @swagger
* /api/v1/settings/{id}:
@@ -1,4 +1,5 @@
import repository from './setting.repository.js';
import { models } from '../../../shared/database/models.js';
import { SocketService } from '../../../shared/services/socket.service.js';
import { AuditService } from '../../../shared/services/audit.service.js';
import { ApiError } from '../../../utils/helpers/ApiError.utils.js';
@@ -54,6 +55,57 @@ export class SettingService {
return record;
}
async getCategorySettings(category, userContext = {}) {
const tenantId = userContext.tenant_id || userContext.tenantId || null;
const where = { category };
if (tenantId) {
where.tenant_id = tenantId;
}
const settings = await models.Setting.findAll({ where });
const result = {};
for (const setting of settings) {
if (setting.key) {
result[setting.key] = setting.value;
}
}
return result;
}
async upsertCategorySettings(category, settingsData = {}, userContext = {}) {
const tenantId = userContext.tenant_id || userContext.tenantId || null;
for (const [key, value] of Object.entries(settingsData)) {
const where = { category, key };
if (tenantId) {
where.tenant_id = tenantId;
}
const existing = await models.Setting.findOne({ where });
if (existing) {
await existing.update({ value });
} else {
await models.Setting.create({
tenant_id: tenantId,
category,
key,
value,
name: `${category}.${key}`
});
}
}
// Audit Log
await AuditService.log({
action: 'UPDATE_SETTINGS',
resource: 'Setting',
userId: userContext.user_id || 'system',
details: { category, settingsData }
});
return await this.getCategorySettings(category, userContext);
}
async delete(id, userContext = {}) {
const deleted = await repository.delete(id);
if (!deleted) {