Upgrade system finished
This commit is contained in:
@@ -1 +1 @@
|
||||
{"version":3,"file":"responses.routes.d.ts","sourceRoot":"","sources":["../../../../src/modules/influence/responses/responses.routes.ts"],"names":[],"mappings":"AAkBA,QAAA,MAAM,oBAAoB,4CAAW,CAAC;AAiDtC,QAAA,MAAM,qBAAqB,4CAAW,CAAC;AA6EvC,QAAA,MAAM,oBAAoB,4CAAW,CAAC;AA6DtC,OAAO,EAAE,oBAAoB,IAAI,4BAA4B,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC"}
|
||||
{"version":3,"file":"responses.routes.d.ts","sourceRoot":"","sources":["../../../../src/modules/influence/responses/responses.routes.ts"],"names":[],"mappings":"AAgBA,QAAA,MAAM,oBAAoB,4CAAW,CAAC;AAiDtC,QAAA,MAAM,qBAAqB,4CAAW,CAAC;AA6EvC,QAAA,MAAM,oBAAoB,4CAAW,CAAC;AA6DtC,OAAO,EAAE,oBAAoB,IAAI,4BAA4B,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC"}
|
||||
@@ -2,7 +2,6 @@
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.responsesAdminRouter = exports.responsesPublicRouter = exports.responseCampaignPublicRouter = void 0;
|
||||
const express_1 = require("express");
|
||||
const client_1 = require("@prisma/client");
|
||||
const responses_service_1 = require("./responses.service");
|
||||
const responses_schemas_1 = require("./responses.schemas");
|
||||
const validate_1 = require("../../../middleware/validate");
|
||||
@@ -10,7 +9,7 @@ const auth_middleware_1 = require("../../../middleware/auth.middleware");
|
||||
const auth_middleware_2 = require("../../../middleware/auth.middleware");
|
||||
const rbac_middleware_1 = require("../../../middleware/rbac.middleware");
|
||||
const rate_limit_1 = require("../../../middleware/rate-limit");
|
||||
const ADMIN_ROLES = [client_1.UserRole.SUPER_ADMIN, client_1.UserRole.INFLUENCE_ADMIN, client_1.UserRole.MAP_ADMIN];
|
||||
const roles_1 = require("../../../utils/roles");
|
||||
// --- Campaign-scoped public routes (mount at /api/campaigns) ---
|
||||
const campaignPublicRouter = (0, express_1.Router)();
|
||||
exports.responseCampaignPublicRouter = campaignPublicRouter;
|
||||
@@ -111,7 +110,7 @@ responsesPublicRouter.get('/:id/report/:token', async (req, res, next) => {
|
||||
const responsesAdminRouter = (0, express_1.Router)();
|
||||
exports.responsesAdminRouter = responsesAdminRouter;
|
||||
responsesAdminRouter.use(auth_middleware_1.authenticate);
|
||||
responsesAdminRouter.use((0, rbac_middleware_1.requireRole)(...ADMIN_ROLES));
|
||||
responsesAdminRouter.use((0, rbac_middleware_1.requireRole)(...roles_1.INFLUENCE_ROLES));
|
||||
// GET /api/responses
|
||||
responsesAdminRouter.get('/', (0, validate_1.validate)(responses_schemas_1.listAdminResponsesSchema, 'query'), async (req, res, next) => {
|
||||
try {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -82,11 +82,11 @@ export declare const listAdminResponsesSchema: z.ZodObject<{
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
limit: number;
|
||||
page: number;
|
||||
status?: "PENDING" | "APPROVED" | "REJECTED" | undefined;
|
||||
status?: "APPROVED" | "PENDING" | "REJECTED" | undefined;
|
||||
search?: string | undefined;
|
||||
campaignId?: string | undefined;
|
||||
}, {
|
||||
status?: "PENDING" | "APPROVED" | "REJECTED" | undefined;
|
||||
status?: "APPROVED" | "PENDING" | "REJECTED" | undefined;
|
||||
search?: string | undefined;
|
||||
limit?: number | undefined;
|
||||
page?: number | undefined;
|
||||
@@ -99,9 +99,9 @@ export declare const updateResponseStatusSchema: z.ZodObject<{
|
||||
REJECTED: "REJECTED";
|
||||
}>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
status: "PENDING" | "APPROVED" | "REJECTED";
|
||||
status: "APPROVED" | "PENDING" | "REJECTED";
|
||||
}, {
|
||||
status: "PENDING" | "APPROVED" | "REJECTED";
|
||||
status: "APPROVED" | "PENDING" | "REJECTED";
|
||||
}>;
|
||||
export type SubmitResponseInput = z.infer<typeof submitResponseSchema>;
|
||||
export type ListPublicResponsesInput = z.infer<typeof listPublicResponsesSchema>;
|
||||
|
||||
@@ -4,14 +4,14 @@ exports.updateResponseStatusSchema = exports.listAdminResponsesSchema = exports.
|
||||
const zod_1 = require("zod");
|
||||
const client_1 = require("@prisma/client");
|
||||
exports.submitResponseSchema = zod_1.z.object({
|
||||
representativeName: zod_1.z.string().min(1, 'Representative name is required'),
|
||||
representativeName: zod_1.z.string().min(1, 'Representative name is required').max(200),
|
||||
representativeLevel: zod_1.z.nativeEnum(client_1.GovernmentLevel),
|
||||
responseType: zod_1.z.nativeEnum(client_1.ResponseType),
|
||||
responseText: zod_1.z.string().min(1, 'Response text is required'),
|
||||
representativeTitle: zod_1.z.string().optional(),
|
||||
responseText: zod_1.z.string().min(1, 'Response text is required').max(5000),
|
||||
representativeTitle: zod_1.z.string().max(200).optional(),
|
||||
representativeEmail: zod_1.z.string().email().optional(),
|
||||
userComment: zod_1.z.string().optional(),
|
||||
submittedByName: zod_1.z.string().optional(),
|
||||
userComment: zod_1.z.string().max(1000).optional(),
|
||||
submittedByName: zod_1.z.string().max(200).optional(),
|
||||
submittedByEmail: zod_1.z.string().email().optional(),
|
||||
isAnonymous: zod_1.z.boolean().optional().default(false),
|
||||
sendVerification: zod_1.z.boolean().optional().default(false),
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"responses.schemas.js","sourceRoot":"","sources":["../../../../src/modules/influence/responses/responses.schemas.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,2CAA+E;AAElE,QAAA,oBAAoB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3C,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,iCAAiC,CAAC;IACxE,mBAAmB,EAAE,OAAC,CAAC,UAAU,CAAC,wBAAe,CAAC;IAClD,YAAY,EAAE,OAAC,CAAC,UAAU,CAAC,qBAAY,CAAC;IACxC,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,2BAA2B,CAAC;IAC5D,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;IAClD,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;IAC/C,WAAW,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAClD,gBAAgB,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACxD,CAAC,CAAC;AAEU,QAAA,yBAAyB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChD,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9D,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC5E,KAAK,EAAE,OAAC,CAAC,UAAU,CAAC,wBAAe,CAAC,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAEU,QAAA,wBAAwB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC/C,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9D,MAAM,EAAE,OAAC,CAAC,UAAU,CAAC,uBAAc,CAAC,CAAC,QAAQ,EAAE;IAC/C,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AAEU,QAAA,0BAA0B,GAAG,OAAC,CAAC,MAAM,CAAC;IACjD,MAAM,EAAE,OAAC,CAAC,UAAU,CAAC,uBAAc,CAAC;CACrC,CAAC,CAAC"}
|
||||
{"version":3,"file":"responses.schemas.js","sourceRoot":"","sources":["../../../../src/modules/influence/responses/responses.schemas.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,2CAA+E;AAElE,QAAA,oBAAoB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3C,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,iCAAiC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACjF,mBAAmB,EAAE,OAAC,CAAC,UAAU,CAAC,wBAAe,CAAC;IAClD,YAAY,EAAE,OAAC,CAAC,UAAU,CAAC,qBAAY,CAAC;IACxC,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACtE,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACnD,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;IAClD,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IAC5C,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAC/C,gBAAgB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;IAC/C,WAAW,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAClD,gBAAgB,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACxD,CAAC,CAAC;AAEU,QAAA,yBAAyB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChD,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9D,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC5E,KAAK,EAAE,OAAC,CAAC,UAAU,CAAC,wBAAe,CAAC,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAEU,QAAA,wBAAwB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC/C,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9D,MAAM,EAAE,OAAC,CAAC,UAAU,CAAC,uBAAc,CAAC,CAAC,QAAQ,EAAE;IAC/C,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AAEU,QAAA,0BAA0B,GAAG,OAAC,CAAC,MAAM,CAAC;IACjD,MAAM,EAAE,OAAC,CAAC,UAAU,CAAC,uBAAc,CAAC;CACrC,CAAC,CAAC"}
|
||||
@@ -100,8 +100,9 @@ export declare const responsesService: {
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
upvoteCount: number;
|
||||
campaignSlug: string;
|
||||
submittedByUserId: string | null;
|
||||
campaignId: string;
|
||||
campaignSlug: string;
|
||||
representativeName: string;
|
||||
representativeTitle: string | null;
|
||||
representativeLevel: import(".prisma/client").$Enums.GovernmentLevel;
|
||||
@@ -119,7 +120,6 @@ export declare const responsesService: {
|
||||
verifiedAt: Date | null;
|
||||
verifiedBy: string | null;
|
||||
submittedIp: string | null;
|
||||
submittedByUserId: string | null;
|
||||
}>;
|
||||
deleteResponse(id: string): Promise<void>;
|
||||
resendVerification(id: string): Promise<{
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"responses.service.d.ts","sourceRoot":"","sources":["../../../../src/modules/influence/responses/responses.service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,gBAAgB;yBAGA,MAAM,QAAQ,mBAAmB,aAAa,MAAM;;;;;uBAmEtD,MAAM,WAAW,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;mBA0D7C,MAAM;;;;;;uBA2BF,MAAM,WAAW,MAAM,WAAW,MAAM;;;;;;;6BAgClC,MAAM,WAAW,MAAM,WAAW,MAAM;;;uBAwB9C,MAAM,SAAS,MAAM;;;;;;;;;uBAqCrB,MAAM,SAAS,MAAM;;;;;;;;;qBA6BvB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAwDvB,MAAM,QAAQ,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAUrC,MAAM;2BAOF,MAAM;;;CA6CpC,CAAC"}
|
||||
{"version":3,"file":"responses.service.d.ts","sourceRoot":"","sources":["../../../../src/modules/influence/responses/responses.service.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,gBAAgB;yBAGA,MAAM,QAAQ,mBAAmB,aAAa,MAAM;;;;;uBA8FtD,MAAM,WAAW,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;mBA0D7C,MAAM;;;;;;uBA2BF,MAAM,WAAW,MAAM,WAAW,MAAM;;;;;;;6BAgClC,MAAM,WAAW,MAAM,WAAW,MAAM;;;uBAwB9C,MAAM,SAAS,MAAM;;;;;;;;;uBAqCrB,MAAM,SAAS,MAAM;;;;;;;;;qBA6BvB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAwDvB,MAAM,QAAQ,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAUrC,MAAM;2BAOF,MAAM;;;CA6CpC,CAAC"}
|
||||
@@ -6,8 +6,12 @@ const client_1 = require("@prisma/client");
|
||||
const database_1 = require("../../../config/database");
|
||||
const error_handler_1 = require("../../../middleware/error-handler");
|
||||
const email_service_1 = require("../../../services/email.service");
|
||||
const notification_queue_service_1 = require("../../../services/notification-queue.service");
|
||||
const notification_helper_1 = require("../../../services/notification.helper");
|
||||
const env_1 = require("../../../config/env");
|
||||
const logger_1 = require("../../../utils/logger");
|
||||
const metrics_1 = require("../../../utils/metrics");
|
||||
const rocketchat_webhook_service_1 = require("../../../services/rocketchat-webhook.service");
|
||||
const VERIFICATION_EXPIRY_DAYS = 30;
|
||||
exports.responsesService = {
|
||||
// --- Public ---
|
||||
@@ -64,6 +68,32 @@ exports.responsesService = {
|
||||
});
|
||||
}
|
||||
(0, metrics_1.recordResponseSubmission)();
|
||||
// Notification: admin response submitted alert
|
||||
try {
|
||||
if (await (0, notification_helper_1.isNotificationEnabled)('notifyAdminResponseSubmitted')) {
|
||||
const adminEmails = await (0, notification_helper_1.getAdminEmailsByRole)([client_1.UserRole.SUPER_ADMIN, client_1.UserRole.INFLUENCE_ADMIN]);
|
||||
if (adminEmails.length > 0) {
|
||||
const adminUrl = `${env_1.env.ADMIN_URL || 'http://localhost:3000'}/app/influence/responses`;
|
||||
await notification_queue_service_1.notificationQueueService.enqueue({
|
||||
type: 'admin-response-submitted',
|
||||
adminEmails,
|
||||
campaignTitle: campaign.title,
|
||||
representativeName: data.representativeName,
|
||||
responseType: data.responseType,
|
||||
submitterName: data.isAnonymous ? 'Anonymous' : (data.submittedByName || 'Anonymous'),
|
||||
adminUrl,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger_1.logger.error('Failed to enqueue response submitted notification:', err);
|
||||
}
|
||||
// Notify Rocket.Chat
|
||||
rocketchat_webhook_service_1.rocketchatWebhookService.onCampaignResponseSubmitted({
|
||||
campaignTitle: campaign.title,
|
||||
representativeName: data.representativeName,
|
||||
}).catch(() => { });
|
||||
return {
|
||||
id: response.id,
|
||||
status: response.status,
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user