@goweekdays/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.github/workflows/main.yml +17 -0
- package/.github/workflows/publish.yml +39 -0
- package/CHANGELOG.md +7 -0
- package/dist/index.d.ts +1366 -0
- package/dist/index.js +4580 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4544 -0
- package/dist/index.mjs.map +1 -0
- package/dist/public/handlebars/forget-password.hbs +13 -0
- package/dist/public/handlebars/member-invite.hbs +16 -0
- package/dist/public/handlebars/user-invite.hbs +13 -0
- package/package.json +40 -0
- package/tsconfig.json +16 -0
- package/tsup.config.ts +10 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4544 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __async = (__this, __arguments, generator) => {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
var fulfilled = (value) => {
|
|
23
|
+
try {
|
|
24
|
+
step(generator.next(value));
|
|
25
|
+
} catch (e) {
|
|
26
|
+
reject(e);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var rejected = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
step(generator.throw(value));
|
|
32
|
+
} catch (e) {
|
|
33
|
+
reject(e);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
37
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/utils/error.ts
|
|
42
|
+
var AppError = class extends Error {
|
|
43
|
+
constructor(message, statusCode, isOperational = true) {
|
|
44
|
+
super(message);
|
|
45
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
46
|
+
this.statusCode = statusCode;
|
|
47
|
+
this.isOperational = isOperational;
|
|
48
|
+
Error.captureStackTrace(this);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var BadRequestError = class extends AppError {
|
|
52
|
+
constructor(message = "Bad Request") {
|
|
53
|
+
super(message, 400);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var UnauthorizedError = class extends AppError {
|
|
57
|
+
constructor(message = "Unauthorized") {
|
|
58
|
+
super(message, 401);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var NotFoundError = class extends AppError {
|
|
62
|
+
constructor(message = "Not Found") {
|
|
63
|
+
super(message, 404);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var InternalServerError = class extends AppError {
|
|
67
|
+
constructor(message = "Internal Server Error") {
|
|
68
|
+
super(message, 500);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/utils/logger.ts
|
|
73
|
+
import * as winston from "winston";
|
|
74
|
+
var logger = winston.createLogger({
|
|
75
|
+
level: "info",
|
|
76
|
+
format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
|
|
77
|
+
transports: [
|
|
78
|
+
// File transport (optional)
|
|
79
|
+
new winston.transports.File({ filename: "error.log", level: "error" }),
|
|
80
|
+
new winston.transports.File({ filename: "combined.log" })
|
|
81
|
+
]
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// src/utils/errorHandler.middleware.ts
|
|
85
|
+
var errorHandler = (err, req, res, next) => {
|
|
86
|
+
if (err.isOperational) {
|
|
87
|
+
res.status(err.statusCode).json({
|
|
88
|
+
status: "error",
|
|
89
|
+
message: err.message
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
} else {
|
|
93
|
+
logger.log({ level: "error", message: err.message });
|
|
94
|
+
res.status(500).json({
|
|
95
|
+
status: "error",
|
|
96
|
+
message: "Internal Server Error"
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// src/utils/authorization.middleware.ts
|
|
103
|
+
import jwt from "jsonwebtoken";
|
|
104
|
+
function authMiddleware(access_token_secret = "") {
|
|
105
|
+
return (req, res, next) => {
|
|
106
|
+
if (!access_token_secret) {
|
|
107
|
+
res.status(401).json({ message: "Access token secret is required" });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const authorization = req.headers["authorization"];
|
|
111
|
+
const token = authorization && authorization.split(" ")[1];
|
|
112
|
+
if (!token) {
|
|
113
|
+
res.status(401).json({ message: "Unauthorized" });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
jwt.verify(token, access_token_secret, (err, user) => {
|
|
117
|
+
if (err) {
|
|
118
|
+
res.status(401).json({ message: "Authorization token expired" });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
req.headers["user"] = user.user;
|
|
122
|
+
next();
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/utils/hash-password.ts
|
|
128
|
+
import bcrypt from "bcrypt";
|
|
129
|
+
var saltRounds = 10;
|
|
130
|
+
function hashPassword(password) {
|
|
131
|
+
return __async(this, null, function* () {
|
|
132
|
+
try {
|
|
133
|
+
return yield bcrypt.hash(password, saltRounds);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
throw new Error("Failed to hash password.");
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/utils/compare-password.ts
|
|
141
|
+
import bcrypt2 from "bcrypt";
|
|
142
|
+
function comparePassword(password, hashedPassword) {
|
|
143
|
+
return __async(this, null, function* () {
|
|
144
|
+
return new Promise((resolve) => {
|
|
145
|
+
bcrypt2.compare(password, hashedPassword, (err, result) => {
|
|
146
|
+
if (err) {
|
|
147
|
+
resolve(false);
|
|
148
|
+
}
|
|
149
|
+
resolve(result);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/utils/mailer.ts
|
|
156
|
+
import { createTransport } from "nodemailer";
|
|
157
|
+
var useMailer = class {
|
|
158
|
+
constructor(config2) {
|
|
159
|
+
this.config = config2;
|
|
160
|
+
this.transporter = createTransport({
|
|
161
|
+
host: config2.host,
|
|
162
|
+
port: config2.port,
|
|
163
|
+
secure: config2.secure,
|
|
164
|
+
auth: {
|
|
165
|
+
user: config2.email,
|
|
166
|
+
pass: config2.password
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
sendMail(_0) {
|
|
171
|
+
return __async(this, arguments, function* ({
|
|
172
|
+
to,
|
|
173
|
+
subject,
|
|
174
|
+
text,
|
|
175
|
+
html,
|
|
176
|
+
sender
|
|
177
|
+
}) {
|
|
178
|
+
const mailOptions = {
|
|
179
|
+
from: sender ? `${sender} <${this.config.email}>` : this.config.email,
|
|
180
|
+
to,
|
|
181
|
+
subject
|
|
182
|
+
};
|
|
183
|
+
if (text) {
|
|
184
|
+
mailOptions.text = text;
|
|
185
|
+
}
|
|
186
|
+
if (html) {
|
|
187
|
+
mailOptions.html = html;
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
yield this.transporter.sendMail(mailOptions);
|
|
191
|
+
return "Email sent successfully";
|
|
192
|
+
} catch (error) {
|
|
193
|
+
return Promise.reject(error);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// src/utils/generate-token.ts
|
|
200
|
+
import jwt2 from "jsonwebtoken";
|
|
201
|
+
function generateToken({ metadata = {}, secret = "", options = {} } = {}) {
|
|
202
|
+
if (!secret)
|
|
203
|
+
throw new Error("Missing secret.");
|
|
204
|
+
return jwt2.sign(metadata, secret, options);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/utils/paginate.ts
|
|
208
|
+
function paginate(items, page = 0, limit = 10, length) {
|
|
209
|
+
if (length === 0) {
|
|
210
|
+
return {
|
|
211
|
+
items: [],
|
|
212
|
+
pages: 0,
|
|
213
|
+
pageRange: `0-0 of 0`
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
const startIndex = page * limit + 1;
|
|
217
|
+
const endIndex = Math.min(startIndex + limit - 1, length);
|
|
218
|
+
return {
|
|
219
|
+
items,
|
|
220
|
+
pages: Math.ceil(length / limit),
|
|
221
|
+
pageRange: `${startIndex}-${endIndex} of ${length}`
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/utils/redis.ts
|
|
226
|
+
import { createClient } from "redis";
|
|
227
|
+
|
|
228
|
+
// src/config.ts
|
|
229
|
+
import * as dotenv from "dotenv";
|
|
230
|
+
dotenv.config();
|
|
231
|
+
var MONGO_URI = process.env.MONGO_URI || "mongodb://localhost:27017";
|
|
232
|
+
var MONGO_DB = process.env.MONGO_DB || "default";
|
|
233
|
+
var PORT = Number(process.env.PORT || 3001);
|
|
234
|
+
var SECRET_KEY = process.env.SECRET_KEY;
|
|
235
|
+
var isDev = process.env.NODE_ENV !== "production";
|
|
236
|
+
var MAILER_TRANSPORT_HOST = process.env.MAILER_TRANSPORT_HOST;
|
|
237
|
+
var MAILER_TRANSPORT_PORT = Number(
|
|
238
|
+
process.env.MAILER_TRANSPORT_PORT || 465
|
|
239
|
+
);
|
|
240
|
+
var MAILER_TRANSPORT_SECURE = process.env.MAILER_TRANSPORT_SECURE === "true";
|
|
241
|
+
var MAILER_EMAIL = process.env.MAILER_EMAIL;
|
|
242
|
+
var MAILER_PASSWORD = process.env.MAILER_PASSWORD;
|
|
243
|
+
var ACCESS_TOKEN_SECRET = process.env.ACCESS_TOKEN_SECRET || "access_token_secret";
|
|
244
|
+
var REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET || "refresh_token_secret";
|
|
245
|
+
var ACCESS_TOKEN_EXPIRY = process.env.ACCESS_TOKEN_EXPIRY || "15s";
|
|
246
|
+
var REFRESH_TOKEN_EXPIRY = process.env.REFRESH_TOKEN_EXPIRY || "30d";
|
|
247
|
+
var APP_ACCOUNT = process.env.APP_ACCOUNT || "http://localhost:3000";
|
|
248
|
+
var VERIFICATION_FORGET_PASSWORD_DURATION = process.env.VERIFICATION_FORGET_PASSWORD_DURATION || "10 minutes";
|
|
249
|
+
var VERIFICATION_USER_INVITE_DURATION = process.env.VERIFICATION_USER_INVITE_DURATION || "3 days";
|
|
250
|
+
var REDIS_HOST = process.env.REDIS_HOST;
|
|
251
|
+
var REDIS_PORT = Number(process.env.REDIS_PORT || 6379);
|
|
252
|
+
var REDIS_PASSWORD = process.env.REDIS_PASSWORD;
|
|
253
|
+
var DEFAULT_USER_EMAIL = process.env.DEFAULT_USER_EMAIL;
|
|
254
|
+
var DEFAULT_USER_PASSWORD = process.env.DEFAULT_USER_PASSWORD;
|
|
255
|
+
var DEFAULT_USER_FIRST_NAME = process.env.DEFAULT_USER_FIRST_NAME;
|
|
256
|
+
var DEFAULT_USER_LAST_NAME = process.env.DEFAULT_USER_LAST_NAME;
|
|
257
|
+
var SPACES_ACCESS_KEY = process.env.SPACES_ACCESS_KEY;
|
|
258
|
+
var SPACES_SECRET_KEY = process.env.SPACES_SECRET_KEY;
|
|
259
|
+
var SPACES_ENDPOINT = process.env.SPACES_ENDPOINT;
|
|
260
|
+
var SPACES_REGION = process.env.SPACES_REGION;
|
|
261
|
+
var SPACES_BUCKET = process.env.SPACES_BUCKET;
|
|
262
|
+
|
|
263
|
+
// src/utils/redis.ts
|
|
264
|
+
var redisClient;
|
|
265
|
+
function initRedisClient() {
|
|
266
|
+
return __async(this, null, function* () {
|
|
267
|
+
redisClient = yield createClient({
|
|
268
|
+
password: REDIS_PASSWORD,
|
|
269
|
+
socket: {
|
|
270
|
+
host: REDIS_HOST,
|
|
271
|
+
port: REDIS_PORT
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function useRedisClient() {
|
|
277
|
+
return redisClient;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/utils/compile-handlebar.ts
|
|
281
|
+
import Handlebars from "handlebars";
|
|
282
|
+
import fs from "fs";
|
|
283
|
+
function compileHandlebar({ context = {}, filePath = "" } = {}) {
|
|
284
|
+
const templateSource = fs.readFileSync(filePath, "utf8");
|
|
285
|
+
const template = Handlebars.compile(templateSource);
|
|
286
|
+
return template(context);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/utils/get-directory.ts
|
|
290
|
+
import path from "path";
|
|
291
|
+
function getDirectory(directory, filePath) {
|
|
292
|
+
return path.resolve(directory, `${filePath}.hbs`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/utils/s3.ts
|
|
296
|
+
import { PutObjectCommand, DeleteObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
297
|
+
import { Readable } from "stream";
|
|
298
|
+
var useS3 = class {
|
|
299
|
+
constructor(config2) {
|
|
300
|
+
this.config = config2;
|
|
301
|
+
this.client = new S3Client({
|
|
302
|
+
endpoint: config2.endpoint,
|
|
303
|
+
region: config2.region,
|
|
304
|
+
credentials: {
|
|
305
|
+
accessKeyId: config2.accessKeyId,
|
|
306
|
+
secretAccessKey: config2.secretAccessKey
|
|
307
|
+
},
|
|
308
|
+
forcePathStyle: false
|
|
309
|
+
// Optional, based on usage
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
uploadObject(_0) {
|
|
313
|
+
return __async(this, arguments, function* ({
|
|
314
|
+
key,
|
|
315
|
+
body,
|
|
316
|
+
metadata = {},
|
|
317
|
+
contentType
|
|
318
|
+
}) {
|
|
319
|
+
const buffer = Readable.from(body);
|
|
320
|
+
try {
|
|
321
|
+
yield this.client.send(new PutObjectCommand({
|
|
322
|
+
Bucket: this.config.bucket,
|
|
323
|
+
Key: key,
|
|
324
|
+
Body: buffer,
|
|
325
|
+
ACL: "public-read",
|
|
326
|
+
Metadata: metadata,
|
|
327
|
+
ContentType: contentType,
|
|
328
|
+
ContentLength: Buffer.byteLength(body)
|
|
329
|
+
}));
|
|
330
|
+
return "Successfully uploaded file.";
|
|
331
|
+
} catch (error) {
|
|
332
|
+
return Promise.reject(error);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
deleteObject(key = "") {
|
|
337
|
+
return __async(this, null, function* () {
|
|
338
|
+
try {
|
|
339
|
+
yield this.client.send(new DeleteObjectCommand({ Key: key, Bucket: this.config.bucket }));
|
|
340
|
+
return "Successfully deleted file.";
|
|
341
|
+
} catch (error) {
|
|
342
|
+
return Promise.reject(error);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
// src/utils/atlas.ts
|
|
349
|
+
import { MongoClient } from "mongodb";
|
|
350
|
+
var useAtlas = class {
|
|
351
|
+
// Initialize the MongoDB connection with the provided config
|
|
352
|
+
static initialize(config2) {
|
|
353
|
+
return __async(this, null, function* () {
|
|
354
|
+
if (this.client) {
|
|
355
|
+
console.warn(`Client is already initialized. Skipping initialization.`);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const { uri, db } = config2;
|
|
359
|
+
this.client = new MongoClient(uri, { maxPoolSize: 10, maxIdleTimeMS: 6e4, connectTimeoutMS: 6e4 });
|
|
360
|
+
try {
|
|
361
|
+
yield this.client.connect();
|
|
362
|
+
this.database = this.client.db(db);
|
|
363
|
+
console.log(`Connected to database "${db}".`);
|
|
364
|
+
} catch (error) {
|
|
365
|
+
this.client = null;
|
|
366
|
+
throw error;
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
// Get the MongoDB client
|
|
371
|
+
static getClient() {
|
|
372
|
+
return this.client;
|
|
373
|
+
}
|
|
374
|
+
// Get the database
|
|
375
|
+
static getDb() {
|
|
376
|
+
return this.database;
|
|
377
|
+
}
|
|
378
|
+
// Close the connection
|
|
379
|
+
static close() {
|
|
380
|
+
return __async(this, null, function* () {
|
|
381
|
+
if (this.client) {
|
|
382
|
+
yield this.client.close();
|
|
383
|
+
this.client = null;
|
|
384
|
+
this.database = null;
|
|
385
|
+
console.log(`Closed connection to the database.`);
|
|
386
|
+
} else {
|
|
387
|
+
console.warn(`No client is currently initialized.`);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
useAtlas.client = null;
|
|
393
|
+
useAtlas.database = null;
|
|
394
|
+
|
|
395
|
+
// src/utils/prepend-zero.ts
|
|
396
|
+
function prependZeros(value, length = 6) {
|
|
397
|
+
let numberStr = value.toString();
|
|
398
|
+
let numZeros = Math.max(0, length - numberStr.length);
|
|
399
|
+
return numberStr.padStart(numZeros + numberStr.length, "0");
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// src/utils/to-object-id.ts
|
|
403
|
+
import { ObjectId } from "mongodb";
|
|
404
|
+
function toObjectId(value) {
|
|
405
|
+
if (!value) {
|
|
406
|
+
throw new BadRequestError("Valid is required.");
|
|
407
|
+
}
|
|
408
|
+
const instanceOfObjectId = value instanceof ObjectId;
|
|
409
|
+
if (!instanceOfObjectId) {
|
|
410
|
+
const isValidHex = /^[0-9a-fA-F]{24}$/.test(value);
|
|
411
|
+
if (!isValidHex) {
|
|
412
|
+
throw new BadRequestError("Invalid value, expecting a hex value.");
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
return new ObjectId(value);
|
|
417
|
+
} catch (error) {
|
|
418
|
+
throw new BadRequestError("Invalid ID.");
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/models/verification.model.ts
|
|
423
|
+
import { ObjectId as ObjectId2 } from "mongodb";
|
|
424
|
+
var MVerification = class {
|
|
425
|
+
constructor(value) {
|
|
426
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
427
|
+
this._id = (_a = value._id) != null ? _a : new ObjectId2();
|
|
428
|
+
this.type = (_b = value.type) != null ? _b : "";
|
|
429
|
+
this.email = (_c = value.email) != null ? _c : "";
|
|
430
|
+
this.metadata = (_d = value.metadata) != null ? _d : {};
|
|
431
|
+
this.status = (_e = value.status) != null ? _e : "pending";
|
|
432
|
+
this.createdAt = (_f = value.createdAt) != null ? _f : /* @__PURE__ */ new Date();
|
|
433
|
+
this.updatedAt = (_g = value.updatedAt) != null ? _g : null;
|
|
434
|
+
this.expireAt = (_h = value.expireAt) != null ? _h : new Date(Date.now() + 3600 * 1e3);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// src/repositories/verification.repository.ts
|
|
439
|
+
import {
|
|
440
|
+
BadRequestError as BadRequestError2,
|
|
441
|
+
InternalServerError as InternalServerError2,
|
|
442
|
+
logger as logger2,
|
|
443
|
+
paginate as paginate2,
|
|
444
|
+
useAtlas as useAtlas2
|
|
445
|
+
} from "@goweekdays/utils";
|
|
446
|
+
import { ObjectId as ObjectId3 } from "mongodb";
|
|
447
|
+
function useVerificationRepo() {
|
|
448
|
+
const db = useAtlas2.getDb();
|
|
449
|
+
if (!db) {
|
|
450
|
+
throw new InternalServerError2("Unable to connect to server.");
|
|
451
|
+
}
|
|
452
|
+
const collection = db.collection("verifications");
|
|
453
|
+
function createTextIndex() {
|
|
454
|
+
return __async(this, null, function* () {
|
|
455
|
+
try {
|
|
456
|
+
yield collection.createIndex({
|
|
457
|
+
email: "text"
|
|
458
|
+
});
|
|
459
|
+
} catch (error) {
|
|
460
|
+
throw new Error("Failed to create text index on email.");
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
function add(value, session) {
|
|
465
|
+
return __async(this, null, function* () {
|
|
466
|
+
value = new MVerification(value);
|
|
467
|
+
try {
|
|
468
|
+
const res = yield collection.insertOne(value, { session });
|
|
469
|
+
return res.insertedId;
|
|
470
|
+
} catch (error) {
|
|
471
|
+
logger2.log({
|
|
472
|
+
level: "info",
|
|
473
|
+
message: String(error)
|
|
474
|
+
});
|
|
475
|
+
throw new InternalServerError2("Server internal error.");
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
function getById(_id) {
|
|
480
|
+
return __async(this, null, function* () {
|
|
481
|
+
try {
|
|
482
|
+
_id = new ObjectId3(_id);
|
|
483
|
+
} catch (error) {
|
|
484
|
+
throw new BadRequestError2("Invalid ID.");
|
|
485
|
+
}
|
|
486
|
+
try {
|
|
487
|
+
return yield collection.findOne({ _id });
|
|
488
|
+
} catch (error) {
|
|
489
|
+
throw new InternalServerError2(
|
|
490
|
+
"Internal server error, failed to retrieve verification."
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function getVerifications() {
|
|
496
|
+
return __async(this, arguments, function* ({
|
|
497
|
+
search = "",
|
|
498
|
+
page = 1,
|
|
499
|
+
limit = 10,
|
|
500
|
+
sort = {},
|
|
501
|
+
status = "active",
|
|
502
|
+
type = ""
|
|
503
|
+
} = {}) {
|
|
504
|
+
page = page > 0 ? page - 1 : 0;
|
|
505
|
+
const query = { status };
|
|
506
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
507
|
+
if (search) {
|
|
508
|
+
query.$text = { $search: search };
|
|
509
|
+
}
|
|
510
|
+
if (type) {
|
|
511
|
+
query.type = type;
|
|
512
|
+
}
|
|
513
|
+
try {
|
|
514
|
+
const items = yield collection.aggregate([
|
|
515
|
+
{ $match: query },
|
|
516
|
+
{ $sort: sort },
|
|
517
|
+
{ $skip: page * limit },
|
|
518
|
+
{ $limit: limit },
|
|
519
|
+
{
|
|
520
|
+
$project: {
|
|
521
|
+
_id: 1,
|
|
522
|
+
createdAt: 1,
|
|
523
|
+
email: 1,
|
|
524
|
+
type: 1,
|
|
525
|
+
metadata: 1,
|
|
526
|
+
status: 1
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
]).toArray();
|
|
530
|
+
const length = yield collection.countDocuments(query);
|
|
531
|
+
return paginate2(items, page, limit, length);
|
|
532
|
+
} catch (error) {
|
|
533
|
+
logger2.log({ level: "error", message: `${error}` });
|
|
534
|
+
throw error;
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
function getByIdByType(type) {
|
|
539
|
+
return __async(this, null, function* () {
|
|
540
|
+
try {
|
|
541
|
+
return yield collection.find({ type }).toArray();
|
|
542
|
+
} catch (error) {
|
|
543
|
+
return Promise.reject(error);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
function updateStatusById(_id, status, session) {
|
|
548
|
+
return __async(this, null, function* () {
|
|
549
|
+
try {
|
|
550
|
+
_id = new ObjectId3(_id);
|
|
551
|
+
} catch (error) {
|
|
552
|
+
throw new BadRequestError2("Invalid ID.");
|
|
553
|
+
}
|
|
554
|
+
try {
|
|
555
|
+
return yield collection.updateOne(
|
|
556
|
+
{ _id },
|
|
557
|
+
{ $set: { status, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
|
|
558
|
+
{ session }
|
|
559
|
+
);
|
|
560
|
+
} catch (error) {
|
|
561
|
+
throw new InternalServerError2("Error updating verification status.");
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
return {
|
|
566
|
+
createTextIndex,
|
|
567
|
+
add,
|
|
568
|
+
getVerifications,
|
|
569
|
+
getById,
|
|
570
|
+
getByIdByType,
|
|
571
|
+
updateStatusById
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/services/verification.service.ts
|
|
576
|
+
import {
|
|
577
|
+
useMailer as useMailer2,
|
|
578
|
+
compileHandlebar as compileHandlebar2,
|
|
579
|
+
logger as logger4,
|
|
580
|
+
getDirectory as getDirectory2,
|
|
581
|
+
BadRequestError as BadRequestError5,
|
|
582
|
+
NotFoundError as NotFoundError2,
|
|
583
|
+
InternalServerError as InternalServerError4,
|
|
584
|
+
useAtlas as useAtlas4
|
|
585
|
+
} from "@goweekdays/utils";
|
|
586
|
+
|
|
587
|
+
// src/repositories/user.repository.ts
|
|
588
|
+
import { ObjectId as ObjectId5 } from "mongodb";
|
|
589
|
+
|
|
590
|
+
// src/models/user.model.ts
|
|
591
|
+
import { ObjectId as ObjectId4 } from "mongodb";
|
|
592
|
+
import { BadRequestError as BadRequestError3 } from "@goweekdays/utils";
|
|
593
|
+
var MUserRole = class {
|
|
594
|
+
constructor(value) {
|
|
595
|
+
var _a, _b, _c, _d;
|
|
596
|
+
this.name = (_a = value.name) != null ? _a : "";
|
|
597
|
+
this.app = (_b = value.app) != null ? _b : "";
|
|
598
|
+
this.role = (_c = value.role) != null ? _c : "";
|
|
599
|
+
this.status = (_d = value.status) != null ? _d : "active";
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
var MUser = class {
|
|
603
|
+
constructor(value) {
|
|
604
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
|
|
605
|
+
this._id = (_a = value._id) != null ? _a : new ObjectId4();
|
|
606
|
+
this.email = (_b = value.email) != null ? _b : "";
|
|
607
|
+
this.password = (_c = value.password) != null ? _c : "";
|
|
608
|
+
this.prefix = (_d = value.prefix) != null ? _d : "";
|
|
609
|
+
this.firstName = (_e = value.firstName) != null ? _e : "";
|
|
610
|
+
this.middleName = (_f = value.middleName) != null ? _f : "";
|
|
611
|
+
this.lastName = (_g = value.lastName) != null ? _g : "";
|
|
612
|
+
this.suffix = (_h = value.suffix) != null ? _h : "";
|
|
613
|
+
this.birthMonth = (_i = value.birthMonth) != null ? _i : "";
|
|
614
|
+
this.birthDay = (_j = value.birthDay) != null ? _j : 0;
|
|
615
|
+
this.birthYear = (_k = value.birthYear) != null ? _k : 0;
|
|
616
|
+
this.gender = (_l = value.gender) != null ? _l : "";
|
|
617
|
+
this.type = (_m = value.type) != null ? _m : "";
|
|
618
|
+
this.roles = (_n = value.roles) != null ? _n : [];
|
|
619
|
+
if (value.roles && value.roles.length) {
|
|
620
|
+
value.roles.forEach((role) => {
|
|
621
|
+
var _a2;
|
|
622
|
+
try {
|
|
623
|
+
role.role = new ObjectId4(role.role);
|
|
624
|
+
} catch (error) {
|
|
625
|
+
throw new BadRequestError3("Invalid role ID.");
|
|
626
|
+
}
|
|
627
|
+
if (!role.app) {
|
|
628
|
+
throw new BadRequestError3("App is required.");
|
|
629
|
+
}
|
|
630
|
+
if (!role.name) {
|
|
631
|
+
throw new BadRequestError3("Name is required.");
|
|
632
|
+
}
|
|
633
|
+
role.status = (_a2 = role.status) != null ? _a2 : "active";
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
this.roles = (_o = value.roles) != null ? _o : [];
|
|
637
|
+
this.status = (_p = value.status) != null ? _p : "";
|
|
638
|
+
this.createdAt = (_q = value.createdAt) != null ? _q : (/* @__PURE__ */ new Date()).toISOString();
|
|
639
|
+
this.updatedAt = (_r = value.updatedAt) != null ? _r : "";
|
|
640
|
+
this.deletedAt = (_s = value.deletedAt) != null ? _s : "";
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
// src/repositories/user.repository.ts
|
|
645
|
+
import {
|
|
646
|
+
useAtlas as useAtlas3,
|
|
647
|
+
InternalServerError as InternalServerError3,
|
|
648
|
+
logger as logger3,
|
|
649
|
+
BadRequestError as BadRequestError4,
|
|
650
|
+
paginate as paginate3
|
|
651
|
+
} from "@goweekdays/utils";
|
|
652
|
+
function useUserRepo() {
|
|
653
|
+
const db = useAtlas3.getDb();
|
|
654
|
+
if (!db) {
|
|
655
|
+
throw new InternalServerError3("Unable to connect to server.");
|
|
656
|
+
}
|
|
657
|
+
const collection = db.collection("users");
|
|
658
|
+
function createTextIndex() {
|
|
659
|
+
return __async(this, null, function* () {
|
|
660
|
+
try {
|
|
661
|
+
yield collection.createIndex({
|
|
662
|
+
firstName: "text",
|
|
663
|
+
middleName: "text",
|
|
664
|
+
lastName: "text",
|
|
665
|
+
email: "text"
|
|
666
|
+
});
|
|
667
|
+
} catch (error) {
|
|
668
|
+
throw new Error("Failed to create text index on email.");
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
function createUniqueIndex() {
|
|
673
|
+
return __async(this, null, function* () {
|
|
674
|
+
try {
|
|
675
|
+
yield collection.createIndex(
|
|
676
|
+
{ email: 1, deletedAt: 1 },
|
|
677
|
+
{ unique: true }
|
|
678
|
+
);
|
|
679
|
+
} catch (error) {
|
|
680
|
+
throw new Error("Failed to create unique index on email.");
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
function createUser(value, session) {
|
|
685
|
+
return __async(this, null, function* () {
|
|
686
|
+
try {
|
|
687
|
+
value = new MUser(value);
|
|
688
|
+
const res = yield collection.insertOne(value, { session });
|
|
689
|
+
return res.insertedId;
|
|
690
|
+
} catch (error) {
|
|
691
|
+
logger3.log({ level: "error", message: `${error}` });
|
|
692
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
693
|
+
if (isDuplicated) {
|
|
694
|
+
throw new BadRequestError4("Item name already exists");
|
|
695
|
+
}
|
|
696
|
+
throw new InternalServerError3("Internal server error.");
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
function getUserByEmail(email) {
|
|
701
|
+
return __async(this, null, function* () {
|
|
702
|
+
try {
|
|
703
|
+
return yield collection.findOne({ email });
|
|
704
|
+
} catch (error) {
|
|
705
|
+
throw new Error("Failed to get user by email.");
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
function getByEmailApp(email, app) {
|
|
710
|
+
return __async(this, null, function* () {
|
|
711
|
+
try {
|
|
712
|
+
return yield collection.findOne({ email, "roles.app": app });
|
|
713
|
+
} catch (error) {
|
|
714
|
+
throw new Error("Failed to get user by email.");
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
function getUserById(_id) {
|
|
719
|
+
return __async(this, null, function* () {
|
|
720
|
+
try {
|
|
721
|
+
_id = new ObjectId5(_id);
|
|
722
|
+
} catch (error) {
|
|
723
|
+
throw new Error("Invalid user ID.");
|
|
724
|
+
}
|
|
725
|
+
try {
|
|
726
|
+
return yield collection.findOne({ _id });
|
|
727
|
+
} catch (error) {
|
|
728
|
+
throw new Error("Failed to get user by email.");
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
function getUsers() {
|
|
733
|
+
return __async(this, arguments, function* ({
|
|
734
|
+
search = "",
|
|
735
|
+
page = 1,
|
|
736
|
+
limit = 10,
|
|
737
|
+
sort = {},
|
|
738
|
+
status = "active",
|
|
739
|
+
type = ""
|
|
740
|
+
} = {}) {
|
|
741
|
+
page = page > 0 ? page - 1 : 0;
|
|
742
|
+
const query = { status };
|
|
743
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
744
|
+
if (search) {
|
|
745
|
+
query.$text = { $search: search };
|
|
746
|
+
}
|
|
747
|
+
if (type) {
|
|
748
|
+
query.type = type;
|
|
749
|
+
}
|
|
750
|
+
try {
|
|
751
|
+
const items = yield collection.aggregate([
|
|
752
|
+
{ $match: query },
|
|
753
|
+
{ $sort: sort },
|
|
754
|
+
{ $skip: page * limit },
|
|
755
|
+
{ $limit: limit },
|
|
756
|
+
{
|
|
757
|
+
$project: {
|
|
758
|
+
_id: 1,
|
|
759
|
+
name: {
|
|
760
|
+
$concat: ["$firstName", " ", "$lastName"]
|
|
761
|
+
},
|
|
762
|
+
email: 1,
|
|
763
|
+
type: 1,
|
|
764
|
+
status: 1
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
]).toArray();
|
|
768
|
+
const length = yield collection.countDocuments(query);
|
|
769
|
+
return paginate3(items, page, limit, length);
|
|
770
|
+
} catch (error) {
|
|
771
|
+
logger3.log({ level: "error", message: `${error}` });
|
|
772
|
+
throw error;
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
function updatePassword() {
|
|
777
|
+
return __async(this, arguments, function* ({ _id, password } = {}, session) {
|
|
778
|
+
try {
|
|
779
|
+
_id = new ObjectId5(_id);
|
|
780
|
+
} catch (error) {
|
|
781
|
+
throw new Error("Invalid user ID.");
|
|
782
|
+
}
|
|
783
|
+
try {
|
|
784
|
+
return yield collection.updateOne(
|
|
785
|
+
{ _id },
|
|
786
|
+
{ $set: { password } },
|
|
787
|
+
{ session }
|
|
788
|
+
);
|
|
789
|
+
} catch (error) {
|
|
790
|
+
throw new Error("Failed to update user password.");
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
function updateName() {
|
|
795
|
+
return __async(this, arguments, function* ({ _id, firstName, lastName } = {}, session) {
|
|
796
|
+
try {
|
|
797
|
+
_id = new ObjectId5(_id);
|
|
798
|
+
} catch (error) {
|
|
799
|
+
throw new Error("Invalid user ID.");
|
|
800
|
+
}
|
|
801
|
+
try {
|
|
802
|
+
return yield collection.updateOne(
|
|
803
|
+
{ _id },
|
|
804
|
+
{ $set: { firstName, lastName } },
|
|
805
|
+
{ session }
|
|
806
|
+
);
|
|
807
|
+
} catch (error) {
|
|
808
|
+
throw new Error("Failed to update user profile.");
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
function updateBirthday() {
|
|
813
|
+
return __async(this, arguments, function* ({ _id, month, day, year } = {}, session) {
|
|
814
|
+
try {
|
|
815
|
+
_id = new ObjectId5(_id);
|
|
816
|
+
} catch (error) {
|
|
817
|
+
throw new Error("Invalid user ID.");
|
|
818
|
+
}
|
|
819
|
+
try {
|
|
820
|
+
return yield collection.updateOne(
|
|
821
|
+
{ _id },
|
|
822
|
+
{ $set: { birthMonth: month, birthDay: day, birthYear: year } },
|
|
823
|
+
{ session }
|
|
824
|
+
);
|
|
825
|
+
} catch (error) {
|
|
826
|
+
throw new Error("Failed to update user birthday.");
|
|
827
|
+
}
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
function updateUserFieldById() {
|
|
831
|
+
return __async(this, arguments, function* ({ _id, field, value } = {}, session) {
|
|
832
|
+
const allowedFields = ["gender", "email", "contact", "profile"];
|
|
833
|
+
if (!allowedFields.includes(field)) {
|
|
834
|
+
throw new BadRequestError4(
|
|
835
|
+
`Field "${field}" is not allowed to be updated.`
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
try {
|
|
839
|
+
_id = new ObjectId5(_id);
|
|
840
|
+
} catch (error) {
|
|
841
|
+
throw new BadRequestError4("Invalid ID.");
|
|
842
|
+
}
|
|
843
|
+
try {
|
|
844
|
+
yield collection.updateOne(
|
|
845
|
+
{ _id },
|
|
846
|
+
{ $set: { [field]: value } },
|
|
847
|
+
// Dynamically set the field
|
|
848
|
+
{ session }
|
|
849
|
+
);
|
|
850
|
+
return `Successfully updated user ${field}.`;
|
|
851
|
+
} catch (error) {
|
|
852
|
+
throw new InternalServerError3(`Failed to update user ${field}.`);
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
function addUserRole() {
|
|
857
|
+
return __async(this, arguments, function* ({ _id, role } = {}, session) {
|
|
858
|
+
try {
|
|
859
|
+
_id = new ObjectId5(_id);
|
|
860
|
+
} catch (error) {
|
|
861
|
+
throw new BadRequestError4("Invalid user ID.");
|
|
862
|
+
}
|
|
863
|
+
role = new MUserRole(role);
|
|
864
|
+
try {
|
|
865
|
+
yield collection.updateOne(
|
|
866
|
+
{ _id, "roles.app": { $ne: role.app } },
|
|
867
|
+
// @ts-ignore
|
|
868
|
+
{ $push: { roles: role } },
|
|
869
|
+
{ session }
|
|
870
|
+
);
|
|
871
|
+
} catch (error) {
|
|
872
|
+
throw new InternalServerError3("Failed to add user role.");
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
return {
|
|
877
|
+
createTextIndex,
|
|
878
|
+
createUniqueIndex,
|
|
879
|
+
createUser,
|
|
880
|
+
getUserByEmail,
|
|
881
|
+
getUserById,
|
|
882
|
+
getUsers,
|
|
883
|
+
updatePassword,
|
|
884
|
+
updateName,
|
|
885
|
+
updateBirthday,
|
|
886
|
+
updateUserFieldById,
|
|
887
|
+
addUserRole,
|
|
888
|
+
getByEmailApp
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// src/services/verification.service.ts
|
|
893
|
+
function useVerificationService() {
|
|
894
|
+
const MailerConfig = {
|
|
895
|
+
host: MAILER_TRANSPORT_HOST,
|
|
896
|
+
port: MAILER_TRANSPORT_PORT,
|
|
897
|
+
secure: MAILER_TRANSPORT_SECURE,
|
|
898
|
+
email: MAILER_EMAIL,
|
|
899
|
+
password: MAILER_PASSWORD
|
|
900
|
+
};
|
|
901
|
+
const mailer = new useMailer2(MailerConfig);
|
|
902
|
+
const {
|
|
903
|
+
add,
|
|
904
|
+
getById: _getById,
|
|
905
|
+
updateStatusById: _updateStatusById,
|
|
906
|
+
getVerifications: _getVerifications
|
|
907
|
+
} = useVerificationRepo();
|
|
908
|
+
const { addUserRole, getUserByEmail, getByEmailApp } = useUserRepo();
|
|
909
|
+
function createUserInvite(_0) {
|
|
910
|
+
return __async(this, arguments, function* ({
|
|
911
|
+
email,
|
|
912
|
+
metadata
|
|
913
|
+
}) {
|
|
914
|
+
const value = {
|
|
915
|
+
type: "user-invite",
|
|
916
|
+
email,
|
|
917
|
+
metadata,
|
|
918
|
+
expireAt: new Date(
|
|
919
|
+
(/* @__PURE__ */ new Date()).getTime() + 72 * 60 * 60 * 1e3
|
|
920
|
+
).toISOString(),
|
|
921
|
+
// 72 hours (3 days) from now
|
|
922
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
923
|
+
};
|
|
924
|
+
try {
|
|
925
|
+
const user = yield getByEmailApp(email, metadata.app);
|
|
926
|
+
if (user) {
|
|
927
|
+
throw new BadRequestError5(
|
|
928
|
+
`User already a user in ${metadata.app} app.`
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
const res = yield add(value);
|
|
932
|
+
const dir = __dirname;
|
|
933
|
+
const filePath = getDirectory2(dir, "./public/handlebars/user-invite");
|
|
934
|
+
const emailContent = compileHandlebar2({
|
|
935
|
+
context: {
|
|
936
|
+
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
937
|
+
link: `${APP_ACCOUNT}/verify/invitation/${res}`
|
|
938
|
+
},
|
|
939
|
+
filePath
|
|
940
|
+
});
|
|
941
|
+
mailer.sendMail({
|
|
942
|
+
to: email,
|
|
943
|
+
subject: "User Invite",
|
|
944
|
+
html: emailContent,
|
|
945
|
+
sender: "Education Ecosystem"
|
|
946
|
+
}).catch((error) => {
|
|
947
|
+
logger4.log({
|
|
948
|
+
level: "error",
|
|
949
|
+
message: `Error sending user invite email: ${error}`
|
|
950
|
+
});
|
|
951
|
+
});
|
|
952
|
+
return res;
|
|
953
|
+
} catch (error) {
|
|
954
|
+
throw error;
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
function createForgetPassword(email) {
|
|
959
|
+
return __async(this, null, function* () {
|
|
960
|
+
const value = {
|
|
961
|
+
type: "forget-password",
|
|
962
|
+
email,
|
|
963
|
+
expireAt: new Date((/* @__PURE__ */ new Date()).getTime() + 10 * 60 * 1e3).toISOString(),
|
|
964
|
+
// 10 minutes from now
|
|
965
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
966
|
+
};
|
|
967
|
+
try {
|
|
968
|
+
const res = yield add(value);
|
|
969
|
+
const dir = __dirname;
|
|
970
|
+
const filePath = getDirectory2(dir, "./public/handlebars/forget-password");
|
|
971
|
+
const emailContent = compileHandlebar2({
|
|
972
|
+
context: {
|
|
973
|
+
validity: VERIFICATION_FORGET_PASSWORD_DURATION,
|
|
974
|
+
link: `${APP_ACCOUNT}/reset-password/${res}`
|
|
975
|
+
},
|
|
976
|
+
filePath
|
|
977
|
+
});
|
|
978
|
+
mailer.sendMail({ to: email, subject: "Forget Password", html: emailContent }).catch((error) => {
|
|
979
|
+
logger4.log({
|
|
980
|
+
level: "error",
|
|
981
|
+
message: `Error sending forget password email: ${error}`
|
|
982
|
+
});
|
|
983
|
+
});
|
|
984
|
+
return res;
|
|
985
|
+
} catch (error) {
|
|
986
|
+
throw new InternalServerError4("Error creating one-time password");
|
|
987
|
+
}
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
function getById(id) {
|
|
991
|
+
return __async(this, null, function* () {
|
|
992
|
+
try {
|
|
993
|
+
const _id = yield _getById(id);
|
|
994
|
+
if (!_id) {
|
|
995
|
+
throw new NotFoundError2("Verification not found.");
|
|
996
|
+
}
|
|
997
|
+
return _id;
|
|
998
|
+
} catch (error) {
|
|
999
|
+
throw error;
|
|
1000
|
+
}
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
function getVerifications() {
|
|
1004
|
+
return __async(this, arguments, function* ({
|
|
1005
|
+
search = "",
|
|
1006
|
+
page = 1,
|
|
1007
|
+
status = "",
|
|
1008
|
+
type = "",
|
|
1009
|
+
limit = 10
|
|
1010
|
+
} = {}) {
|
|
1011
|
+
try {
|
|
1012
|
+
return yield _getVerifications({ search, page, status, type, limit });
|
|
1013
|
+
} catch (error) {
|
|
1014
|
+
throw error;
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
function errorByType(type, status) {
|
|
1019
|
+
if (type === "user-invite" && status === "expired") {
|
|
1020
|
+
throw new BadRequestError5(
|
|
1021
|
+
"Invitation has already expired, please contact admin to resend the invitation."
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
if (type === "user-invite" && status === "complete") {
|
|
1025
|
+
throw new BadRequestError5(
|
|
1026
|
+
"User already registered, please login to continue."
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
throw new BadRequestError5("Invalid verification.");
|
|
1030
|
+
}
|
|
1031
|
+
function verify(id) {
|
|
1032
|
+
return __async(this, null, function* () {
|
|
1033
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1034
|
+
const session = (_a = useAtlas4.getClient()) == null ? void 0 : _a.startSession();
|
|
1035
|
+
session == null ? void 0 : session.startTransaction();
|
|
1036
|
+
try {
|
|
1037
|
+
const _id = yield _getById(id);
|
|
1038
|
+
if (!_id) {
|
|
1039
|
+
throw new NotFoundError2("Verification not found.");
|
|
1040
|
+
}
|
|
1041
|
+
if (_id.status === "expired") {
|
|
1042
|
+
errorByType(_id.type, "expired");
|
|
1043
|
+
}
|
|
1044
|
+
if (_id.status === "complete") {
|
|
1045
|
+
throw new BadRequestError5("Verification already completed.");
|
|
1046
|
+
}
|
|
1047
|
+
const expiration = new Date(_id.expireAt).getTime();
|
|
1048
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
1049
|
+
if (now > expiration) {
|
|
1050
|
+
yield _updateStatusById(id, "expired");
|
|
1051
|
+
errorByType(_id.type, "expired");
|
|
1052
|
+
}
|
|
1053
|
+
const user = yield getUserByEmail(_id.email);
|
|
1054
|
+
const appMember = (_b = user == null ? void 0 : user.roles) == null ? void 0 : _b.filter((i) => {
|
|
1055
|
+
var _a2;
|
|
1056
|
+
return i.app === ((_a2 = _id.metadata) == null ? void 0 : _a2.app);
|
|
1057
|
+
});
|
|
1058
|
+
if ((appMember == null ? void 0 : appMember.length) === 0 && user && _id.type === "user-invite") {
|
|
1059
|
+
yield addUserRole(
|
|
1060
|
+
{
|
|
1061
|
+
_id: (_c = user._id) == null ? void 0 : _c.toString(),
|
|
1062
|
+
role: {
|
|
1063
|
+
name: (_d = _id.metadata) == null ? void 0 : _d.name,
|
|
1064
|
+
app: (_e = _id.metadata) == null ? void 0 : _e.app,
|
|
1065
|
+
role: (_f = _id.metadata) == null ? void 0 : _f.role
|
|
1066
|
+
}
|
|
1067
|
+
},
|
|
1068
|
+
session
|
|
1069
|
+
);
|
|
1070
|
+
yield _updateStatusById(id, "complete", session);
|
|
1071
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
1072
|
+
return "Successfully added user role.";
|
|
1073
|
+
}
|
|
1074
|
+
if ((appMember == null ? void 0 : appMember.length) && _id.type === "user-invite") {
|
|
1075
|
+
yield _updateStatusById(id, "expired");
|
|
1076
|
+
throw new BadRequestError5(
|
|
1077
|
+
`Invalid user invitation. User is already a user in the ${(_g = _id.metadata) == null ? void 0 : _g.app} app.`
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
return _id;
|
|
1081
|
+
} catch (error) {
|
|
1082
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
1083
|
+
logger4.log({
|
|
1084
|
+
level: "info",
|
|
1085
|
+
message: `Error verifying user invitation: ${error}`
|
|
1086
|
+
});
|
|
1087
|
+
throw error;
|
|
1088
|
+
} finally {
|
|
1089
|
+
session == null ? void 0 : session.endSession();
|
|
1090
|
+
}
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
function cancelUserInvitation(id) {
|
|
1094
|
+
return __async(this, null, function* () {
|
|
1095
|
+
try {
|
|
1096
|
+
yield updateStatusById(id, "cancelled");
|
|
1097
|
+
} catch (error) {
|
|
1098
|
+
throw new InternalServerError4(
|
|
1099
|
+
`Error cancelling user invitation: ${error}`
|
|
1100
|
+
);
|
|
1101
|
+
}
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
function updateStatusById(_id, status) {
|
|
1105
|
+
return __async(this, null, function* () {
|
|
1106
|
+
try {
|
|
1107
|
+
yield _updateStatusById(_id, status);
|
|
1108
|
+
return "Successfully updated verification status.";
|
|
1109
|
+
} catch (error) {
|
|
1110
|
+
throw error;
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
return {
|
|
1115
|
+
createForgetPassword,
|
|
1116
|
+
createUserInvite,
|
|
1117
|
+
verify,
|
|
1118
|
+
getById,
|
|
1119
|
+
getVerifications,
|
|
1120
|
+
cancelUserInvitation,
|
|
1121
|
+
updateStatusById
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// src/controllers/verification.controller.ts
|
|
1126
|
+
import {
|
|
1127
|
+
AppError as AppError2,
|
|
1128
|
+
BadRequestError as BadRequestError6,
|
|
1129
|
+
InternalServerError as InternalServerError5
|
|
1130
|
+
} from "@goweekdays/utils";
|
|
1131
|
+
import Joi from "joi";
|
|
1132
|
+
import { ObjectId as ObjectId6 } from "mongodb";
|
|
1133
|
+
function useVerificationController() {
|
|
1134
|
+
const {
|
|
1135
|
+
createUserInvite: _createUserInvite,
|
|
1136
|
+
createForgetPassword: _createForgetPassword,
|
|
1137
|
+
cancelUserInvitation: _cancelUserInvitation,
|
|
1138
|
+
verify: _verify,
|
|
1139
|
+
getVerifications: _getVerifications
|
|
1140
|
+
} = useVerificationService();
|
|
1141
|
+
function createUserInvite(req, res, next) {
|
|
1142
|
+
return __async(this, null, function* () {
|
|
1143
|
+
var _a, _b, _c, _d;
|
|
1144
|
+
const email = (_a = req.body.email) != null ? _a : "";
|
|
1145
|
+
const app = (_b = req.body.app) != null ? _b : "";
|
|
1146
|
+
const role = (_c = req.body.role) != null ? _c : "";
|
|
1147
|
+
const name = (_d = req.body.name) != null ? _d : "";
|
|
1148
|
+
const validation = Joi.object({
|
|
1149
|
+
email: Joi.string().email().required(),
|
|
1150
|
+
app: Joi.string().optional().allow("", null),
|
|
1151
|
+
role: Joi.string().hex().optional().allow("", null),
|
|
1152
|
+
name: Joi.string().optional().allow("", null)
|
|
1153
|
+
});
|
|
1154
|
+
const { error } = validation.validate({
|
|
1155
|
+
email,
|
|
1156
|
+
app,
|
|
1157
|
+
role,
|
|
1158
|
+
name
|
|
1159
|
+
});
|
|
1160
|
+
if (error) {
|
|
1161
|
+
next(new BadRequestError6(error.message));
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
try {
|
|
1165
|
+
yield _createUserInvite({
|
|
1166
|
+
email,
|
|
1167
|
+
metadata: {
|
|
1168
|
+
app,
|
|
1169
|
+
role,
|
|
1170
|
+
name
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
1173
|
+
res.json({ message: "Successfully invited user." });
|
|
1174
|
+
return;
|
|
1175
|
+
} catch (error2) {
|
|
1176
|
+
console.log(error2);
|
|
1177
|
+
next(error2);
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
function createForgetPassword(req, res, next) {
|
|
1182
|
+
return __async(this, null, function* () {
|
|
1183
|
+
const email = req.body.email || "";
|
|
1184
|
+
const validation = Joi.string().email().required();
|
|
1185
|
+
const { error } = validation.validate(email);
|
|
1186
|
+
if (error) {
|
|
1187
|
+
next(new BadRequestError6(error.message));
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
try {
|
|
1191
|
+
yield _createForgetPassword(email);
|
|
1192
|
+
res.json({
|
|
1193
|
+
message: "Check your email to verify it before resetting your password."
|
|
1194
|
+
});
|
|
1195
|
+
return;
|
|
1196
|
+
} catch (error2) {
|
|
1197
|
+
if (error2 instanceof AppError2) {
|
|
1198
|
+
next(error2);
|
|
1199
|
+
} else {
|
|
1200
|
+
next(new InternalServerError5("An unexpected error occurred"));
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
function getVerifications(req, res, next) {
|
|
1206
|
+
return __async(this, null, function* () {
|
|
1207
|
+
var _a, _b, _c;
|
|
1208
|
+
const status = (_a = req.query.status) != null ? _a : "";
|
|
1209
|
+
const search = (_b = req.query.search) != null ? _b : "";
|
|
1210
|
+
const page = (_c = Number(req.query.page)) != null ? _c : 1;
|
|
1211
|
+
const validation = Joi.object({
|
|
1212
|
+
status: Joi.string().required(),
|
|
1213
|
+
search: Joi.string().optional().allow("", null),
|
|
1214
|
+
page: Joi.number().required()
|
|
1215
|
+
});
|
|
1216
|
+
const { error } = validation.validate({ status, search, page });
|
|
1217
|
+
if (error) {
|
|
1218
|
+
next(new BadRequestError6(error.message));
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
try {
|
|
1222
|
+
const items = yield _getVerifications({ status, search, page });
|
|
1223
|
+
res.json(items);
|
|
1224
|
+
return;
|
|
1225
|
+
} catch (error2) {
|
|
1226
|
+
next(error2);
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
function verify(req, res, next) {
|
|
1231
|
+
return __async(this, null, function* () {
|
|
1232
|
+
const id = req.params.id || "";
|
|
1233
|
+
const validation = Joi.string().hex().required();
|
|
1234
|
+
const { error } = validation.validate(id);
|
|
1235
|
+
if (error) {
|
|
1236
|
+
next(new BadRequestError6(error.message));
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
try {
|
|
1240
|
+
const message = yield _verify(id);
|
|
1241
|
+
res.json({ message });
|
|
1242
|
+
return;
|
|
1243
|
+
} catch (error2) {
|
|
1244
|
+
next(error2);
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
function cancelUserInvitation(req, res, next) {
|
|
1249
|
+
return __async(this, null, function* () {
|
|
1250
|
+
const otpId = req.params.id || "";
|
|
1251
|
+
const validation = Joi.string().hex().required();
|
|
1252
|
+
const { error } = validation.validate(otpId);
|
|
1253
|
+
if (error) {
|
|
1254
|
+
next(new BadRequestError6(error.message));
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
try {
|
|
1258
|
+
const otpObjectId = new ObjectId6(otpId);
|
|
1259
|
+
yield _cancelUserInvitation(otpObjectId);
|
|
1260
|
+
return res.json({
|
|
1261
|
+
message: "User invite has been cancelled."
|
|
1262
|
+
});
|
|
1263
|
+
} catch (error2) {
|
|
1264
|
+
throw error2;
|
|
1265
|
+
}
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
return {
|
|
1269
|
+
getVerifications,
|
|
1270
|
+
createUserInvite,
|
|
1271
|
+
createForgetPassword,
|
|
1272
|
+
verify,
|
|
1273
|
+
cancelUserInvitation
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// src/models/token.model.ts
|
|
1278
|
+
import { ObjectId as ObjectId7 } from "mongodb";
|
|
1279
|
+
var MToken = class {
|
|
1280
|
+
constructor(value) {
|
|
1281
|
+
var _a, _b, _c;
|
|
1282
|
+
this.token = (_a = value.token) != null ? _a : "";
|
|
1283
|
+
this.user = (_b = value.user) != null ? _b : new ObjectId7();
|
|
1284
|
+
this.createdAt = (_c = value.createdAt) != null ? _c : (/* @__PURE__ */ new Date()).toISOString();
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
// src/repositories/token.repository.ts
|
|
1289
|
+
import { InternalServerError as InternalServerError6, useAtlas as useAtlas5 } from "@goweekdays/utils";
|
|
1290
|
+
import { ObjectId as ObjectId8 } from "mongodb";
|
|
1291
|
+
function useTokenRepo() {
|
|
1292
|
+
const db = useAtlas5.getDb();
|
|
1293
|
+
if (!db) {
|
|
1294
|
+
throw new InternalServerError6("Unable to connect to server.");
|
|
1295
|
+
}
|
|
1296
|
+
const collection = db.collection("tokens");
|
|
1297
|
+
function createToken() {
|
|
1298
|
+
return __async(this, arguments, function* ({ token, user } = {}) {
|
|
1299
|
+
try {
|
|
1300
|
+
user = new ObjectId8(user);
|
|
1301
|
+
} catch (error) {
|
|
1302
|
+
return Promise.reject("Invalid user ID");
|
|
1303
|
+
}
|
|
1304
|
+
try {
|
|
1305
|
+
yield collection.insertOne({ token, user });
|
|
1306
|
+
return "Token created";
|
|
1307
|
+
} catch (error) {
|
|
1308
|
+
return Promise.reject(error);
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
function getToken(token) {
|
|
1313
|
+
return __async(this, null, function* () {
|
|
1314
|
+
try {
|
|
1315
|
+
return yield collection.findOne({ token });
|
|
1316
|
+
} catch (error) {
|
|
1317
|
+
return Promise.reject(error);
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
function deleteToken(token) {
|
|
1322
|
+
return __async(this, null, function* () {
|
|
1323
|
+
try {
|
|
1324
|
+
return yield collection.deleteOne({ token });
|
|
1325
|
+
} catch (error) {
|
|
1326
|
+
return Promise.reject(error);
|
|
1327
|
+
}
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
return {
|
|
1331
|
+
createToken,
|
|
1332
|
+
getToken,
|
|
1333
|
+
deleteToken
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
// src/services/user.service.ts
|
|
1338
|
+
import {
|
|
1339
|
+
BadRequestError as BadRequestError8,
|
|
1340
|
+
InternalServerError as InternalServerError8,
|
|
1341
|
+
NotFoundError as NotFoundError3,
|
|
1342
|
+
hashPassword as hashPassword2,
|
|
1343
|
+
useAtlas as useAtlas7,
|
|
1344
|
+
useS3 as useS32
|
|
1345
|
+
} from "@goweekdays/utils";
|
|
1346
|
+
|
|
1347
|
+
// src/repositories/file.repository.ts
|
|
1348
|
+
import {
|
|
1349
|
+
BadRequestError as BadRequestError7,
|
|
1350
|
+
InternalServerError as InternalServerError7,
|
|
1351
|
+
useAtlas as useAtlas6
|
|
1352
|
+
} from "@goweekdays/utils";
|
|
1353
|
+
|
|
1354
|
+
// src/models/file.model.ts
|
|
1355
|
+
var MFile = class {
|
|
1356
|
+
constructor(value) {
|
|
1357
|
+
var _a, _b, _c, _d;
|
|
1358
|
+
this._id = value._id;
|
|
1359
|
+
this.name = (_a = value.name) != null ? _a : "";
|
|
1360
|
+
this.type = (_b = value.type) != null ? _b : "public";
|
|
1361
|
+
this.status = (_c = value.status) != null ? _c : "active";
|
|
1362
|
+
this.createdAt = (_d = value.createdAt) != null ? _d : (/* @__PURE__ */ new Date()).toISOString();
|
|
1363
|
+
}
|
|
1364
|
+
};
|
|
1365
|
+
|
|
1366
|
+
// src/repositories/file.repository.ts
|
|
1367
|
+
import { ObjectId as ObjectId9 } from "mongodb";
|
|
1368
|
+
function useFileRepo() {
|
|
1369
|
+
const db = useAtlas6.getDb();
|
|
1370
|
+
if (!db) {
|
|
1371
|
+
throw new InternalServerError7("Unable to connect to server.");
|
|
1372
|
+
}
|
|
1373
|
+
const collection = db.collection("files");
|
|
1374
|
+
function createFile(value, session) {
|
|
1375
|
+
return __async(this, null, function* () {
|
|
1376
|
+
try {
|
|
1377
|
+
value = new MFile(value);
|
|
1378
|
+
const res = yield collection.insertOne(value, { session });
|
|
1379
|
+
return res.insertedId.toString();
|
|
1380
|
+
} catch (error) {
|
|
1381
|
+
throw new InternalServerError7("Failed to create file.");
|
|
1382
|
+
}
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
function deleteFileById(_id, session) {
|
|
1386
|
+
return __async(this, null, function* () {
|
|
1387
|
+
try {
|
|
1388
|
+
_id = new ObjectId9(_id);
|
|
1389
|
+
} catch (error) {
|
|
1390
|
+
throw new BadRequestError7("Invalid file id.");
|
|
1391
|
+
}
|
|
1392
|
+
try {
|
|
1393
|
+
yield collection.deleteOne({ _id }, { session });
|
|
1394
|
+
return "File deleted successfully";
|
|
1395
|
+
} catch (error) {
|
|
1396
|
+
throw new InternalServerError7("Failed to delete file.");
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
function getAllDraftedFiles() {
|
|
1401
|
+
return __async(this, null, function* () {
|
|
1402
|
+
try {
|
|
1403
|
+
return yield collection.find({ $and: [{ status: "draft" }, { status: null }] }).toArray();
|
|
1404
|
+
} catch (error) {
|
|
1405
|
+
throw new InternalServerError7("Failed to get drafted files.");
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
return {
|
|
1410
|
+
createFile,
|
|
1411
|
+
deleteFileById,
|
|
1412
|
+
getAllDraftedFiles
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// src/services/user.service.ts
|
|
1417
|
+
function useUserService() {
|
|
1418
|
+
const {
|
|
1419
|
+
createUser: _createUser,
|
|
1420
|
+
getUserByEmail,
|
|
1421
|
+
getUserById: _getById,
|
|
1422
|
+
updateName: _updateName,
|
|
1423
|
+
updateBirthday: _updateBirthday,
|
|
1424
|
+
updateUserFieldById: _updateUserFieldById,
|
|
1425
|
+
getUsers: _getUsers
|
|
1426
|
+
} = useUserRepo();
|
|
1427
|
+
function getUserById(id) {
|
|
1428
|
+
return __async(this, null, function* () {
|
|
1429
|
+
try {
|
|
1430
|
+
return yield _getById(id);
|
|
1431
|
+
} catch (error) {
|
|
1432
|
+
throw new InternalServerError8();
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1435
|
+
}
|
|
1436
|
+
function getUsers() {
|
|
1437
|
+
return __async(this, arguments, function* ({
|
|
1438
|
+
search = "",
|
|
1439
|
+
page = 1,
|
|
1440
|
+
status = "",
|
|
1441
|
+
type = "",
|
|
1442
|
+
limit = 10
|
|
1443
|
+
} = {}) {
|
|
1444
|
+
try {
|
|
1445
|
+
return yield _getUsers({ search, page, status, type, limit });
|
|
1446
|
+
} catch (error) {
|
|
1447
|
+
throw error;
|
|
1448
|
+
}
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
function createUser(value) {
|
|
1452
|
+
return __async(this, null, function* () {
|
|
1453
|
+
var _a;
|
|
1454
|
+
const session = (_a = useAtlas7.getClient()) == null ? void 0 : _a.startSession();
|
|
1455
|
+
session == null ? void 0 : session.startTransaction();
|
|
1456
|
+
try {
|
|
1457
|
+
const _user = yield getUserByEmail(value.email);
|
|
1458
|
+
if (_user) {
|
|
1459
|
+
throw new BadRequestError8(`User already exists: ${value.email}.`);
|
|
1460
|
+
}
|
|
1461
|
+
const hashedPassword = yield hashPassword2(value.password);
|
|
1462
|
+
const user = {
|
|
1463
|
+
email: value.email,
|
|
1464
|
+
password: hashedPassword,
|
|
1465
|
+
prefix: value.prefix,
|
|
1466
|
+
firstName: value.firstName,
|
|
1467
|
+
middleName: value.middleName,
|
|
1468
|
+
lastName: value.lastName,
|
|
1469
|
+
suffix: value.suffix,
|
|
1470
|
+
type: value.type,
|
|
1471
|
+
roles: value.roles,
|
|
1472
|
+
status: "active",
|
|
1473
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1474
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1475
|
+
};
|
|
1476
|
+
const userId = yield _createUser(user, session);
|
|
1477
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
1478
|
+
return userId;
|
|
1479
|
+
} catch (error) {
|
|
1480
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
1481
|
+
throw error;
|
|
1482
|
+
} finally {
|
|
1483
|
+
session == null ? void 0 : session.endSession();
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
const { getById: _getVerificationById, updateStatusById: _updateStatusById } = useVerificationRepo();
|
|
1488
|
+
function createUserByInvite() {
|
|
1489
|
+
return __async(this, arguments, function* ({
|
|
1490
|
+
id = "",
|
|
1491
|
+
firstName = "",
|
|
1492
|
+
lastName = "",
|
|
1493
|
+
password = ""
|
|
1494
|
+
} = {}) {
|
|
1495
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1496
|
+
const session = (_a = useAtlas7.getClient()) == null ? void 0 : _a.startSession();
|
|
1497
|
+
session == null ? void 0 : session.startTransaction();
|
|
1498
|
+
try {
|
|
1499
|
+
const invitation = yield _getVerificationById(id);
|
|
1500
|
+
if (!invitation || !((_b = invitation.metadata) == null ? void 0 : _b.app) || !((_c = invitation.metadata) == null ? void 0 : _c.role)) {
|
|
1501
|
+
throw new BadRequestError8("Invalid invitation.");
|
|
1502
|
+
}
|
|
1503
|
+
if (invitation.status === "complete") {
|
|
1504
|
+
throw new BadRequestError8("Invitation already used.");
|
|
1505
|
+
}
|
|
1506
|
+
const expired = new Date(invitation.expireAt) < /* @__PURE__ */ new Date();
|
|
1507
|
+
if (invitation.status === "expired" || expired) {
|
|
1508
|
+
throw new BadRequestError8("Invitation expired.");
|
|
1509
|
+
}
|
|
1510
|
+
const email = invitation.email;
|
|
1511
|
+
const _user = yield getUserByEmail(invitation.email);
|
|
1512
|
+
if (_user) {
|
|
1513
|
+
throw new BadRequestError8(`User already exists: ${email}.`);
|
|
1514
|
+
}
|
|
1515
|
+
const hashedPassword = yield hashPassword2(password);
|
|
1516
|
+
const user = {
|
|
1517
|
+
email,
|
|
1518
|
+
password: hashedPassword,
|
|
1519
|
+
firstName,
|
|
1520
|
+
lastName,
|
|
1521
|
+
type: (_d = invitation.metadata) == null ? void 0 : _d.app,
|
|
1522
|
+
status: "active",
|
|
1523
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1524
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1525
|
+
roles: [
|
|
1526
|
+
{
|
|
1527
|
+
name: (_e = invitation.metadata) == null ? void 0 : _e.name,
|
|
1528
|
+
app: (_f = invitation.metadata) == null ? void 0 : _f.app,
|
|
1529
|
+
role: (_g = invitation.metadata) == null ? void 0 : _g.role
|
|
1530
|
+
}
|
|
1531
|
+
]
|
|
1532
|
+
};
|
|
1533
|
+
const userId = yield _createUser(user, session);
|
|
1534
|
+
yield _updateStatusById(id, "complete", session);
|
|
1535
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
1536
|
+
return userId;
|
|
1537
|
+
} catch (error) {
|
|
1538
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
1539
|
+
throw error;
|
|
1540
|
+
} finally {
|
|
1541
|
+
session == null ? void 0 : session.endSession();
|
|
1542
|
+
}
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
const { verify, getById, updateStatusById } = useVerificationService();
|
|
1546
|
+
function resetPassword(id, newPassword, passwordConfirmation) {
|
|
1547
|
+
return __async(this, null, function* () {
|
|
1548
|
+
try {
|
|
1549
|
+
yield verify(id);
|
|
1550
|
+
} catch (error) {
|
|
1551
|
+
throw error;
|
|
1552
|
+
}
|
|
1553
|
+
if (newPassword !== passwordConfirmation) {
|
|
1554
|
+
throw new BadRequestError8("Passwords do not match");
|
|
1555
|
+
}
|
|
1556
|
+
let hashedPassword;
|
|
1557
|
+
try {
|
|
1558
|
+
hashedPassword = yield hashPassword2(newPassword);
|
|
1559
|
+
} catch (error) {
|
|
1560
|
+
throw new InternalServerError8(`Error hashing password: ${error}`);
|
|
1561
|
+
}
|
|
1562
|
+
try {
|
|
1563
|
+
const otpDoc = yield getById(id);
|
|
1564
|
+
if (!otpDoc) {
|
|
1565
|
+
throw new NotFoundError3("OTP not found");
|
|
1566
|
+
}
|
|
1567
|
+
if (otpDoc.status === "used") {
|
|
1568
|
+
throw new BadRequestError8("Invalid OTP, already used.");
|
|
1569
|
+
}
|
|
1570
|
+
yield updateStatusById(id, "used");
|
|
1571
|
+
return "Updated password successfully";
|
|
1572
|
+
} catch (error) {
|
|
1573
|
+
throw error;
|
|
1574
|
+
}
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
function updateName(_id, firstName, lastName) {
|
|
1578
|
+
return __async(this, null, function* () {
|
|
1579
|
+
var _a;
|
|
1580
|
+
if (!_id) {
|
|
1581
|
+
throw new BadRequestError8("Invalid user ID");
|
|
1582
|
+
}
|
|
1583
|
+
if (!firstName) {
|
|
1584
|
+
throw new BadRequestError8("Invalid firstName");
|
|
1585
|
+
}
|
|
1586
|
+
if (!lastName) {
|
|
1587
|
+
throw new BadRequestError8("Invalid lastName");
|
|
1588
|
+
}
|
|
1589
|
+
const session = (_a = useAtlas7.getClient()) == null ? void 0 : _a.startSession();
|
|
1590
|
+
session == null ? void 0 : session.startTransaction();
|
|
1591
|
+
try {
|
|
1592
|
+
yield _updateName({ _id, firstName, lastName }, session);
|
|
1593
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
1594
|
+
return "Successfully updated name.";
|
|
1595
|
+
} catch (error) {
|
|
1596
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
1597
|
+
throw error;
|
|
1598
|
+
} finally {
|
|
1599
|
+
session == null ? void 0 : session.endSession();
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
function updateBirthday(_id, month, day, year) {
|
|
1604
|
+
return __async(this, null, function* () {
|
|
1605
|
+
if (!_id) {
|
|
1606
|
+
throw new BadRequestError8("Invalid user ID");
|
|
1607
|
+
}
|
|
1608
|
+
if (!month) {
|
|
1609
|
+
throw new BadRequestError8("Invalid birth month.");
|
|
1610
|
+
}
|
|
1611
|
+
if (!day) {
|
|
1612
|
+
throw new BadRequestError8("Invalid birthday.");
|
|
1613
|
+
}
|
|
1614
|
+
if (!year) {
|
|
1615
|
+
throw new BadRequestError8("Invalid birth year.");
|
|
1616
|
+
}
|
|
1617
|
+
try {
|
|
1618
|
+
yield _updateBirthday({ _id, month, day, year });
|
|
1619
|
+
return "Successfully updated birthday.";
|
|
1620
|
+
} catch (error) {
|
|
1621
|
+
throw error;
|
|
1622
|
+
}
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
function updateUserFieldById() {
|
|
1626
|
+
return __async(this, arguments, function* ({ _id, field, value } = {}) {
|
|
1627
|
+
try {
|
|
1628
|
+
return yield _updateUserFieldById({ _id, field, value });
|
|
1629
|
+
} catch (error) {
|
|
1630
|
+
throw error;
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
const { createFile: _createFile, deleteFileById } = useFileRepo();
|
|
1635
|
+
const s3 = new useS32({
|
|
1636
|
+
accessKeyId: SPACES_ACCESS_KEY,
|
|
1637
|
+
secretAccessKey: SPACES_SECRET_KEY,
|
|
1638
|
+
endpoint: SPACES_ENDPOINT,
|
|
1639
|
+
region: SPACES_REGION,
|
|
1640
|
+
bucket: SPACES_BUCKET
|
|
1641
|
+
});
|
|
1642
|
+
function updateUserProfile() {
|
|
1643
|
+
return __async(this, arguments, function* ({ file, user, previousProfile } = {}) {
|
|
1644
|
+
var _a;
|
|
1645
|
+
const session = (_a = useAtlas7.getClient()) == null ? void 0 : _a.startSession();
|
|
1646
|
+
session == null ? void 0 : session.startTransaction();
|
|
1647
|
+
const _file = {
|
|
1648
|
+
name: file.originalname,
|
|
1649
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1650
|
+
};
|
|
1651
|
+
try {
|
|
1652
|
+
const id = yield _createFile(_file, session);
|
|
1653
|
+
yield s3.uploadObject({
|
|
1654
|
+
key: id,
|
|
1655
|
+
body: file.buffer,
|
|
1656
|
+
contentType: file.mimetype
|
|
1657
|
+
});
|
|
1658
|
+
if (previousProfile) {
|
|
1659
|
+
yield deleteFileById(previousProfile, session);
|
|
1660
|
+
yield s3.deleteObject(previousProfile);
|
|
1661
|
+
}
|
|
1662
|
+
yield _updateUserFieldById(
|
|
1663
|
+
{ _id: user, field: "profile", value: id },
|
|
1664
|
+
session
|
|
1665
|
+
);
|
|
1666
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
1667
|
+
return id;
|
|
1668
|
+
} catch (error) {
|
|
1669
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
1670
|
+
throw error;
|
|
1671
|
+
} finally {
|
|
1672
|
+
session == null ? void 0 : session.endSession();
|
|
1673
|
+
}
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
return {
|
|
1677
|
+
getUserById,
|
|
1678
|
+
getUsers,
|
|
1679
|
+
createUser,
|
|
1680
|
+
resetPassword,
|
|
1681
|
+
updateName,
|
|
1682
|
+
updateBirthday,
|
|
1683
|
+
updateUserFieldById,
|
|
1684
|
+
updateUserProfile,
|
|
1685
|
+
createUserByInvite
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
// src/controllers/user.controller.ts
|
|
1690
|
+
import {
|
|
1691
|
+
AppError as AppError3,
|
|
1692
|
+
BadRequestError as BadRequestError9,
|
|
1693
|
+
InternalServerError as InternalServerError9
|
|
1694
|
+
} from "@goweekdays/utils";
|
|
1695
|
+
import Joi2 from "joi";
|
|
1696
|
+
function useUserController() {
|
|
1697
|
+
const {
|
|
1698
|
+
getUserById: _getUserById,
|
|
1699
|
+
updateName: _updateName,
|
|
1700
|
+
updateBirthday: _updateBirthday,
|
|
1701
|
+
updateUserFieldById: _updateUserFieldById,
|
|
1702
|
+
updateUserProfile: _updateUserProfile,
|
|
1703
|
+
getUsers: _getUsers,
|
|
1704
|
+
createUserByInvite: _createUserByInvite
|
|
1705
|
+
} = useUserService();
|
|
1706
|
+
function getUsers(req, res, next) {
|
|
1707
|
+
return __async(this, null, function* () {
|
|
1708
|
+
var _a, _b, _c;
|
|
1709
|
+
const status = (_a = req.query.status) != null ? _a : "";
|
|
1710
|
+
const search = (_b = req.query.search) != null ? _b : "";
|
|
1711
|
+
const page = (_c = Number(req.query.page)) != null ? _c : 1;
|
|
1712
|
+
const validation = Joi2.object({
|
|
1713
|
+
status: Joi2.string().required(),
|
|
1714
|
+
search: Joi2.string().optional().allow("", null),
|
|
1715
|
+
page: Joi2.number().required()
|
|
1716
|
+
});
|
|
1717
|
+
const { error } = validation.validate({ status, search, page });
|
|
1718
|
+
if (error) {
|
|
1719
|
+
next(new BadRequestError9(error.message));
|
|
1720
|
+
}
|
|
1721
|
+
try {
|
|
1722
|
+
const items = yield _getUsers({ status, search, page });
|
|
1723
|
+
res.json(items);
|
|
1724
|
+
return;
|
|
1725
|
+
} catch (error2) {
|
|
1726
|
+
next(error2);
|
|
1727
|
+
}
|
|
1728
|
+
});
|
|
1729
|
+
}
|
|
1730
|
+
function getUserById(req, res, next) {
|
|
1731
|
+
return __async(this, null, function* () {
|
|
1732
|
+
const id = req.params.id || "";
|
|
1733
|
+
const validation = Joi2.string().hex().validate(id);
|
|
1734
|
+
if (validation.error) {
|
|
1735
|
+
throw new BadRequestError9("Invalid id.");
|
|
1736
|
+
}
|
|
1737
|
+
try {
|
|
1738
|
+
const user = yield _getUserById(id);
|
|
1739
|
+
if (!user) {
|
|
1740
|
+
throw new BadRequestError9("User not found.");
|
|
1741
|
+
}
|
|
1742
|
+
res.json(user);
|
|
1743
|
+
} catch (error) {
|
|
1744
|
+
next(error);
|
|
1745
|
+
}
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
function updateName(req, res, next) {
|
|
1749
|
+
return __async(this, null, function* () {
|
|
1750
|
+
var _a, _b, _c;
|
|
1751
|
+
const id = (_a = req.headers.user) != null ? _a : "";
|
|
1752
|
+
const firstName = (_b = req.body.firstName) != null ? _b : "";
|
|
1753
|
+
const lastName = (_c = req.body.lastName) != null ? _c : "";
|
|
1754
|
+
const validation = Joi2.object({
|
|
1755
|
+
firstName: Joi2.string().required(),
|
|
1756
|
+
lastName: Joi2.string().required()
|
|
1757
|
+
});
|
|
1758
|
+
const { error } = validation.validate({ firstName, lastName });
|
|
1759
|
+
if (error) {
|
|
1760
|
+
next(new BadRequestError9(error.message));
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
try {
|
|
1764
|
+
const message = yield _updateName(id, firstName, lastName);
|
|
1765
|
+
res.json({ message });
|
|
1766
|
+
return;
|
|
1767
|
+
} catch (error2) {
|
|
1768
|
+
next(error2);
|
|
1769
|
+
}
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
function updateBirthday(req, res, next) {
|
|
1773
|
+
return __async(this, null, function* () {
|
|
1774
|
+
var _a, _b, _c, _d;
|
|
1775
|
+
const id = (_a = req.headers.user) != null ? _a : "";
|
|
1776
|
+
const month = (_b = req.body.month) != null ? _b : "";
|
|
1777
|
+
const day = (_c = req.body.day) != null ? _c : 0;
|
|
1778
|
+
const year = (_d = req.body.year) != null ? _d : 0;
|
|
1779
|
+
const validation = Joi2.object({
|
|
1780
|
+
month: Joi2.string().required(),
|
|
1781
|
+
day: Joi2.number().integer().min(1).max(31).required(),
|
|
1782
|
+
year: Joi2.number().integer().min(1900).max((/* @__PURE__ */ new Date()).getFullYear()).required()
|
|
1783
|
+
});
|
|
1784
|
+
const { error } = validation.validate({ month, day, year });
|
|
1785
|
+
if (error) {
|
|
1786
|
+
next(new BadRequestError9(error.message));
|
|
1787
|
+
return;
|
|
1788
|
+
}
|
|
1789
|
+
try {
|
|
1790
|
+
const message = yield _updateBirthday(id, month, day, year);
|
|
1791
|
+
res.json({ message });
|
|
1792
|
+
return;
|
|
1793
|
+
} catch (error2) {
|
|
1794
|
+
next(error2);
|
|
1795
|
+
}
|
|
1796
|
+
});
|
|
1797
|
+
}
|
|
1798
|
+
function updateUserFieldById(req, res, next) {
|
|
1799
|
+
return __async(this, null, function* () {
|
|
1800
|
+
const _id = req.params.id;
|
|
1801
|
+
const { field, value } = req.body;
|
|
1802
|
+
const validation = Joi2.object({
|
|
1803
|
+
_id: Joi2.string().hex().required(),
|
|
1804
|
+
field: Joi2.string().valid("gender", "email", "contact", "profile").required(),
|
|
1805
|
+
value: Joi2.alternatives().conditional("field", {
|
|
1806
|
+
is: "email",
|
|
1807
|
+
then: Joi2.string().email().required(),
|
|
1808
|
+
otherwise: Joi2.string().required()
|
|
1809
|
+
})
|
|
1810
|
+
});
|
|
1811
|
+
const { error } = validation.validate({ _id, field, value });
|
|
1812
|
+
if (error) {
|
|
1813
|
+
next(new BadRequestError9(error.message));
|
|
1814
|
+
return;
|
|
1815
|
+
}
|
|
1816
|
+
try {
|
|
1817
|
+
const message = yield _updateUserFieldById({ _id, field, value });
|
|
1818
|
+
res.json({ message });
|
|
1819
|
+
} catch (error2) {
|
|
1820
|
+
next(error2);
|
|
1821
|
+
}
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
function updateUserProfile(req, res, next) {
|
|
1825
|
+
return __async(this, null, function* () {
|
|
1826
|
+
var _a, _b;
|
|
1827
|
+
if (!req.file) {
|
|
1828
|
+
res.status(400).send("File is required!");
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
const previousProfile = (_a = req.body.previousProfile) != null ? _a : "";
|
|
1832
|
+
const validation = Joi2.object({
|
|
1833
|
+
previousProfile: Joi2.string().hex().optional().allow("", null)
|
|
1834
|
+
});
|
|
1835
|
+
const { error } = validation.validate({ previousProfile });
|
|
1836
|
+
if (error) {
|
|
1837
|
+
next(new BadRequestError9(error.message));
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
const user = (_b = req.headers["user"]) != null ? _b : "";
|
|
1841
|
+
try {
|
|
1842
|
+
yield _updateUserProfile({
|
|
1843
|
+
file: req.file,
|
|
1844
|
+
user,
|
|
1845
|
+
previousProfile
|
|
1846
|
+
});
|
|
1847
|
+
res.json({ message: "Successfully updated profile picture." });
|
|
1848
|
+
return;
|
|
1849
|
+
} catch (error2) {
|
|
1850
|
+
if (error2 instanceof AppError3) {
|
|
1851
|
+
next(error2);
|
|
1852
|
+
} else {
|
|
1853
|
+
next(new InternalServerError9(error2));
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
});
|
|
1857
|
+
}
|
|
1858
|
+
function createUserByInvite(req, res, next) {
|
|
1859
|
+
return __async(this, null, function* () {
|
|
1860
|
+
var _a, _b, _c, _d;
|
|
1861
|
+
const firstName = (_a = req.body.firstName) != null ? _a : "";
|
|
1862
|
+
const lastName = (_b = req.body.lastName) != null ? _b : "";
|
|
1863
|
+
const password = (_c = req.body.password) != null ? _c : "";
|
|
1864
|
+
const id = (_d = req.params.id) != null ? _d : "";
|
|
1865
|
+
const validation = Joi2.object({
|
|
1866
|
+
firstName: Joi2.string().required(),
|
|
1867
|
+
lastName: Joi2.string().required(),
|
|
1868
|
+
password: Joi2.string().required(),
|
|
1869
|
+
id: Joi2.string().hex().required()
|
|
1870
|
+
});
|
|
1871
|
+
const { error } = validation.validate({
|
|
1872
|
+
firstName,
|
|
1873
|
+
lastName,
|
|
1874
|
+
password,
|
|
1875
|
+
id
|
|
1876
|
+
});
|
|
1877
|
+
if (error) {
|
|
1878
|
+
next(new BadRequestError9(error.message));
|
|
1879
|
+
return;
|
|
1880
|
+
}
|
|
1881
|
+
try {
|
|
1882
|
+
yield _createUserByInvite({ firstName, lastName, password, id });
|
|
1883
|
+
res.json({ message: "Successfully created account." });
|
|
1884
|
+
return;
|
|
1885
|
+
} catch (error2) {
|
|
1886
|
+
next(error2);
|
|
1887
|
+
}
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
return {
|
|
1891
|
+
getUsers,
|
|
1892
|
+
getUserById,
|
|
1893
|
+
updateName,
|
|
1894
|
+
updateBirthday,
|
|
1895
|
+
updateUserFieldById,
|
|
1896
|
+
updateUserProfile,
|
|
1897
|
+
createUserByInvite
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
// src/services/auth.service.ts
|
|
1902
|
+
import {
|
|
1903
|
+
AppError as AppError4,
|
|
1904
|
+
BadRequestError as BadRequestError10,
|
|
1905
|
+
comparePassword as comparePassword2,
|
|
1906
|
+
generateToken as generateToken2,
|
|
1907
|
+
InternalServerError as InternalServerError10,
|
|
1908
|
+
NotFoundError as NotFoundError4
|
|
1909
|
+
} from "@goweekdays/utils";
|
|
1910
|
+
import jwt3 from "jsonwebtoken";
|
|
1911
|
+
function useAuthService() {
|
|
1912
|
+
const expiresIn = "1m";
|
|
1913
|
+
function login() {
|
|
1914
|
+
return __async(this, arguments, function* ({ email, password } = {}) {
|
|
1915
|
+
var _a;
|
|
1916
|
+
if (!email) {
|
|
1917
|
+
throw new BadRequestError10("Email is required");
|
|
1918
|
+
}
|
|
1919
|
+
if (!password) {
|
|
1920
|
+
throw new BadRequestError10("Password is required");
|
|
1921
|
+
}
|
|
1922
|
+
let _user;
|
|
1923
|
+
try {
|
|
1924
|
+
_user = yield useUserRepo().getUserByEmail(email);
|
|
1925
|
+
} catch (error) {
|
|
1926
|
+
if (error instanceof AppError4) {
|
|
1927
|
+
throw error;
|
|
1928
|
+
} else {
|
|
1929
|
+
throw new InternalServerError10(`${error}`);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
if (!_user) {
|
|
1933
|
+
throw new NotFoundError4(
|
|
1934
|
+
"Invalid user email. Please check your email and try again."
|
|
1935
|
+
);
|
|
1936
|
+
}
|
|
1937
|
+
if (_user.status === "suspended") {
|
|
1938
|
+
throw new BadRequestError10(
|
|
1939
|
+
"Your account is currently suspended. Please contact support for assistance."
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1942
|
+
const isPasswordValid = yield comparePassword2(password, _user.password);
|
|
1943
|
+
if (!isPasswordValid) {
|
|
1944
|
+
throw new BadRequestError10("Invalid password");
|
|
1945
|
+
}
|
|
1946
|
+
const metadata = { user: _user._id };
|
|
1947
|
+
let refreshToken2;
|
|
1948
|
+
try {
|
|
1949
|
+
refreshToken2 = generateToken2({
|
|
1950
|
+
secret: REFRESH_TOKEN_SECRET,
|
|
1951
|
+
metadata,
|
|
1952
|
+
options: { expiresIn: "7d" }
|
|
1953
|
+
});
|
|
1954
|
+
} catch (error) {
|
|
1955
|
+
throw new BadRequestError10("Error generating refresh token");
|
|
1956
|
+
}
|
|
1957
|
+
let accessToken;
|
|
1958
|
+
try {
|
|
1959
|
+
accessToken = generateToken2({
|
|
1960
|
+
secret: ACCESS_TOKEN_SECRET,
|
|
1961
|
+
metadata,
|
|
1962
|
+
options: { expiresIn }
|
|
1963
|
+
});
|
|
1964
|
+
} catch (error) {
|
|
1965
|
+
throw new BadRequestError10("Error generating access token");
|
|
1966
|
+
}
|
|
1967
|
+
const user = (_a = _user._id) != null ? _a : "";
|
|
1968
|
+
try {
|
|
1969
|
+
yield useTokenRepo().createToken({ token: refreshToken2, user });
|
|
1970
|
+
} catch (error) {
|
|
1971
|
+
throw new BadRequestError10("Error creating refresh token");
|
|
1972
|
+
}
|
|
1973
|
+
return { accessToken, refreshToken: refreshToken2, id: _user._id };
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
function refreshToken(token) {
|
|
1977
|
+
return __async(this, null, function* () {
|
|
1978
|
+
let decoded;
|
|
1979
|
+
try {
|
|
1980
|
+
decoded = yield jwt3.verify(token, REFRESH_TOKEN_SECRET);
|
|
1981
|
+
} catch (error) {
|
|
1982
|
+
throw new BadRequestError10("Invalid refresh token");
|
|
1983
|
+
}
|
|
1984
|
+
let _token;
|
|
1985
|
+
try {
|
|
1986
|
+
_token = yield useTokenRepo().getToken(token);
|
|
1987
|
+
if (!_token) {
|
|
1988
|
+
throw new NotFoundError4("Invalid token");
|
|
1989
|
+
}
|
|
1990
|
+
} catch (error) {
|
|
1991
|
+
if (error instanceof AppError4) {
|
|
1992
|
+
throw error;
|
|
1993
|
+
} else {
|
|
1994
|
+
throw new InternalServerError10(`${error}`);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
let accessToken;
|
|
1998
|
+
try {
|
|
1999
|
+
accessToken = generateToken2({
|
|
2000
|
+
secret: ACCESS_TOKEN_SECRET,
|
|
2001
|
+
metadata: { user: decoded.user },
|
|
2002
|
+
options: { expiresIn }
|
|
2003
|
+
});
|
|
2004
|
+
} catch (error) {
|
|
2005
|
+
throw new BadRequestError10("Error generating access token");
|
|
2006
|
+
}
|
|
2007
|
+
return accessToken;
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
function logout(token) {
|
|
2011
|
+
return __async(this, null, function* () {
|
|
2012
|
+
let _token;
|
|
2013
|
+
try {
|
|
2014
|
+
_token = yield useTokenRepo().getToken(token);
|
|
2015
|
+
if (!_token) {
|
|
2016
|
+
throw new NotFoundError4("Invalid token");
|
|
2017
|
+
}
|
|
2018
|
+
} catch (error) {
|
|
2019
|
+
if (error instanceof AppError4) {
|
|
2020
|
+
throw error;
|
|
2021
|
+
} else {
|
|
2022
|
+
throw new InternalServerError10(`${error}`);
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
try {
|
|
2026
|
+
yield useTokenRepo().deleteToken(token);
|
|
2027
|
+
} catch (error) {
|
|
2028
|
+
throw new InternalServerError10("Error deleting token");
|
|
2029
|
+
}
|
|
2030
|
+
return "Logged out successfully";
|
|
2031
|
+
});
|
|
2032
|
+
}
|
|
2033
|
+
return {
|
|
2034
|
+
login,
|
|
2035
|
+
refreshToken,
|
|
2036
|
+
logout
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
// src/controllers/auth.controller.ts
|
|
2041
|
+
import Joi3 from "joi";
|
|
2042
|
+
import {
|
|
2043
|
+
AppError as AppError5,
|
|
2044
|
+
BadRequestError as BadRequestError11,
|
|
2045
|
+
InternalServerError as InternalServerError11
|
|
2046
|
+
} from "@goweekdays/utils";
|
|
2047
|
+
function useAuthController() {
|
|
2048
|
+
function login(req, res, next) {
|
|
2049
|
+
return __async(this, null, function* () {
|
|
2050
|
+
const email = req.body.email;
|
|
2051
|
+
const password = req.body.password;
|
|
2052
|
+
const validation = Joi3.object({
|
|
2053
|
+
email: Joi3.string().email().required(),
|
|
2054
|
+
password: Joi3.string().required()
|
|
2055
|
+
});
|
|
2056
|
+
const { error } = validation.validate({ email, password });
|
|
2057
|
+
if (error) {
|
|
2058
|
+
next(new BadRequestError11(error.message));
|
|
2059
|
+
}
|
|
2060
|
+
try {
|
|
2061
|
+
const token = yield useAuthService().login({ email, password });
|
|
2062
|
+
res.json(token);
|
|
2063
|
+
} catch (error2) {
|
|
2064
|
+
if (error2 instanceof AppError5) {
|
|
2065
|
+
next(error2);
|
|
2066
|
+
} else {
|
|
2067
|
+
next(new InternalServerError11("An unexpected error occurred"));
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
function refreshToken(req, res, next) {
|
|
2073
|
+
return __async(this, null, function* () {
|
|
2074
|
+
const refreshToken2 = req.body.token;
|
|
2075
|
+
if (!refreshToken2) {
|
|
2076
|
+
next(new BadRequestError11("Refresh token is required"));
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
try {
|
|
2080
|
+
const newRefreshToken = yield useAuthService().refreshToken(refreshToken2);
|
|
2081
|
+
res.json({ token: newRefreshToken });
|
|
2082
|
+
} catch (error) {
|
|
2083
|
+
if (error instanceof AppError5) {
|
|
2084
|
+
next(error);
|
|
2085
|
+
} else {
|
|
2086
|
+
next(new InternalServerError11("An unexpected error occurred"));
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
function logout(req, res, next) {
|
|
2092
|
+
return __async(this, null, function* () {
|
|
2093
|
+
const token = req.params.id || "";
|
|
2094
|
+
if (!token) {
|
|
2095
|
+
next(new BadRequestError11("Token is required"));
|
|
2096
|
+
return;
|
|
2097
|
+
}
|
|
2098
|
+
try {
|
|
2099
|
+
yield useAuthService().logout(token);
|
|
2100
|
+
res.json({ message: "Logged out successfully" });
|
|
2101
|
+
} catch (error) {
|
|
2102
|
+
if (error instanceof AppError5) {
|
|
2103
|
+
next(error);
|
|
2104
|
+
} else {
|
|
2105
|
+
next(new InternalServerError11("An unexpected error occurred"));
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
}
|
|
2110
|
+
function resetPassword(req, res, next) {
|
|
2111
|
+
return __async(this, null, function* () {
|
|
2112
|
+
const otp = req.body.otp || "";
|
|
2113
|
+
const newPassword = req.body.newPassword || "";
|
|
2114
|
+
const passwordConfirmation = req.body.passwordConfirmation || "";
|
|
2115
|
+
const validation = Joi3.object({
|
|
2116
|
+
otp: Joi3.string().hex().required(),
|
|
2117
|
+
newPassword: Joi3.string().required().min(8),
|
|
2118
|
+
passwordConfirmation: Joi3.string().required().min(8)
|
|
2119
|
+
});
|
|
2120
|
+
const { error } = validation.validate({
|
|
2121
|
+
otp,
|
|
2122
|
+
newPassword,
|
|
2123
|
+
passwordConfirmation
|
|
2124
|
+
});
|
|
2125
|
+
if (error) {
|
|
2126
|
+
next(new BadRequestError11(error.message));
|
|
2127
|
+
return;
|
|
2128
|
+
}
|
|
2129
|
+
try {
|
|
2130
|
+
const message = yield useUserService().resetPassword(
|
|
2131
|
+
otp,
|
|
2132
|
+
newPassword,
|
|
2133
|
+
passwordConfirmation
|
|
2134
|
+
);
|
|
2135
|
+
res.json({ message });
|
|
2136
|
+
return;
|
|
2137
|
+
} catch (error2) {
|
|
2138
|
+
next(error2);
|
|
2139
|
+
}
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
2142
|
+
return {
|
|
2143
|
+
login,
|
|
2144
|
+
refreshToken,
|
|
2145
|
+
logout,
|
|
2146
|
+
resetPassword
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
// src/models/role.model.ts
|
|
2151
|
+
import { ObjectId as ObjectId10 } from "mongodb";
|
|
2152
|
+
var MRole = class {
|
|
2153
|
+
constructor(value) {
|
|
2154
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2155
|
+
if (typeof value._id === "string") {
|
|
2156
|
+
try {
|
|
2157
|
+
value._id = new ObjectId10(value._id);
|
|
2158
|
+
} catch (error) {
|
|
2159
|
+
throw new Error("Invalid _id.");
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
this._id = (_a = value._id) != null ? _a : new ObjectId10();
|
|
2163
|
+
this.name = (_b = value.name) != null ? _b : "";
|
|
2164
|
+
this.permissions = (_c = value.permissions) != null ? _c : [];
|
|
2165
|
+
this.type = value.type ? value.type : "account";
|
|
2166
|
+
this.status = (_d = value.status) != null ? _d : "active";
|
|
2167
|
+
if (value.createdBy) {
|
|
2168
|
+
try {
|
|
2169
|
+
value.createdBy = new ObjectId10(value.createdBy);
|
|
2170
|
+
} catch (error) {
|
|
2171
|
+
throw new Error("Invalid createdBy.");
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
this.createdBy = (_e = value.createdBy) != null ? _e : "";
|
|
2175
|
+
this.createdAt = (_f = value.createdAt) != null ? _f : (/* @__PURE__ */ new Date()).toISOString();
|
|
2176
|
+
this.updatedAt = (_g = value.updatedAt) != null ? _g : "";
|
|
2177
|
+
this.deletedAt = (_h = value.deletedAt) != null ? _h : "";
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
|
|
2181
|
+
// src/repositories/role.repository.ts
|
|
2182
|
+
import {
|
|
2183
|
+
BadRequestError as BadRequestError12,
|
|
2184
|
+
InternalServerError as InternalServerError12,
|
|
2185
|
+
useAtlas as useAtlas8,
|
|
2186
|
+
paginate as paginate4,
|
|
2187
|
+
logger as logger5
|
|
2188
|
+
} from "@goweekdays/utils";
|
|
2189
|
+
import { ObjectId as ObjectId11 } from "mongodb";
|
|
2190
|
+
function useRoleRepo() {
|
|
2191
|
+
const db = useAtlas8.getDb();
|
|
2192
|
+
if (!db) {
|
|
2193
|
+
throw new InternalServerError12("Unable to connect to server.");
|
|
2194
|
+
}
|
|
2195
|
+
const collection = db.collection("roles");
|
|
2196
|
+
function createIndex() {
|
|
2197
|
+
return __async(this, null, function* () {
|
|
2198
|
+
try {
|
|
2199
|
+
yield collection.createIndex({ name: 1 });
|
|
2200
|
+
yield collection.createIndex({ type: 1 });
|
|
2201
|
+
yield collection.createIndex({ status: 1 });
|
|
2202
|
+
} catch (error) {
|
|
2203
|
+
throw new InternalServerError12("Failed to create index on role.");
|
|
2204
|
+
}
|
|
2205
|
+
});
|
|
2206
|
+
}
|
|
2207
|
+
function createTextIndex() {
|
|
2208
|
+
return __async(this, null, function* () {
|
|
2209
|
+
try {
|
|
2210
|
+
yield collection.createIndex({ name: "text" });
|
|
2211
|
+
} catch (error) {
|
|
2212
|
+
throw new InternalServerError12("Failed to create text index on role.");
|
|
2213
|
+
}
|
|
2214
|
+
});
|
|
2215
|
+
}
|
|
2216
|
+
function createUniqueIndex() {
|
|
2217
|
+
return __async(this, null, function* () {
|
|
2218
|
+
try {
|
|
2219
|
+
yield collection.createIndex({ name: 1, type: 1 }, { unique: true });
|
|
2220
|
+
} catch (error) {
|
|
2221
|
+
throw new InternalServerError12("Failed to create unique index on role.");
|
|
2222
|
+
}
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
function addRole(value, session) {
|
|
2226
|
+
return __async(this, null, function* () {
|
|
2227
|
+
value = new MRole(value);
|
|
2228
|
+
try {
|
|
2229
|
+
const res = yield collection.insertOne(value, { session });
|
|
2230
|
+
return res.insertedId;
|
|
2231
|
+
} catch (error) {
|
|
2232
|
+
logger5.log({ level: "error", message: `${error}` });
|
|
2233
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
2234
|
+
if (isDuplicated) {
|
|
2235
|
+
throw new BadRequestError12("Item role already exists");
|
|
2236
|
+
}
|
|
2237
|
+
throw new InternalServerError12("Failed to create role.");
|
|
2238
|
+
}
|
|
2239
|
+
});
|
|
2240
|
+
}
|
|
2241
|
+
function getRoleByUserId(value) {
|
|
2242
|
+
return __async(this, null, function* () {
|
|
2243
|
+
try {
|
|
2244
|
+
value = new ObjectId11(value);
|
|
2245
|
+
} catch (error) {
|
|
2246
|
+
throw new BadRequestError12("Invalid user ID.");
|
|
2247
|
+
}
|
|
2248
|
+
try {
|
|
2249
|
+
return yield collection.findOne({ user: value });
|
|
2250
|
+
} catch (error) {
|
|
2251
|
+
throw new InternalServerError12("Failed to retrieve role by user ID.");
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
function getRoleById(_id) {
|
|
2256
|
+
return __async(this, null, function* () {
|
|
2257
|
+
try {
|
|
2258
|
+
_id = new ObjectId11(_id);
|
|
2259
|
+
} catch (error) {
|
|
2260
|
+
throw new BadRequestError12("Invalid ID.");
|
|
2261
|
+
}
|
|
2262
|
+
try {
|
|
2263
|
+
return yield collection.findOne({ _id });
|
|
2264
|
+
} catch (error) {
|
|
2265
|
+
throw new InternalServerError12("Failed to retrieve role by ID.");
|
|
2266
|
+
}
|
|
2267
|
+
});
|
|
2268
|
+
}
|
|
2269
|
+
function getRoleByName(name) {
|
|
2270
|
+
return __async(this, null, function* () {
|
|
2271
|
+
if (!name) {
|
|
2272
|
+
throw new BadRequestError12("Role name is required.");
|
|
2273
|
+
}
|
|
2274
|
+
try {
|
|
2275
|
+
return yield collection.findOne({ name });
|
|
2276
|
+
} catch (error) {
|
|
2277
|
+
throw new InternalServerError12("Failed to retrieve role by name.");
|
|
2278
|
+
}
|
|
2279
|
+
});
|
|
2280
|
+
}
|
|
2281
|
+
function getRoles() {
|
|
2282
|
+
return __async(this, arguments, function* ({
|
|
2283
|
+
search = "",
|
|
2284
|
+
page = 1,
|
|
2285
|
+
limit = 10,
|
|
2286
|
+
sort = {},
|
|
2287
|
+
type = ""
|
|
2288
|
+
} = {}) {
|
|
2289
|
+
page = page > 0 ? page - 1 : 0;
|
|
2290
|
+
const query = { status: "active" };
|
|
2291
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
2292
|
+
if (search) {
|
|
2293
|
+
query.$text = { $search: search };
|
|
2294
|
+
}
|
|
2295
|
+
if (type) {
|
|
2296
|
+
query.type = type;
|
|
2297
|
+
}
|
|
2298
|
+
try {
|
|
2299
|
+
const items = yield collection.aggregate([
|
|
2300
|
+
{ $match: query },
|
|
2301
|
+
{ $sort: sort },
|
|
2302
|
+
{ $skip: page * limit },
|
|
2303
|
+
{ $limit: limit }
|
|
2304
|
+
]).toArray();
|
|
2305
|
+
const length = yield collection.countDocuments(query);
|
|
2306
|
+
return paginate4(items, page, limit, length);
|
|
2307
|
+
} catch (error) {
|
|
2308
|
+
logger5.log({ level: "error", message: `${error}` });
|
|
2309
|
+
throw error;
|
|
2310
|
+
}
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
function updateRole(_id, value, session) {
|
|
2314
|
+
return __async(this, null, function* () {
|
|
2315
|
+
if (!_id) {
|
|
2316
|
+
throw new BadRequestError12("Role ID is required.");
|
|
2317
|
+
}
|
|
2318
|
+
try {
|
|
2319
|
+
_id = new ObjectId11(_id);
|
|
2320
|
+
} catch (error) {
|
|
2321
|
+
throw new BadRequestError12("Invalid role ID.");
|
|
2322
|
+
}
|
|
2323
|
+
if (!value.name) {
|
|
2324
|
+
delete value.name;
|
|
2325
|
+
}
|
|
2326
|
+
if (!value.permissions) {
|
|
2327
|
+
delete value.permissions;
|
|
2328
|
+
}
|
|
2329
|
+
if (value.name || value.permissions) {
|
|
2330
|
+
try {
|
|
2331
|
+
yield collection.updateOne({ _id }, { $set: value }, { session });
|
|
2332
|
+
return "Successfully updated role.";
|
|
2333
|
+
} catch (error) {
|
|
2334
|
+
throw new InternalServerError12("Failed to update role.");
|
|
2335
|
+
}
|
|
2336
|
+
} else {
|
|
2337
|
+
throw new BadRequestError12("No fields to update.");
|
|
2338
|
+
}
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
function deleteRole(_id, session) {
|
|
2342
|
+
return __async(this, null, function* () {
|
|
2343
|
+
try {
|
|
2344
|
+
_id = new ObjectId11(_id);
|
|
2345
|
+
} catch (error) {
|
|
2346
|
+
throw new BadRequestError12("Invalid ID.");
|
|
2347
|
+
}
|
|
2348
|
+
try {
|
|
2349
|
+
yield collection.deleteOne(
|
|
2350
|
+
{ _id },
|
|
2351
|
+
{
|
|
2352
|
+
session
|
|
2353
|
+
}
|
|
2354
|
+
);
|
|
2355
|
+
return "Successfully deleted role.";
|
|
2356
|
+
} catch (error) {
|
|
2357
|
+
throw new InternalServerError12("Failed to delete role.");
|
|
2358
|
+
}
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
return {
|
|
2362
|
+
createIndex,
|
|
2363
|
+
createTextIndex,
|
|
2364
|
+
createUniqueIndex,
|
|
2365
|
+
addRole,
|
|
2366
|
+
getRoles,
|
|
2367
|
+
getRoleByUserId,
|
|
2368
|
+
getRoleById,
|
|
2369
|
+
getRoleByName,
|
|
2370
|
+
updateRole,
|
|
2371
|
+
deleteRole
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
// src/services/file.service.ts
|
|
2376
|
+
import { logger as logger6, useS3 as useS33, useAtlas as useAtlas9 } from "@goweekdays/utils";
|
|
2377
|
+
import cron from "node-cron";
|
|
2378
|
+
function useFileService() {
|
|
2379
|
+
const {
|
|
2380
|
+
createFile: _createFile,
|
|
2381
|
+
deleteFileById,
|
|
2382
|
+
getAllDraftedFiles
|
|
2383
|
+
} = useFileRepo();
|
|
2384
|
+
const s3 = new useS33({
|
|
2385
|
+
accessKeyId: SPACES_ACCESS_KEY,
|
|
2386
|
+
secretAccessKey: SPACES_SECRET_KEY,
|
|
2387
|
+
endpoint: SPACES_ENDPOINT,
|
|
2388
|
+
region: SPACES_REGION,
|
|
2389
|
+
bucket: SPACES_BUCKET
|
|
2390
|
+
});
|
|
2391
|
+
function createFile(value) {
|
|
2392
|
+
return __async(this, null, function* () {
|
|
2393
|
+
var _a;
|
|
2394
|
+
const session = (_a = useAtlas9.getClient()) == null ? void 0 : _a.startSession();
|
|
2395
|
+
session == null ? void 0 : session.startTransaction();
|
|
2396
|
+
const file = {
|
|
2397
|
+
name: value.originalname,
|
|
2398
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2399
|
+
};
|
|
2400
|
+
try {
|
|
2401
|
+
const id = yield _createFile(file, session);
|
|
2402
|
+
yield s3.uploadObject({
|
|
2403
|
+
key: id,
|
|
2404
|
+
body: value.buffer,
|
|
2405
|
+
contentType: value.mimetype
|
|
2406
|
+
});
|
|
2407
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
2408
|
+
return id;
|
|
2409
|
+
} catch (error) {
|
|
2410
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
2411
|
+
throw error;
|
|
2412
|
+
} finally {
|
|
2413
|
+
session == null ? void 0 : session.endSession();
|
|
2414
|
+
}
|
|
2415
|
+
});
|
|
2416
|
+
}
|
|
2417
|
+
function deleteFile(id) {
|
|
2418
|
+
return __async(this, null, function* () {
|
|
2419
|
+
var _a;
|
|
2420
|
+
const session = (_a = useAtlas9.getClient()) == null ? void 0 : _a.startSession();
|
|
2421
|
+
session == null ? void 0 : session.startTransaction();
|
|
2422
|
+
try {
|
|
2423
|
+
yield deleteFileById(id, session);
|
|
2424
|
+
yield s3.deleteObject(id);
|
|
2425
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
2426
|
+
return "File deleted successfully";
|
|
2427
|
+
} catch (error) {
|
|
2428
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
2429
|
+
throw error;
|
|
2430
|
+
} finally {
|
|
2431
|
+
session == null ? void 0 : session.endSession();
|
|
2432
|
+
}
|
|
2433
|
+
});
|
|
2434
|
+
}
|
|
2435
|
+
function deleteDraft() {
|
|
2436
|
+
cron.schedule("0 0 * * *", () => __async(this, null, function* () {
|
|
2437
|
+
const files = yield getAllDraftedFiles();
|
|
2438
|
+
for (let index = 0; index < files.length; index++) {
|
|
2439
|
+
const file = files[index];
|
|
2440
|
+
try {
|
|
2441
|
+
yield deleteFile(file._id.toString());
|
|
2442
|
+
yield logger6.log({
|
|
2443
|
+
level: "info",
|
|
2444
|
+
message: "Successfully deleted draft files."
|
|
2445
|
+
});
|
|
2446
|
+
} catch (error) {
|
|
2447
|
+
logger6.log({
|
|
2448
|
+
level: "info",
|
|
2449
|
+
message: "Successfully deleted draft files."
|
|
2450
|
+
});
|
|
2451
|
+
return;
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
}));
|
|
2455
|
+
}
|
|
2456
|
+
return {
|
|
2457
|
+
createFile,
|
|
2458
|
+
deleteFile,
|
|
2459
|
+
deleteDraft
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
// src/controllers/file.controller.ts
|
|
2464
|
+
import {
|
|
2465
|
+
AppError as AppError6,
|
|
2466
|
+
BadRequestError as BadRequestError13,
|
|
2467
|
+
InternalServerError as InternalServerError13
|
|
2468
|
+
} from "@goweekdays/utils";
|
|
2469
|
+
import Joi4 from "joi";
|
|
2470
|
+
function useFileController() {
|
|
2471
|
+
const { createFile, deleteFile: _deleteFile } = useFileService();
|
|
2472
|
+
function upload(req, res, next) {
|
|
2473
|
+
return __async(this, null, function* () {
|
|
2474
|
+
if (!req.file) {
|
|
2475
|
+
res.status(400).send("File is required!");
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
try {
|
|
2479
|
+
const id = yield createFile(req.file);
|
|
2480
|
+
res.json({ message: "Successfully uploaded file", id });
|
|
2481
|
+
return;
|
|
2482
|
+
} catch (error) {
|
|
2483
|
+
if (error instanceof AppError6) {
|
|
2484
|
+
next(error);
|
|
2485
|
+
} else {
|
|
2486
|
+
next(new InternalServerError13(error));
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
function deleteFile(req, res, next) {
|
|
2492
|
+
return __async(this, null, function* () {
|
|
2493
|
+
const id = req.params.id;
|
|
2494
|
+
const validation = Joi4.string().required();
|
|
2495
|
+
const { error } = validation.validate(id);
|
|
2496
|
+
if (error) {
|
|
2497
|
+
next(new BadRequestError13(error.message));
|
|
2498
|
+
}
|
|
2499
|
+
try {
|
|
2500
|
+
const message = yield _deleteFile(id);
|
|
2501
|
+
res.json({ message });
|
|
2502
|
+
return;
|
|
2503
|
+
} catch (error2) {
|
|
2504
|
+
if (error2 instanceof AppError6) {
|
|
2505
|
+
next(error2);
|
|
2506
|
+
} else {
|
|
2507
|
+
next(new InternalServerError13(error2));
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
});
|
|
2511
|
+
}
|
|
2512
|
+
return {
|
|
2513
|
+
upload,
|
|
2514
|
+
deleteFile
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
// src/services/role.service.ts
|
|
2519
|
+
function useRoleService() {
|
|
2520
|
+
const {
|
|
2521
|
+
addRole,
|
|
2522
|
+
getRoles: _getRoles,
|
|
2523
|
+
getRoleByUserId: _getRoleByUserId,
|
|
2524
|
+
getRoleById: _getRoleById,
|
|
2525
|
+
getRoleByName: _getRoleByName,
|
|
2526
|
+
updateRole: _updateRole,
|
|
2527
|
+
deleteRole: _deleteRole
|
|
2528
|
+
} = useRoleRepo();
|
|
2529
|
+
function createRole(value) {
|
|
2530
|
+
return __async(this, null, function* () {
|
|
2531
|
+
try {
|
|
2532
|
+
return yield addRole(value);
|
|
2533
|
+
} catch (error) {
|
|
2534
|
+
throw error;
|
|
2535
|
+
}
|
|
2536
|
+
});
|
|
2537
|
+
}
|
|
2538
|
+
function getRoles() {
|
|
2539
|
+
return __async(this, arguments, function* ({
|
|
2540
|
+
search = "",
|
|
2541
|
+
page = 1,
|
|
2542
|
+
limit = 10,
|
|
2543
|
+
type = ""
|
|
2544
|
+
} = {}) {
|
|
2545
|
+
try {
|
|
2546
|
+
return yield _getRoles({ search, page, limit, type });
|
|
2547
|
+
} catch (error) {
|
|
2548
|
+
throw error;
|
|
2549
|
+
}
|
|
2550
|
+
});
|
|
2551
|
+
}
|
|
2552
|
+
function getRoleByUserId(value) {
|
|
2553
|
+
return __async(this, null, function* () {
|
|
2554
|
+
try {
|
|
2555
|
+
return yield _getRoleByUserId(value);
|
|
2556
|
+
} catch (error) {
|
|
2557
|
+
throw error;
|
|
2558
|
+
}
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2561
|
+
function getRoleById(_id) {
|
|
2562
|
+
return __async(this, null, function* () {
|
|
2563
|
+
try {
|
|
2564
|
+
return yield _getRoleById(_id);
|
|
2565
|
+
} catch (error) {
|
|
2566
|
+
throw error;
|
|
2567
|
+
}
|
|
2568
|
+
});
|
|
2569
|
+
}
|
|
2570
|
+
function getRoleByName(name) {
|
|
2571
|
+
return __async(this, null, function* () {
|
|
2572
|
+
try {
|
|
2573
|
+
return yield _getRoleByName(name);
|
|
2574
|
+
} catch (error) {
|
|
2575
|
+
throw error;
|
|
2576
|
+
}
|
|
2577
|
+
});
|
|
2578
|
+
}
|
|
2579
|
+
function updateRole(_id, value) {
|
|
2580
|
+
return __async(this, null, function* () {
|
|
2581
|
+
try {
|
|
2582
|
+
return yield _updateRole(_id, value);
|
|
2583
|
+
} catch (error) {
|
|
2584
|
+
throw error;
|
|
2585
|
+
}
|
|
2586
|
+
});
|
|
2587
|
+
}
|
|
2588
|
+
function deleteRole(_id) {
|
|
2589
|
+
return __async(this, null, function* () {
|
|
2590
|
+
try {
|
|
2591
|
+
return yield _deleteRole(_id);
|
|
2592
|
+
} catch (error) {
|
|
2593
|
+
throw error;
|
|
2594
|
+
}
|
|
2595
|
+
});
|
|
2596
|
+
}
|
|
2597
|
+
return {
|
|
2598
|
+
createRole,
|
|
2599
|
+
getRoles,
|
|
2600
|
+
getRoleByUserId,
|
|
2601
|
+
getRoleById,
|
|
2602
|
+
getRoleByName,
|
|
2603
|
+
updateRole,
|
|
2604
|
+
deleteRole
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
// src/controllers/role.controller.ts
|
|
2609
|
+
import Joi5 from "joi";
|
|
2610
|
+
import { BadRequestError as BadRequestError14 } from "@goweekdays/utils";
|
|
2611
|
+
function useRoleController() {
|
|
2612
|
+
const {
|
|
2613
|
+
createRole: _createRole,
|
|
2614
|
+
getRoleById: _getRoleById,
|
|
2615
|
+
getRoleByUserId: _getRoleByUserId,
|
|
2616
|
+
getRoles: _getRoles,
|
|
2617
|
+
updateRole: _updateRole,
|
|
2618
|
+
deleteRole: _deleteRole
|
|
2619
|
+
} = useRoleService();
|
|
2620
|
+
function createRole(req, res, next) {
|
|
2621
|
+
return __async(this, null, function* () {
|
|
2622
|
+
var _a, _b, _c;
|
|
2623
|
+
const name = (_a = req.body.name) != null ? _a : "";
|
|
2624
|
+
const permissions = (_b = req.body.permissions) != null ? _b : [];
|
|
2625
|
+
const type = (_c = req.body.type) != null ? _c : "";
|
|
2626
|
+
const validation = Joi5.object({
|
|
2627
|
+
name: Joi5.string().required(),
|
|
2628
|
+
permissions: Joi5.array().items(Joi5.string()).required(),
|
|
2629
|
+
type: Joi5.string().optional().allow("", null)
|
|
2630
|
+
});
|
|
2631
|
+
const { error } = validation.validate({ name, permissions, type });
|
|
2632
|
+
if (error) {
|
|
2633
|
+
next(new BadRequestError14(error.message));
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2636
|
+
try {
|
|
2637
|
+
const role = yield _createRole({ name, permissions, type });
|
|
2638
|
+
res.json({ message: "Successfully created role.", data: { role } });
|
|
2639
|
+
return;
|
|
2640
|
+
} catch (error2) {
|
|
2641
|
+
next(error2);
|
|
2642
|
+
}
|
|
2643
|
+
});
|
|
2644
|
+
}
|
|
2645
|
+
function getRoles(req, res, next) {
|
|
2646
|
+
return __async(this, null, function* () {
|
|
2647
|
+
var _a, _b, _c, _d;
|
|
2648
|
+
const search = (_a = req.query.search) != null ? _a : "";
|
|
2649
|
+
const page = parseInt((_b = req.query.page) != null ? _b : "1");
|
|
2650
|
+
const limit = parseInt((_c = req.query.limit) != null ? _c : "10");
|
|
2651
|
+
const type = (_d = req.query.type) != null ? _d : "";
|
|
2652
|
+
const validation = Joi5.object({
|
|
2653
|
+
search: Joi5.string().optional().allow("", null),
|
|
2654
|
+
page: Joi5.number().required(),
|
|
2655
|
+
limit: Joi5.number().required(),
|
|
2656
|
+
type: Joi5.string().optional().allow("", null)
|
|
2657
|
+
});
|
|
2658
|
+
const { error } = validation.validate({ search, page, limit, type });
|
|
2659
|
+
if (error) {
|
|
2660
|
+
next(new BadRequestError14(error.message));
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2663
|
+
try {
|
|
2664
|
+
const data = yield _getRoles({ search, page, limit, type });
|
|
2665
|
+
res.json(data);
|
|
2666
|
+
return;
|
|
2667
|
+
} catch (error2) {
|
|
2668
|
+
console.log(error2);
|
|
2669
|
+
next(error2);
|
|
2670
|
+
}
|
|
2671
|
+
});
|
|
2672
|
+
}
|
|
2673
|
+
function getRoleByUserId(req, res, next) {
|
|
2674
|
+
return __async(this, null, function* () {
|
|
2675
|
+
const userId = req.params.userId;
|
|
2676
|
+
const validation = Joi5.object({
|
|
2677
|
+
userId: Joi5.string().required()
|
|
2678
|
+
});
|
|
2679
|
+
const { error } = validation.validate({ userId });
|
|
2680
|
+
if (error) {
|
|
2681
|
+
next(new BadRequestError14(error.message));
|
|
2682
|
+
return;
|
|
2683
|
+
}
|
|
2684
|
+
try {
|
|
2685
|
+
const role = yield _getRoleByUserId(userId);
|
|
2686
|
+
res.json({ message: "Successfully retrieved role.", data: { role } });
|
|
2687
|
+
return;
|
|
2688
|
+
} catch (error2) {
|
|
2689
|
+
next(error2);
|
|
2690
|
+
}
|
|
2691
|
+
});
|
|
2692
|
+
}
|
|
2693
|
+
function getRoleById(req, res, next) {
|
|
2694
|
+
return __async(this, null, function* () {
|
|
2695
|
+
const _id = req.params.id;
|
|
2696
|
+
const validation = Joi5.object({
|
|
2697
|
+
_id: Joi5.string().hex().required()
|
|
2698
|
+
});
|
|
2699
|
+
const { error } = validation.validate({ _id });
|
|
2700
|
+
if (error) {
|
|
2701
|
+
next(new BadRequestError14(error.message));
|
|
2702
|
+
return;
|
|
2703
|
+
}
|
|
2704
|
+
try {
|
|
2705
|
+
const data = yield _getRoleById(_id);
|
|
2706
|
+
res.json(data);
|
|
2707
|
+
return;
|
|
2708
|
+
} catch (error2) {
|
|
2709
|
+
next(error2);
|
|
2710
|
+
}
|
|
2711
|
+
});
|
|
2712
|
+
}
|
|
2713
|
+
function updateRole(req, res, next) {
|
|
2714
|
+
return __async(this, null, function* () {
|
|
2715
|
+
var _a, _b;
|
|
2716
|
+
const _id = req.params.id;
|
|
2717
|
+
const name = (_a = req.body.name) != null ? _a : "";
|
|
2718
|
+
const permissions = (_b = req.body.permissions) != null ? _b : [];
|
|
2719
|
+
const validation = Joi5.object({
|
|
2720
|
+
_id: Joi5.string().required(),
|
|
2721
|
+
name: Joi5.string().required(),
|
|
2722
|
+
permissions: Joi5.array().items(Joi5.string()).required()
|
|
2723
|
+
});
|
|
2724
|
+
const { error } = validation.validate({ _id, name, permissions });
|
|
2725
|
+
if (error) {
|
|
2726
|
+
next(new BadRequestError14(error.message));
|
|
2727
|
+
return;
|
|
2728
|
+
}
|
|
2729
|
+
try {
|
|
2730
|
+
const role = yield _updateRole(_id, { name, permissions });
|
|
2731
|
+
res.json({ message: "Successfully updated role.", data: { role } });
|
|
2732
|
+
return;
|
|
2733
|
+
} catch (error2) {
|
|
2734
|
+
next(error2);
|
|
2735
|
+
}
|
|
2736
|
+
});
|
|
2737
|
+
}
|
|
2738
|
+
function deleteRole(req, res, next) {
|
|
2739
|
+
return __async(this, null, function* () {
|
|
2740
|
+
const _id = req.params.id;
|
|
2741
|
+
const validation = Joi5.object({
|
|
2742
|
+
_id: Joi5.string().required()
|
|
2743
|
+
});
|
|
2744
|
+
const { error } = validation.validate({ _id });
|
|
2745
|
+
if (error) {
|
|
2746
|
+
next(new BadRequestError14(error.message));
|
|
2747
|
+
return;
|
|
2748
|
+
}
|
|
2749
|
+
try {
|
|
2750
|
+
const message = yield _deleteRole(_id);
|
|
2751
|
+
res.json({ message });
|
|
2752
|
+
return;
|
|
2753
|
+
} catch (error2) {
|
|
2754
|
+
next(error2);
|
|
2755
|
+
}
|
|
2756
|
+
});
|
|
2757
|
+
}
|
|
2758
|
+
return {
|
|
2759
|
+
createRole,
|
|
2760
|
+
getRoles,
|
|
2761
|
+
getRoleByUserId,
|
|
2762
|
+
getRoleById,
|
|
2763
|
+
updateRole,
|
|
2764
|
+
deleteRole
|
|
2765
|
+
};
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
// src/models/entity.model.ts
|
|
2769
|
+
import { ObjectId as ObjectId12 } from "mongodb";
|
|
2770
|
+
var MEntity = class {
|
|
2771
|
+
constructor(value) {
|
|
2772
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2773
|
+
this._id = (_a = value._id) != null ? _a : new ObjectId12();
|
|
2774
|
+
this.name = (_b = value.name) != null ? _b : "";
|
|
2775
|
+
this.username = (_c = value.username) != null ? _c : "";
|
|
2776
|
+
this.type = value.type;
|
|
2777
|
+
this.createdAt = (_d = value.createdAt) != null ? _d : (/* @__PURE__ */ new Date()).toISOString();
|
|
2778
|
+
this.updatedAt = (_e = value.updatedAt) != null ? _e : "";
|
|
2779
|
+
this.deletedAt = (_f = value.deletedAt) != null ? _f : "";
|
|
2780
|
+
this.status = (_g = value.status) != null ? _g : "active";
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
|
|
2784
|
+
// src/repositories/entity.repository.ts
|
|
2785
|
+
import { ObjectId as ObjectId13 } from "mongodb";
|
|
2786
|
+
import {
|
|
2787
|
+
BadRequestError as BadRequestError15,
|
|
2788
|
+
InternalServerError as InternalServerError14,
|
|
2789
|
+
logger as logger7,
|
|
2790
|
+
paginate as paginate5,
|
|
2791
|
+
useAtlas as useAtlas10
|
|
2792
|
+
} from "@goweekdays/utils";
|
|
2793
|
+
function useEntityRepo() {
|
|
2794
|
+
const db = useAtlas10.getDb();
|
|
2795
|
+
if (!db) {
|
|
2796
|
+
throw new InternalServerError14("Unable to connect to server.");
|
|
2797
|
+
}
|
|
2798
|
+
const collection = db.collection("entities");
|
|
2799
|
+
function createIndex() {
|
|
2800
|
+
return __async(this, null, function* () {
|
|
2801
|
+
try {
|
|
2802
|
+
yield collection.createIndex({ name: 1 });
|
|
2803
|
+
yield collection.createIndex({ status: 1 });
|
|
2804
|
+
} catch (error) {
|
|
2805
|
+
throw new Error("Failed to create index for entity.");
|
|
2806
|
+
}
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
function createUniqueIndex() {
|
|
2810
|
+
return __async(this, null, function* () {
|
|
2811
|
+
try {
|
|
2812
|
+
yield collection.createIndex({ name: 1, deletedAt: 1 }, { unique: true });
|
|
2813
|
+
} catch (error) {
|
|
2814
|
+
throw new Error("Failed to create unique index on email.");
|
|
2815
|
+
}
|
|
2816
|
+
});
|
|
2817
|
+
}
|
|
2818
|
+
function createEntity(value, session) {
|
|
2819
|
+
return __async(this, null, function* () {
|
|
2820
|
+
try {
|
|
2821
|
+
value = new MEntity(value);
|
|
2822
|
+
const res = yield collection.insertOne(value, {
|
|
2823
|
+
session
|
|
2824
|
+
});
|
|
2825
|
+
return res.insertedId.toString();
|
|
2826
|
+
} catch (error) {
|
|
2827
|
+
logger7.log({ level: "error", message: `${error}` });
|
|
2828
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
2829
|
+
if (isDuplicated) {
|
|
2830
|
+
throw new BadRequestError15("Entity name already exists.");
|
|
2831
|
+
}
|
|
2832
|
+
throw new InternalServerError14("Failed to create entity.");
|
|
2833
|
+
}
|
|
2834
|
+
});
|
|
2835
|
+
}
|
|
2836
|
+
function getEntities() {
|
|
2837
|
+
return __async(this, arguments, function* ({
|
|
2838
|
+
search = "",
|
|
2839
|
+
page = 1,
|
|
2840
|
+
limit = 10,
|
|
2841
|
+
sort = {}
|
|
2842
|
+
} = {}) {
|
|
2843
|
+
page = page > 0 ? page - 1 : 0;
|
|
2844
|
+
const query = { status: "active" };
|
|
2845
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
2846
|
+
if (search) {
|
|
2847
|
+
query.$text = { $search: search };
|
|
2848
|
+
}
|
|
2849
|
+
try {
|
|
2850
|
+
const items = yield collection.aggregate([
|
|
2851
|
+
{ $match: query },
|
|
2852
|
+
{ $sort: sort },
|
|
2853
|
+
{ $skip: page * limit },
|
|
2854
|
+
{ $limit: limit }
|
|
2855
|
+
]).toArray();
|
|
2856
|
+
const length = yield collection.countDocuments(query);
|
|
2857
|
+
return paginate5(items, page, limit, length);
|
|
2858
|
+
} catch (error) {
|
|
2859
|
+
logger7.log({ level: "error", message: `${error}` });
|
|
2860
|
+
throw error;
|
|
2861
|
+
}
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2864
|
+
function updateEntityFieldById() {
|
|
2865
|
+
return __async(this, arguments, function* ({ _id, field, value } = {}, session) {
|
|
2866
|
+
const allowedFields = ["name"];
|
|
2867
|
+
if (!allowedFields.includes(field)) {
|
|
2868
|
+
throw new BadRequestError15(
|
|
2869
|
+
`Field "${field}" is not allowed to be updated.`
|
|
2870
|
+
);
|
|
2871
|
+
}
|
|
2872
|
+
try {
|
|
2873
|
+
_id = new ObjectId13(_id);
|
|
2874
|
+
} catch (error) {
|
|
2875
|
+
throw new BadRequestError15("Invalid ID.");
|
|
2876
|
+
}
|
|
2877
|
+
try {
|
|
2878
|
+
yield collection.updateOne(
|
|
2879
|
+
{ _id },
|
|
2880
|
+
{ $set: { [field]: value } },
|
|
2881
|
+
// Dynamically set the field
|
|
2882
|
+
{ session }
|
|
2883
|
+
);
|
|
2884
|
+
return `Successfully updated entity ${field}.`;
|
|
2885
|
+
} catch (error) {
|
|
2886
|
+
throw new InternalServerError14(`Failed to update entity ${field}.`);
|
|
2887
|
+
}
|
|
2888
|
+
});
|
|
2889
|
+
}
|
|
2890
|
+
function deleteEntity(_id) {
|
|
2891
|
+
return __async(this, null, function* () {
|
|
2892
|
+
try {
|
|
2893
|
+
_id = new ObjectId13(_id);
|
|
2894
|
+
} catch (error) {
|
|
2895
|
+
throw new BadRequestError15("Invalid entity ID.");
|
|
2896
|
+
}
|
|
2897
|
+
try {
|
|
2898
|
+
return yield collection.updateOne(
|
|
2899
|
+
{ _id },
|
|
2900
|
+
{ $set: { status: "deleted", deletedAt: (/* @__PURE__ */ new Date()).toISOString() } }
|
|
2901
|
+
);
|
|
2902
|
+
} catch (error) {
|
|
2903
|
+
return Promise.reject(error);
|
|
2904
|
+
}
|
|
2905
|
+
});
|
|
2906
|
+
}
|
|
2907
|
+
return {
|
|
2908
|
+
createIndex,
|
|
2909
|
+
createUniqueIndex,
|
|
2910
|
+
createEntity,
|
|
2911
|
+
getEntities,
|
|
2912
|
+
updateEntityFieldById,
|
|
2913
|
+
deleteEntity
|
|
2914
|
+
};
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2917
|
+
// src/services/entity.service.ts
|
|
2918
|
+
import { InternalServerError as InternalServerError15 } from "@goweekdays/utils";
|
|
2919
|
+
function useEntityService() {
|
|
2920
|
+
const {
|
|
2921
|
+
createEntity: _createEntity,
|
|
2922
|
+
getEntities: _getEntities,
|
|
2923
|
+
updateEntityFieldById: _updateEntityFieldById,
|
|
2924
|
+
deleteEntity: _deleteEntity
|
|
2925
|
+
} = useEntityRepo();
|
|
2926
|
+
function createEntity(value) {
|
|
2927
|
+
return __async(this, null, function* () {
|
|
2928
|
+
try {
|
|
2929
|
+
return yield _createEntity(value);
|
|
2930
|
+
} catch (error) {
|
|
2931
|
+
throw new InternalServerError15();
|
|
2932
|
+
}
|
|
2933
|
+
});
|
|
2934
|
+
}
|
|
2935
|
+
function getEntities(value) {
|
|
2936
|
+
return __async(this, null, function* () {
|
|
2937
|
+
try {
|
|
2938
|
+
return yield _getEntities(value);
|
|
2939
|
+
} catch (error) {
|
|
2940
|
+
throw new InternalServerError15();
|
|
2941
|
+
}
|
|
2942
|
+
});
|
|
2943
|
+
}
|
|
2944
|
+
function updateEntityFieldById(_id, field, value) {
|
|
2945
|
+
return __async(this, null, function* () {
|
|
2946
|
+
try {
|
|
2947
|
+
return yield _updateEntityFieldById({ _id, field, value });
|
|
2948
|
+
} catch (error) {
|
|
2949
|
+
throw new InternalServerError15();
|
|
2950
|
+
}
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
2953
|
+
function deleteEntity(_id) {
|
|
2954
|
+
return __async(this, null, function* () {
|
|
2955
|
+
try {
|
|
2956
|
+
return yield _deleteEntity(_id);
|
|
2957
|
+
} catch (error) {
|
|
2958
|
+
throw error;
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
return {
|
|
2963
|
+
createEntity,
|
|
2964
|
+
getEntities,
|
|
2965
|
+
updateEntityFieldById,
|
|
2966
|
+
deleteEntity
|
|
2967
|
+
};
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
// src/controllers/entity.controller.ts
|
|
2971
|
+
import Joi6 from "joi";
|
|
2972
|
+
import { BadRequestError as BadRequestError16 } from "@goweekdays/utils";
|
|
2973
|
+
function useEntityController() {
|
|
2974
|
+
const {
|
|
2975
|
+
createEntity: _createEntity,
|
|
2976
|
+
getEntities: _getEntities,
|
|
2977
|
+
updateEntityFieldById: _updateEntityFieldById,
|
|
2978
|
+
deleteEntity: _deleteEntity
|
|
2979
|
+
} = useEntityService();
|
|
2980
|
+
function createEntity(req, res, next) {
|
|
2981
|
+
return __async(this, null, function* () {
|
|
2982
|
+
const value = req.body;
|
|
2983
|
+
const validation = Joi6.object({
|
|
2984
|
+
name: Joi6.string().required(),
|
|
2985
|
+
type: Joi6.string().valid(
|
|
2986
|
+
"strand",
|
|
2987
|
+
"office",
|
|
2988
|
+
"bureau",
|
|
2989
|
+
"service",
|
|
2990
|
+
"person"
|
|
2991
|
+
)
|
|
2992
|
+
});
|
|
2993
|
+
const { error } = validation.validate(value);
|
|
2994
|
+
if (error) {
|
|
2995
|
+
next(new BadRequestError16(error.message));
|
|
2996
|
+
return;
|
|
2997
|
+
}
|
|
2998
|
+
try {
|
|
2999
|
+
const id = yield _createEntity(value);
|
|
3000
|
+
res.json({ message: "Successfully created entity.", id });
|
|
3001
|
+
return;
|
|
3002
|
+
} catch (error2) {
|
|
3003
|
+
console.log(error2);
|
|
3004
|
+
next(error2);
|
|
3005
|
+
return;
|
|
3006
|
+
}
|
|
3007
|
+
});
|
|
3008
|
+
}
|
|
3009
|
+
function getEntities(req, res, next) {
|
|
3010
|
+
return __async(this, null, function* () {
|
|
3011
|
+
var _a, _b, _c;
|
|
3012
|
+
const search = (_a = req.query.search) != null ? _a : "";
|
|
3013
|
+
const page = (_b = Number(req.query.page)) != null ? _b : 1;
|
|
3014
|
+
const limit = (_c = Number(req.query.limit)) != null ? _c : 10;
|
|
3015
|
+
const validation = Joi6.object({
|
|
3016
|
+
search: Joi6.string().allow(""),
|
|
3017
|
+
page: Joi6.number().min(1),
|
|
3018
|
+
limit: Joi6.number().min(1)
|
|
3019
|
+
});
|
|
3020
|
+
const { error } = validation.validate(req.query);
|
|
3021
|
+
if (error) {
|
|
3022
|
+
next(new BadRequestError16(error.message));
|
|
3023
|
+
return;
|
|
3024
|
+
}
|
|
3025
|
+
try {
|
|
3026
|
+
const entities = yield _getEntities({
|
|
3027
|
+
search,
|
|
3028
|
+
page,
|
|
3029
|
+
limit
|
|
3030
|
+
});
|
|
3031
|
+
res.json(entities);
|
|
3032
|
+
return;
|
|
3033
|
+
} catch (error2) {
|
|
3034
|
+
next(error2);
|
|
3035
|
+
return;
|
|
3036
|
+
}
|
|
3037
|
+
});
|
|
3038
|
+
}
|
|
3039
|
+
function updateEntityFieldById(req, res, next) {
|
|
3040
|
+
return __async(this, null, function* () {
|
|
3041
|
+
const { id, field, value } = req.body;
|
|
3042
|
+
const validation = Joi6.object({
|
|
3043
|
+
id: Joi6.string().required(),
|
|
3044
|
+
field: Joi6.string().required(),
|
|
3045
|
+
value: Joi6.string().required()
|
|
3046
|
+
});
|
|
3047
|
+
const { error } = validation.validate({ id, field, value });
|
|
3048
|
+
if (error) {
|
|
3049
|
+
next(new BadRequestError16(error.message));
|
|
3050
|
+
return;
|
|
3051
|
+
}
|
|
3052
|
+
try {
|
|
3053
|
+
yield _updateEntityFieldById(id, field, value);
|
|
3054
|
+
res.json({ message: "Entity updated." });
|
|
3055
|
+
return;
|
|
3056
|
+
} catch (error2) {
|
|
3057
|
+
next(error2);
|
|
3058
|
+
return;
|
|
3059
|
+
}
|
|
3060
|
+
});
|
|
3061
|
+
}
|
|
3062
|
+
function deleteEntity(req, res, next) {
|
|
3063
|
+
return __async(this, null, function* () {
|
|
3064
|
+
const { id } = req.params;
|
|
3065
|
+
const validation = Joi6.object({
|
|
3066
|
+
id: Joi6.string().required()
|
|
3067
|
+
});
|
|
3068
|
+
const { error } = validation.validate({ id });
|
|
3069
|
+
if (error) {
|
|
3070
|
+
next(new BadRequestError16(error.message));
|
|
3071
|
+
return;
|
|
3072
|
+
}
|
|
3073
|
+
try {
|
|
3074
|
+
yield _deleteEntity(id);
|
|
3075
|
+
res.json({ message: "Entity deleted." });
|
|
3076
|
+
return;
|
|
3077
|
+
} catch (error2) {
|
|
3078
|
+
next(error2);
|
|
3079
|
+
return;
|
|
3080
|
+
}
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
return {
|
|
3084
|
+
createEntity,
|
|
3085
|
+
getEntities,
|
|
3086
|
+
updateEntityFieldById,
|
|
3087
|
+
deleteEntity
|
|
3088
|
+
};
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
// src/models/workflow.model.ts
|
|
3092
|
+
import { ObjectId as ObjectId14 } from "mongodb";
|
|
3093
|
+
var MWorkflow = class {
|
|
3094
|
+
constructor(value) {
|
|
3095
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3096
|
+
this._id = (_a = value._id) != null ? _a : new ObjectId14();
|
|
3097
|
+
this.name = (_b = value.name) != null ? _b : "";
|
|
3098
|
+
this.steps = (_c = value.steps) != null ? _c : [];
|
|
3099
|
+
this.status = (_d = value.status) != null ? _d : "active";
|
|
3100
|
+
this.createdAt = (_e = value.createdAt) != null ? _e : (/* @__PURE__ */ new Date()).toISOString();
|
|
3101
|
+
this.updatedAt = (_f = value.updatedAt) != null ? _f : "";
|
|
3102
|
+
this.deletedAt = (_g = value.deletedAt) != null ? _g : "";
|
|
3103
|
+
}
|
|
3104
|
+
};
|
|
3105
|
+
|
|
3106
|
+
// src/repositories/workflow.repository.ts
|
|
3107
|
+
import { ObjectId as ObjectId15 } from "mongodb";
|
|
3108
|
+
import {
|
|
3109
|
+
BadRequestError as BadRequestError17,
|
|
3110
|
+
InternalServerError as InternalServerError16,
|
|
3111
|
+
logger as logger8,
|
|
3112
|
+
paginate as paginate6,
|
|
3113
|
+
useAtlas as useAtlas11
|
|
3114
|
+
} from "@goweekdays/utils";
|
|
3115
|
+
function useWorkflowRepo() {
|
|
3116
|
+
const db = useAtlas11.getDb();
|
|
3117
|
+
if (!db) {
|
|
3118
|
+
throw new InternalServerError16("Unable to connect to server.");
|
|
3119
|
+
}
|
|
3120
|
+
const collection = db.collection("workflows");
|
|
3121
|
+
function createIndex() {
|
|
3122
|
+
return __async(this, null, function* () {
|
|
3123
|
+
try {
|
|
3124
|
+
yield collection.createIndex({ name: 1 });
|
|
3125
|
+
yield collection.createIndex({ status: 1 });
|
|
3126
|
+
} catch (error) {
|
|
3127
|
+
throw new Error("Failed to create index for workflow.");
|
|
3128
|
+
}
|
|
3129
|
+
});
|
|
3130
|
+
}
|
|
3131
|
+
function createUniqueIndex() {
|
|
3132
|
+
return __async(this, null, function* () {
|
|
3133
|
+
try {
|
|
3134
|
+
yield collection.createIndex({ name: 1, deletedAt: 1 }, { unique: true });
|
|
3135
|
+
} catch (error) {
|
|
3136
|
+
throw new Error("Failed to create unique index for workflow.");
|
|
3137
|
+
}
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
function createWorkflow(value) {
|
|
3141
|
+
return __async(this, null, function* () {
|
|
3142
|
+
try {
|
|
3143
|
+
value = new MWorkflow(value);
|
|
3144
|
+
const res = yield collection.insertOne(value);
|
|
3145
|
+
return res.insertedId.toString();
|
|
3146
|
+
} catch (error) {
|
|
3147
|
+
const duplicated = error.message.includes("duplicate");
|
|
3148
|
+
if (duplicated) {
|
|
3149
|
+
throw new BadRequestError17("Workflow name already exists.");
|
|
3150
|
+
}
|
|
3151
|
+
throw new InternalServerError16("Failed to create workflow.");
|
|
3152
|
+
}
|
|
3153
|
+
});
|
|
3154
|
+
}
|
|
3155
|
+
function getWorkflows() {
|
|
3156
|
+
return __async(this, arguments, function* ({
|
|
3157
|
+
search = "",
|
|
3158
|
+
page = 1,
|
|
3159
|
+
limit = 10,
|
|
3160
|
+
sort = {}
|
|
3161
|
+
} = {}) {
|
|
3162
|
+
page = page > 0 ? page - 1 : 0;
|
|
3163
|
+
const query = { status: "active" };
|
|
3164
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
3165
|
+
if (search) {
|
|
3166
|
+
query.$text = { $search: search };
|
|
3167
|
+
}
|
|
3168
|
+
try {
|
|
3169
|
+
const items = yield collection.aggregate([
|
|
3170
|
+
{ $match: query },
|
|
3171
|
+
{ $sort: sort },
|
|
3172
|
+
{ $skip: page * limit },
|
|
3173
|
+
{ $limit: limit }
|
|
3174
|
+
]).toArray();
|
|
3175
|
+
const length = yield collection.countDocuments(query);
|
|
3176
|
+
return paginate6(items, page, limit, length);
|
|
3177
|
+
} catch (error) {
|
|
3178
|
+
logger8.log({ level: "error", message: `${error}` });
|
|
3179
|
+
throw error;
|
|
3180
|
+
}
|
|
3181
|
+
});
|
|
3182
|
+
}
|
|
3183
|
+
function getWorkflowById(_id) {
|
|
3184
|
+
return __async(this, null, function* () {
|
|
3185
|
+
try {
|
|
3186
|
+
_id = new ObjectId15(_id);
|
|
3187
|
+
} catch (error) {
|
|
3188
|
+
throw new BadRequestError17("Invalid workflow ID.");
|
|
3189
|
+
}
|
|
3190
|
+
try {
|
|
3191
|
+
return yield collection.findOne({ _id });
|
|
3192
|
+
} catch (error) {
|
|
3193
|
+
throw new InternalServerError16("Failed to get workflow.");
|
|
3194
|
+
}
|
|
3195
|
+
});
|
|
3196
|
+
}
|
|
3197
|
+
function updateWorkflowFieldById() {
|
|
3198
|
+
return __async(this, arguments, function* ({ _id, field, value } = {}, session) {
|
|
3199
|
+
const allowedFields = ["name"];
|
|
3200
|
+
if (!allowedFields.includes(field)) {
|
|
3201
|
+
throw new BadRequestError17(
|
|
3202
|
+
`Field "${field}" is not allowed to be updated.`
|
|
3203
|
+
);
|
|
3204
|
+
}
|
|
3205
|
+
try {
|
|
3206
|
+
_id = new ObjectId15(_id);
|
|
3207
|
+
} catch (error) {
|
|
3208
|
+
throw new BadRequestError17("Invalid ID.");
|
|
3209
|
+
}
|
|
3210
|
+
try {
|
|
3211
|
+
yield collection.updateOne(
|
|
3212
|
+
{ _id },
|
|
3213
|
+
{ $set: { [field]: value } },
|
|
3214
|
+
// Dynamically set the field
|
|
3215
|
+
{ session }
|
|
3216
|
+
);
|
|
3217
|
+
return `Successfully updated entity ${field}.`;
|
|
3218
|
+
} catch (error) {
|
|
3219
|
+
throw new InternalServerError16(`Failed to update entity ${field}.`);
|
|
3220
|
+
}
|
|
3221
|
+
});
|
|
3222
|
+
}
|
|
3223
|
+
function deleteWorkflow(_id) {
|
|
3224
|
+
return __async(this, null, function* () {
|
|
3225
|
+
try {
|
|
3226
|
+
_id = new ObjectId15(_id);
|
|
3227
|
+
} catch (error) {
|
|
3228
|
+
throw new BadRequestError17("Invalid entity ID.");
|
|
3229
|
+
}
|
|
3230
|
+
try {
|
|
3231
|
+
return yield collection.updateOne(
|
|
3232
|
+
{ _id },
|
|
3233
|
+
{ $set: { status: "deleted", deletedAt: (/* @__PURE__ */ new Date()).toISOString() } }
|
|
3234
|
+
);
|
|
3235
|
+
} catch (error) {
|
|
3236
|
+
return Promise.reject(error);
|
|
3237
|
+
}
|
|
3238
|
+
});
|
|
3239
|
+
}
|
|
3240
|
+
return {
|
|
3241
|
+
createIndex,
|
|
3242
|
+
createUniqueIndex,
|
|
3243
|
+
createWorkflow,
|
|
3244
|
+
getWorkflows,
|
|
3245
|
+
getWorkflowById,
|
|
3246
|
+
updateWorkflowFieldById,
|
|
3247
|
+
deleteWorkflow
|
|
3248
|
+
};
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
// src/services/workflow.service.ts
|
|
3252
|
+
function useWorkflowService() {
|
|
3253
|
+
const {
|
|
3254
|
+
createWorkflow: _createWorkflow,
|
|
3255
|
+
getWorkflows: _getWorkflows,
|
|
3256
|
+
getWorkflowById: _getWorkflowById,
|
|
3257
|
+
updateWorkflowFieldById: _updateWorkflowFieldById,
|
|
3258
|
+
deleteWorkflow: _deleteWorkflow
|
|
3259
|
+
} = useWorkflowRepo();
|
|
3260
|
+
function createWorkflow(value) {
|
|
3261
|
+
return __async(this, null, function* () {
|
|
3262
|
+
try {
|
|
3263
|
+
return yield _createWorkflow(value);
|
|
3264
|
+
} catch (error) {
|
|
3265
|
+
throw error;
|
|
3266
|
+
}
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3269
|
+
function getWorkflows() {
|
|
3270
|
+
return __async(this, arguments, function* ({
|
|
3271
|
+
search = "",
|
|
3272
|
+
page = 1,
|
|
3273
|
+
limit = 10,
|
|
3274
|
+
sort = {}
|
|
3275
|
+
} = {}) {
|
|
3276
|
+
try {
|
|
3277
|
+
return yield _getWorkflows({ search, page, limit, sort });
|
|
3278
|
+
} catch (error) {
|
|
3279
|
+
throw error;
|
|
3280
|
+
}
|
|
3281
|
+
});
|
|
3282
|
+
}
|
|
3283
|
+
function getWorkflowById(_id) {
|
|
3284
|
+
return __async(this, null, function* () {
|
|
3285
|
+
try {
|
|
3286
|
+
return yield _getWorkflowById(_id);
|
|
3287
|
+
} catch (error) {
|
|
3288
|
+
throw error;
|
|
3289
|
+
}
|
|
3290
|
+
});
|
|
3291
|
+
}
|
|
3292
|
+
function updateWorkflowFieldById(_id, field, value) {
|
|
3293
|
+
return __async(this, null, function* () {
|
|
3294
|
+
try {
|
|
3295
|
+
return yield _updateWorkflowFieldById({ _id, field, value });
|
|
3296
|
+
} catch (error) {
|
|
3297
|
+
throw error;
|
|
3298
|
+
}
|
|
3299
|
+
});
|
|
3300
|
+
}
|
|
3301
|
+
function deleteWorkflow(_id) {
|
|
3302
|
+
return __async(this, null, function* () {
|
|
3303
|
+
try {
|
|
3304
|
+
return yield _deleteWorkflow(_id);
|
|
3305
|
+
} catch (error) {
|
|
3306
|
+
throw error;
|
|
3307
|
+
}
|
|
3308
|
+
});
|
|
3309
|
+
}
|
|
3310
|
+
return {
|
|
3311
|
+
createWorkflow,
|
|
3312
|
+
getWorkflows,
|
|
3313
|
+
getWorkflowById,
|
|
3314
|
+
updateWorkflowFieldById,
|
|
3315
|
+
deleteWorkflow
|
|
3316
|
+
};
|
|
3317
|
+
}
|
|
3318
|
+
|
|
3319
|
+
// src/controllers/workflow.controller.ts
|
|
3320
|
+
import Joi7 from "joi";
|
|
3321
|
+
function useWorkflowController() {
|
|
3322
|
+
const {
|
|
3323
|
+
createWorkflow: _createWorkflow,
|
|
3324
|
+
getWorkflows: _getWorkflows,
|
|
3325
|
+
getWorkflowById: _getWorkflowById,
|
|
3326
|
+
updateWorkflowFieldById: _updateWorkflowFieldById,
|
|
3327
|
+
deleteWorkflow: _deleteWorkflow
|
|
3328
|
+
} = useWorkflowService();
|
|
3329
|
+
function createWorkflow(req, res, next) {
|
|
3330
|
+
return __async(this, null, function* () {
|
|
3331
|
+
var _a, _b;
|
|
3332
|
+
const name = (_a = req.body.name) != null ? _a : "";
|
|
3333
|
+
const steps = (_b = req.body.steps) != null ? _b : [];
|
|
3334
|
+
const validation = Joi7.object({
|
|
3335
|
+
name: Joi7.string().required(),
|
|
3336
|
+
steps: Joi7.array().items(
|
|
3337
|
+
Joi7.object({
|
|
3338
|
+
name: Joi7.string().required(),
|
|
3339
|
+
assignedTo: Joi7.string().optional(),
|
|
3340
|
+
nextStep: Joi7.string().optional
|
|
3341
|
+
})
|
|
3342
|
+
).min(3).required()
|
|
3343
|
+
});
|
|
3344
|
+
const { error } = validation.validate({ name, steps });
|
|
3345
|
+
if (error) {
|
|
3346
|
+
next(error);
|
|
3347
|
+
return;
|
|
3348
|
+
}
|
|
3349
|
+
try {
|
|
3350
|
+
const id = yield _createWorkflow({ name, steps });
|
|
3351
|
+
res.json({ message: "Successfully created workflow.", id });
|
|
3352
|
+
return;
|
|
3353
|
+
} catch (error2) {
|
|
3354
|
+
next(error2);
|
|
3355
|
+
return;
|
|
3356
|
+
}
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
3359
|
+
function getWorkflows(req, res, next) {
|
|
3360
|
+
return __async(this, null, function* () {
|
|
3361
|
+
var _a, _b, _c;
|
|
3362
|
+
const search = (_a = req.query.search) != null ? _a : "";
|
|
3363
|
+
const page = (_b = Number(req.query.page)) != null ? _b : 1;
|
|
3364
|
+
const limit = (_c = Number(req.query.limit)) != null ? _c : 10;
|
|
3365
|
+
const validation = Joi7.object({
|
|
3366
|
+
search: Joi7.string().allow(""),
|
|
3367
|
+
page: Joi7.number().min(1),
|
|
3368
|
+
limit: Joi7.number().min(10)
|
|
3369
|
+
});
|
|
3370
|
+
const { error } = validation.validate(req.query);
|
|
3371
|
+
if (error) {
|
|
3372
|
+
next(error);
|
|
3373
|
+
return;
|
|
3374
|
+
}
|
|
3375
|
+
try {
|
|
3376
|
+
const workflows = yield _getWorkflows({ search, page, limit });
|
|
3377
|
+
res.json(workflows);
|
|
3378
|
+
return;
|
|
3379
|
+
} catch (error2) {
|
|
3380
|
+
next(error2);
|
|
3381
|
+
return;
|
|
3382
|
+
}
|
|
3383
|
+
});
|
|
3384
|
+
}
|
|
3385
|
+
function getWorkflowById(req, res, next) {
|
|
3386
|
+
return __async(this, null, function* () {
|
|
3387
|
+
var _a;
|
|
3388
|
+
const id = (_a = req.params.id) != null ? _a : "";
|
|
3389
|
+
const validation = Joi7.object({
|
|
3390
|
+
id: Joi7.string().required()
|
|
3391
|
+
});
|
|
3392
|
+
const { error } = validation.validate({ id });
|
|
3393
|
+
if (error) {
|
|
3394
|
+
next(error);
|
|
3395
|
+
return;
|
|
3396
|
+
}
|
|
3397
|
+
try {
|
|
3398
|
+
const workflow = yield _getWorkflowById(id);
|
|
3399
|
+
res.json(workflow);
|
|
3400
|
+
return;
|
|
3401
|
+
} catch (error2) {
|
|
3402
|
+
next(error2);
|
|
3403
|
+
return;
|
|
3404
|
+
}
|
|
3405
|
+
});
|
|
3406
|
+
}
|
|
3407
|
+
function updateWorkflowFieldById(req, res, next) {
|
|
3408
|
+
return __async(this, null, function* () {
|
|
3409
|
+
var _a, _b, _c;
|
|
3410
|
+
const id = (_a = req.body.id) != null ? _a : "";
|
|
3411
|
+
const field = (_b = req.body.field) != null ? _b : "";
|
|
3412
|
+
const value = (_c = req.body.value) != null ? _c : "";
|
|
3413
|
+
const validation = Joi7.object({
|
|
3414
|
+
id: Joi7.string().required(),
|
|
3415
|
+
field: Joi7.string().required(),
|
|
3416
|
+
value: Joi7.string().required()
|
|
3417
|
+
});
|
|
3418
|
+
const { error } = validation.validate({ id, field, value });
|
|
3419
|
+
if (error) {
|
|
3420
|
+
next(error);
|
|
3421
|
+
return;
|
|
3422
|
+
}
|
|
3423
|
+
try {
|
|
3424
|
+
yield _updateWorkflowFieldById(id, field, value);
|
|
3425
|
+
res.json({ message: "Successfully updated workflow." });
|
|
3426
|
+
return;
|
|
3427
|
+
} catch (error2) {
|
|
3428
|
+
next(error2);
|
|
3429
|
+
return;
|
|
3430
|
+
}
|
|
3431
|
+
});
|
|
3432
|
+
}
|
|
3433
|
+
function deleteWorkflow(req, res, next) {
|
|
3434
|
+
return __async(this, null, function* () {
|
|
3435
|
+
var _a;
|
|
3436
|
+
const id = (_a = req.body.id) != null ? _a : "";
|
|
3437
|
+
const validation = Joi7.object({
|
|
3438
|
+
id: Joi7.string().required()
|
|
3439
|
+
});
|
|
3440
|
+
const { error } = validation.validate({ id });
|
|
3441
|
+
if (error) {
|
|
3442
|
+
next(error);
|
|
3443
|
+
return;
|
|
3444
|
+
}
|
|
3445
|
+
try {
|
|
3446
|
+
yield _deleteWorkflow(id);
|
|
3447
|
+
res.json({ message: "Successfully deleted workflow." });
|
|
3448
|
+
return;
|
|
3449
|
+
} catch (error2) {
|
|
3450
|
+
next(error2);
|
|
3451
|
+
return;
|
|
3452
|
+
}
|
|
3453
|
+
});
|
|
3454
|
+
}
|
|
3455
|
+
return {
|
|
3456
|
+
createWorkflow,
|
|
3457
|
+
getWorkflows,
|
|
3458
|
+
getWorkflowById,
|
|
3459
|
+
updateWorkflowFieldById,
|
|
3460
|
+
deleteWorkflow
|
|
3461
|
+
};
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
// src/models/cap-bldg-act.model.ts
|
|
3465
|
+
import { ObjectId as ObjectId16 } from "mongodb";
|
|
3466
|
+
var MCapBldgAct = class {
|
|
3467
|
+
constructor(value) {
|
|
3468
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q;
|
|
3469
|
+
this._id = (_a = value._id) != null ? _a : new ObjectId16();
|
|
3470
|
+
this.title = (_b = value.title) != null ? _b : "";
|
|
3471
|
+
this.subject = (_c = value.subject) != null ? _c : "";
|
|
3472
|
+
this.PMISActivityCode = (_d = value.PMISActivityCode) != null ? _d : "";
|
|
3473
|
+
this.type = (_e = value.type) != null ? _e : "";
|
|
3474
|
+
this.strandMandateAddressed = (_f = value.strandMandateAddressed) != null ? _f : "";
|
|
3475
|
+
this.objectives = (_g = value.objectives) != null ? _g : [];
|
|
3476
|
+
this.withCPDUnits = (_h = value.withCPDUnits) != null ? _h : false;
|
|
3477
|
+
this.completeStaffWorkReport = (_i = value.completeStaffWorkReport) != null ? _i : "";
|
|
3478
|
+
this.withATC = (_j = value.withATC) != null ? _j : null;
|
|
3479
|
+
this.ATC = (_k = value.ATC) != null ? _k : "";
|
|
3480
|
+
this.conceptNote = (_l = value.conceptNote) != null ? _l : "";
|
|
3481
|
+
this.certOfFundAvailability = (_m = value.certOfFundAvailability) != null ? _m : "";
|
|
3482
|
+
this.budgetProposal = (_n = value.budgetProposal) != null ? _n : "";
|
|
3483
|
+
this.targets = (_o = value.targets) != null ? _o : [];
|
|
3484
|
+
this.PRCFormsTemplate = (_p = value.PRCFormsTemplate) != null ? _p : "";
|
|
3485
|
+
this.HGDGTool = (_q = value.HGDGTool) != null ? _q : "";
|
|
3486
|
+
this.EXECOMLeadEndorsement = (_r = value.EXECOMLeadEndorsement) != null ? _r : "";
|
|
3487
|
+
this.individualResults = (_s = value.individualResults) != null ? _s : [];
|
|
3488
|
+
this.organizationalResults = (_t = value.organizationalResults) != null ? _t : [];
|
|
3489
|
+
this.indicative = (_u = value.indicative) != null ? _u : "";
|
|
3490
|
+
this.tentative = (_v = value.tentative) != null ? _v : { month: "", day: 0 };
|
|
3491
|
+
this.tentativeOption = (_w = value.tentativeOption) != null ? _w : { month: "", day: 0 };
|
|
3492
|
+
this.tentativeYear = (_x = value.tentativeYear) != null ? _x : 0;
|
|
3493
|
+
this.GADAttrRate = (_y = value.GADAttrRate) != null ? _y : 0;
|
|
3494
|
+
this.GADAttrRateAmount = (_z = value.GADAttrRateAmount) != null ? _z : 0;
|
|
3495
|
+
this.NTPCO = (_A = value.NTPCO) != null ? _A : {
|
|
3496
|
+
teaching: 0,
|
|
3497
|
+
nonteaching: 0,
|
|
3498
|
+
teachingRelated: 0
|
|
3499
|
+
};
|
|
3500
|
+
this.NTPRO = (_B = value.NTPRO) != null ? _B : {
|
|
3501
|
+
teaching: 0,
|
|
3502
|
+
nonteaching: 0,
|
|
3503
|
+
teachingRelated: 0
|
|
3504
|
+
};
|
|
3505
|
+
this.NTPSDO = (_C = value.NTPSDO) != null ? _C : {
|
|
3506
|
+
teaching: 0,
|
|
3507
|
+
nonteaching: 0,
|
|
3508
|
+
teachingRelated: 0
|
|
3509
|
+
};
|
|
3510
|
+
this.NTPSchool = (_D = value.NTPSchool) != null ? _D : {
|
|
3511
|
+
teaching: 0,
|
|
3512
|
+
nonteaching: 0,
|
|
3513
|
+
teachingRelated: 0
|
|
3514
|
+
};
|
|
3515
|
+
this.withSkeletonWorkforce = (_E = value.withSkeletonWorkforce) != null ? _E : null;
|
|
3516
|
+
this.skeletonWorkforce = (_F = value.skeletonWorkforce) != null ? _F : "";
|
|
3517
|
+
this.roles = (_G = value.roles) != null ? _G : [];
|
|
3518
|
+
this.rolesRate = (_H = value.rolesRate) != null ? _H : [];
|
|
3519
|
+
this.skills = (_I = value.skills) != null ? _I : [];
|
|
3520
|
+
this.skillsRate = (_J = value.skillsRate) != null ? _J : [];
|
|
3521
|
+
this.resourceEfficiencyRate = (_K = value.resourceEfficiencyRate) != null ? _K : [];
|
|
3522
|
+
this.AOOR = (_L = value.AOOR) != null ? _L : [];
|
|
3523
|
+
this.AOOS = (_M = value.AOOS) != null ? _M : [];
|
|
3524
|
+
this.status = (_N = value.status) != null ? _N : "draft";
|
|
3525
|
+
if (value.createdBy instanceof ObjectId16) {
|
|
3526
|
+
try {
|
|
3527
|
+
value.createdBy = new ObjectId16(value.createdBy);
|
|
3528
|
+
} catch (error) {
|
|
3529
|
+
throw new Error("Invalid createdBy ObjectId.");
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3532
|
+
this.createdBy = value.createdBy;
|
|
3533
|
+
this.createdAt = (_O = value.createdAt) != null ? _O : (/* @__PURE__ */ new Date()).toISOString();
|
|
3534
|
+
this.updatedAt = (_P = value.updatedAt) != null ? _P : "";
|
|
3535
|
+
this.deletedAt = (_Q = value.deletedAt) != null ? _Q : "";
|
|
3536
|
+
}
|
|
3537
|
+
};
|
|
3538
|
+
|
|
3539
|
+
// src/repositories/cap-bldg-act.repository.ts
|
|
3540
|
+
import { ObjectId as ObjectId17 } from "mongodb";
|
|
3541
|
+
import {
|
|
3542
|
+
BadRequestError as BadRequestError18,
|
|
3543
|
+
InternalServerError as InternalServerError17,
|
|
3544
|
+
logger as logger9,
|
|
3545
|
+
paginate as paginate7,
|
|
3546
|
+
useAtlas as useAtlas12
|
|
3547
|
+
} from "@goweekdays/utils";
|
|
3548
|
+
function useCapBldgActRepo() {
|
|
3549
|
+
const db = useAtlas12.getDb();
|
|
3550
|
+
if (!db) {
|
|
3551
|
+
throw new InternalServerError17("Unable to connect to server.");
|
|
3552
|
+
}
|
|
3553
|
+
const collection = db.collection("cap-bldg-acts");
|
|
3554
|
+
function createIndex() {
|
|
3555
|
+
return __async(this, null, function* () {
|
|
3556
|
+
try {
|
|
3557
|
+
yield collection.createIndex({ title: 1 });
|
|
3558
|
+
yield collection.createIndex({ subject: 1 });
|
|
3559
|
+
yield collection.createIndex({ type: 1 });
|
|
3560
|
+
yield collection.createIndex({ status: 1 });
|
|
3561
|
+
} catch (error) {
|
|
3562
|
+
throw new Error("Failed to create index for cap-bldg-acts.");
|
|
3563
|
+
}
|
|
3564
|
+
});
|
|
3565
|
+
}
|
|
3566
|
+
function createTextIndex() {
|
|
3567
|
+
return __async(this, null, function* () {
|
|
3568
|
+
try {
|
|
3569
|
+
yield collection.createIndex({
|
|
3570
|
+
title: "text",
|
|
3571
|
+
subject: "text",
|
|
3572
|
+
type: "text"
|
|
3573
|
+
});
|
|
3574
|
+
} catch (error) {
|
|
3575
|
+
throw new Error("Failed to create text index on cap-bldg-acts.");
|
|
3576
|
+
}
|
|
3577
|
+
});
|
|
3578
|
+
}
|
|
3579
|
+
function createCapBldgAct(value, session) {
|
|
3580
|
+
return __async(this, null, function* () {
|
|
3581
|
+
try {
|
|
3582
|
+
value = new MCapBldgAct(value);
|
|
3583
|
+
const res = yield collection.insertOne(value, {
|
|
3584
|
+
session
|
|
3585
|
+
});
|
|
3586
|
+
return res.insertedId.toString();
|
|
3587
|
+
} catch (error) {
|
|
3588
|
+
logger9.log({ level: "error", message: `${error}` });
|
|
3589
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
3590
|
+
if (isDuplicated) {
|
|
3591
|
+
throw new BadRequestError18("CapBldgAct name already exists.");
|
|
3592
|
+
}
|
|
3593
|
+
throw new InternalServerError17("Failed to create CapBldgAct.");
|
|
3594
|
+
}
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3597
|
+
function updateCapBldgActBasicInfo() {
|
|
3598
|
+
return __async(this, arguments, function* ({ _id, value } = {}, session) {
|
|
3599
|
+
try {
|
|
3600
|
+
_id = new ObjectId17(_id);
|
|
3601
|
+
} catch (error) {
|
|
3602
|
+
throw new BadRequestError18("Invalid CapBldgAct ID.");
|
|
3603
|
+
}
|
|
3604
|
+
try {
|
|
3605
|
+
yield collection.updateOne(
|
|
3606
|
+
{ _id },
|
|
3607
|
+
{ $set: value },
|
|
3608
|
+
{
|
|
3609
|
+
session
|
|
3610
|
+
}
|
|
3611
|
+
);
|
|
3612
|
+
} catch (error) {
|
|
3613
|
+
logger9.log({ level: "error", message: `${error}` });
|
|
3614
|
+
throw new InternalServerError17("Failed to update CapBldgAct basic info.");
|
|
3615
|
+
}
|
|
3616
|
+
});
|
|
3617
|
+
}
|
|
3618
|
+
function updateCapBldgActInitRevEval() {
|
|
3619
|
+
return __async(this, arguments, function* ({ _id, value } = {}, session) {
|
|
3620
|
+
try {
|
|
3621
|
+
_id = new ObjectId17(_id);
|
|
3622
|
+
} catch (error) {
|
|
3623
|
+
throw new BadRequestError18("Invalid CapBldgAct ID.");
|
|
3624
|
+
}
|
|
3625
|
+
try {
|
|
3626
|
+
yield collection.updateOne(
|
|
3627
|
+
{ _id },
|
|
3628
|
+
{ $set: value },
|
|
3629
|
+
{
|
|
3630
|
+
session
|
|
3631
|
+
}
|
|
3632
|
+
);
|
|
3633
|
+
} catch (error) {
|
|
3634
|
+
logger9.log({ level: "error", message: `${error}` });
|
|
3635
|
+
throw new InternalServerError17(
|
|
3636
|
+
"Failed to update CapBldgAct initial review and evaluation."
|
|
3637
|
+
);
|
|
3638
|
+
}
|
|
3639
|
+
});
|
|
3640
|
+
}
|
|
3641
|
+
function updateCapBldgActAssmtCriteria() {
|
|
3642
|
+
return __async(this, arguments, function* ({ _id, value } = {}, session) {
|
|
3643
|
+
try {
|
|
3644
|
+
_id = new ObjectId17(_id);
|
|
3645
|
+
} catch (error) {
|
|
3646
|
+
throw new BadRequestError18("Invalid CapBldgAct ID.");
|
|
3647
|
+
}
|
|
3648
|
+
try {
|
|
3649
|
+
yield collection.updateOne(
|
|
3650
|
+
{ _id },
|
|
3651
|
+
{ $set: value },
|
|
3652
|
+
{
|
|
3653
|
+
session
|
|
3654
|
+
}
|
|
3655
|
+
);
|
|
3656
|
+
} catch (error) {
|
|
3657
|
+
logger9.log({ level: "error", message: `${error}` });
|
|
3658
|
+
throw new InternalServerError17(
|
|
3659
|
+
"Failed to update CapBldgAct assessment criteria."
|
|
3660
|
+
);
|
|
3661
|
+
}
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
function getById(_id) {
|
|
3665
|
+
return __async(this, null, function* () {
|
|
3666
|
+
try {
|
|
3667
|
+
_id = new ObjectId17(_id);
|
|
3668
|
+
} catch (error) {
|
|
3669
|
+
throw new BadRequestError18("Invalid CapBldgAct ID.");
|
|
3670
|
+
}
|
|
3671
|
+
try {
|
|
3672
|
+
return yield collection.findOne({ _id });
|
|
3673
|
+
} catch (error) {
|
|
3674
|
+
logger9.log({ level: "error", message: `${error}` });
|
|
3675
|
+
throw new InternalServerError17("Failed to create CapBldgAct.");
|
|
3676
|
+
}
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3679
|
+
function getCapBldgActs() {
|
|
3680
|
+
return __async(this, arguments, function* ({
|
|
3681
|
+
search = "",
|
|
3682
|
+
page = 1,
|
|
3683
|
+
limit = 10,
|
|
3684
|
+
sort = {},
|
|
3685
|
+
status = "draft"
|
|
3686
|
+
} = {}) {
|
|
3687
|
+
page = page > 0 ? page - 1 : 0;
|
|
3688
|
+
const query = { status };
|
|
3689
|
+
if (status === "ongoing") {
|
|
3690
|
+
query.status = {
|
|
3691
|
+
$in: [
|
|
3692
|
+
"for-internal-review",
|
|
3693
|
+
"for-initial-evaluation",
|
|
3694
|
+
"for-endorsement",
|
|
3695
|
+
"for-final-review",
|
|
3696
|
+
"for-final-evaluation",
|
|
3697
|
+
"for-clearance",
|
|
3698
|
+
"for-signature",
|
|
3699
|
+
"for-approval"
|
|
3700
|
+
]
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
3703
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
3704
|
+
if (search) {
|
|
3705
|
+
query.$text = { $search: search };
|
|
3706
|
+
}
|
|
3707
|
+
try {
|
|
3708
|
+
const items = yield collection.aggregate([
|
|
3709
|
+
{ $match: query },
|
|
3710
|
+
{ $sort: sort },
|
|
3711
|
+
{ $skip: page * limit },
|
|
3712
|
+
{ $limit: limit }
|
|
3713
|
+
]).toArray();
|
|
3714
|
+
const length = yield collection.countDocuments(query);
|
|
3715
|
+
return paginate7(items, page, limit, length);
|
|
3716
|
+
} catch (error) {
|
|
3717
|
+
logger9.log({ level: "error", message: `${error}` });
|
|
3718
|
+
throw error;
|
|
3719
|
+
}
|
|
3720
|
+
});
|
|
3721
|
+
}
|
|
3722
|
+
function updateCapBldgActFieldById() {
|
|
3723
|
+
return __async(this, arguments, function* ({ _id, field, value } = {}, session) {
|
|
3724
|
+
const allowedFields = [
|
|
3725
|
+
"completeStaffWorkReport",
|
|
3726
|
+
"ATC",
|
|
3727
|
+
"certOfFundAvailability",
|
|
3728
|
+
"conceptNote",
|
|
3729
|
+
"budgetProposal",
|
|
3730
|
+
"PRCFormsTemplate",
|
|
3731
|
+
"HGDGTool",
|
|
3732
|
+
"EXECOMLeadEndorsement",
|
|
3733
|
+
"skeletonWorkforce",
|
|
3734
|
+
"status"
|
|
3735
|
+
];
|
|
3736
|
+
if (!allowedFields.includes(field)) {
|
|
3737
|
+
throw new BadRequestError18(
|
|
3738
|
+
`Field "${field}" is not allowed to be updated.`
|
|
3739
|
+
);
|
|
3740
|
+
}
|
|
3741
|
+
try {
|
|
3742
|
+
_id = new ObjectId17(_id);
|
|
3743
|
+
} catch (error) {
|
|
3744
|
+
throw new BadRequestError18("Invalid ID.");
|
|
3745
|
+
}
|
|
3746
|
+
try {
|
|
3747
|
+
yield collection.updateOne(
|
|
3748
|
+
{ _id },
|
|
3749
|
+
{ $set: { [field]: value } },
|
|
3750
|
+
// Dynamically set the field
|
|
3751
|
+
{ session }
|
|
3752
|
+
);
|
|
3753
|
+
return `Successfully updated CapBldgAct ${field}.`;
|
|
3754
|
+
} catch (error) {
|
|
3755
|
+
throw new InternalServerError17(`Failed to update CapBldgAct ${field}.`);
|
|
3756
|
+
}
|
|
3757
|
+
});
|
|
3758
|
+
}
|
|
3759
|
+
function deleteCapBldgAct(_id) {
|
|
3760
|
+
return __async(this, null, function* () {
|
|
3761
|
+
try {
|
|
3762
|
+
_id = new ObjectId17(_id);
|
|
3763
|
+
} catch (error) {
|
|
3764
|
+
throw new BadRequestError18("Invalid CapBldgAct ID.");
|
|
3765
|
+
}
|
|
3766
|
+
try {
|
|
3767
|
+
return yield collection.updateOne(
|
|
3768
|
+
{ _id },
|
|
3769
|
+
{ $set: { status: "deleted", deletedAt: (/* @__PURE__ */ new Date()).toISOString() } }
|
|
3770
|
+
);
|
|
3771
|
+
} catch (error) {
|
|
3772
|
+
return Promise.reject(error);
|
|
3773
|
+
}
|
|
3774
|
+
});
|
|
3775
|
+
}
|
|
3776
|
+
return {
|
|
3777
|
+
createIndex,
|
|
3778
|
+
createTextIndex,
|
|
3779
|
+
createCapBldgAct,
|
|
3780
|
+
getById,
|
|
3781
|
+
getCapBldgActs,
|
|
3782
|
+
updateCapBldgActFieldById,
|
|
3783
|
+
deleteCapBldgAct,
|
|
3784
|
+
updateCapBldgActBasicInfo,
|
|
3785
|
+
updateCapBldgActInitRevEval,
|
|
3786
|
+
updateCapBldgActAssmtCriteria
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
// src/services/cap-bldg-act.service.ts
|
|
3791
|
+
import { useAtlas as useAtlas13, useS3 as useS34 } from "@goweekdays/utils";
|
|
3792
|
+
function useCapBldgActService() {
|
|
3793
|
+
const {
|
|
3794
|
+
createCapBldgAct: _createCapBldgAct,
|
|
3795
|
+
getCapBldgActs: _getCapBldgActs,
|
|
3796
|
+
getById: _getById,
|
|
3797
|
+
updateCapBldgActFieldById: _updateCapBldgActFieldById,
|
|
3798
|
+
deleteCapBldgAct: _deleteCapBldgAct,
|
|
3799
|
+
updateCapBldgActBasicInfo: _updateCapBldgActBasicInfo,
|
|
3800
|
+
updateCapBldgActInitRevEval: _updateCapBldgActInitRevEval,
|
|
3801
|
+
updateCapBldgActAssmtCriteria: _updateCapBldgActAssmt
|
|
3802
|
+
} = useCapBldgActRepo();
|
|
3803
|
+
function createCapBldgAct(value) {
|
|
3804
|
+
return __async(this, null, function* () {
|
|
3805
|
+
try {
|
|
3806
|
+
value = new MCapBldgAct(value);
|
|
3807
|
+
return yield _createCapBldgAct(value);
|
|
3808
|
+
} catch (error) {
|
|
3809
|
+
throw error;
|
|
3810
|
+
}
|
|
3811
|
+
});
|
|
3812
|
+
}
|
|
3813
|
+
function updateCapBldgActBasicInfo(_id, value) {
|
|
3814
|
+
return __async(this, null, function* () {
|
|
3815
|
+
try {
|
|
3816
|
+
return yield _updateCapBldgActBasicInfo({ _id, value });
|
|
3817
|
+
} catch (error) {
|
|
3818
|
+
throw error;
|
|
3819
|
+
}
|
|
3820
|
+
});
|
|
3821
|
+
}
|
|
3822
|
+
function updateCapBldgActInitRevEval(_id, value) {
|
|
3823
|
+
return __async(this, null, function* () {
|
|
3824
|
+
try {
|
|
3825
|
+
return yield _updateCapBldgActInitRevEval({ _id, value });
|
|
3826
|
+
} catch (error) {
|
|
3827
|
+
throw error;
|
|
3828
|
+
}
|
|
3829
|
+
});
|
|
3830
|
+
}
|
|
3831
|
+
function updateCapBldgActAssmtCriteria(_id, value) {
|
|
3832
|
+
return __async(this, null, function* () {
|
|
3833
|
+
try {
|
|
3834
|
+
return yield _updateCapBldgActAssmt({ _id, value });
|
|
3835
|
+
} catch (error) {
|
|
3836
|
+
throw error;
|
|
3837
|
+
}
|
|
3838
|
+
});
|
|
3839
|
+
}
|
|
3840
|
+
function getCapBldgActs() {
|
|
3841
|
+
return __async(this, arguments, function* ({
|
|
3842
|
+
search = "",
|
|
3843
|
+
page = 1,
|
|
3844
|
+
status = "",
|
|
3845
|
+
limit = 10
|
|
3846
|
+
} = {}) {
|
|
3847
|
+
try {
|
|
3848
|
+
return yield _getCapBldgActs({ search, page, status, limit });
|
|
3849
|
+
} catch (error) {
|
|
3850
|
+
throw error;
|
|
3851
|
+
}
|
|
3852
|
+
});
|
|
3853
|
+
}
|
|
3854
|
+
function getById(id) {
|
|
3855
|
+
return __async(this, null, function* () {
|
|
3856
|
+
try {
|
|
3857
|
+
return yield _getById(id);
|
|
3858
|
+
} catch (error) {
|
|
3859
|
+
throw error;
|
|
3860
|
+
}
|
|
3861
|
+
});
|
|
3862
|
+
}
|
|
3863
|
+
function updateCapBldgActFieldById() {
|
|
3864
|
+
return __async(this, arguments, function* ({
|
|
3865
|
+
_id = "",
|
|
3866
|
+
field = "",
|
|
3867
|
+
value = ""
|
|
3868
|
+
} = {}) {
|
|
3869
|
+
try {
|
|
3870
|
+
return yield _updateCapBldgActFieldById({ _id, field, value });
|
|
3871
|
+
} catch (error) {
|
|
3872
|
+
throw error;
|
|
3873
|
+
}
|
|
3874
|
+
});
|
|
3875
|
+
}
|
|
3876
|
+
function deleteCapBldgAct(id) {
|
|
3877
|
+
return __async(this, null, function* () {
|
|
3878
|
+
try {
|
|
3879
|
+
return yield _deleteCapBldgAct(id);
|
|
3880
|
+
} catch (error) {
|
|
3881
|
+
throw error;
|
|
3882
|
+
}
|
|
3883
|
+
});
|
|
3884
|
+
}
|
|
3885
|
+
const s3 = new useS34({
|
|
3886
|
+
accessKeyId: SPACES_ACCESS_KEY,
|
|
3887
|
+
secretAccessKey: SPACES_SECRET_KEY,
|
|
3888
|
+
endpoint: SPACES_ENDPOINT,
|
|
3889
|
+
region: SPACES_REGION,
|
|
3890
|
+
bucket: SPACES_BUCKET
|
|
3891
|
+
});
|
|
3892
|
+
const { createFile: _createFile, deleteFileById } = useFileRepo();
|
|
3893
|
+
function uploadAttachment(value, id, field) {
|
|
3894
|
+
return __async(this, null, function* () {
|
|
3895
|
+
var _a;
|
|
3896
|
+
const session = (_a = useAtlas13.getClient()) == null ? void 0 : _a.startSession();
|
|
3897
|
+
session == null ? void 0 : session.startTransaction();
|
|
3898
|
+
const file = {
|
|
3899
|
+
name: value.originalname,
|
|
3900
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3901
|
+
};
|
|
3902
|
+
try {
|
|
3903
|
+
const _id = yield _createFile(file, session);
|
|
3904
|
+
yield s3.uploadObject({
|
|
3905
|
+
key: _id,
|
|
3906
|
+
body: value.buffer,
|
|
3907
|
+
contentType: value.mimetype
|
|
3908
|
+
});
|
|
3909
|
+
yield _updateCapBldgActFieldById({ _id: id, field, value: _id }, session);
|
|
3910
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
3911
|
+
return id;
|
|
3912
|
+
} catch (error) {
|
|
3913
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
3914
|
+
throw error;
|
|
3915
|
+
} finally {
|
|
3916
|
+
session == null ? void 0 : session.endSession();
|
|
3917
|
+
}
|
|
3918
|
+
});
|
|
3919
|
+
}
|
|
3920
|
+
function deleteAttachment(attachment, id, field) {
|
|
3921
|
+
return __async(this, null, function* () {
|
|
3922
|
+
var _a;
|
|
3923
|
+
const session = (_a = useAtlas13.getClient()) == null ? void 0 : _a.startSession();
|
|
3924
|
+
session == null ? void 0 : session.startTransaction();
|
|
3925
|
+
try {
|
|
3926
|
+
yield deleteFileById(attachment, session);
|
|
3927
|
+
yield _updateCapBldgActFieldById({ _id: id, field, value: "" }, session);
|
|
3928
|
+
yield s3.deleteObject(attachment);
|
|
3929
|
+
yield session == null ? void 0 : session.commitTransaction();
|
|
3930
|
+
return "Attachment successfully deleted.";
|
|
3931
|
+
} catch (error) {
|
|
3932
|
+
yield session == null ? void 0 : session.abortTransaction();
|
|
3933
|
+
throw error;
|
|
3934
|
+
} finally {
|
|
3935
|
+
session == null ? void 0 : session.endSession();
|
|
3936
|
+
}
|
|
3937
|
+
});
|
|
3938
|
+
}
|
|
3939
|
+
return {
|
|
3940
|
+
createCapBldgAct,
|
|
3941
|
+
getCapBldgActs,
|
|
3942
|
+
getById,
|
|
3943
|
+
updateCapBldgActFieldById,
|
|
3944
|
+
deleteCapBldgAct,
|
|
3945
|
+
updateCapBldgActBasicInfo,
|
|
3946
|
+
updateCapBldgActInitRevEval,
|
|
3947
|
+
updateCapBldgActAssmtCriteria,
|
|
3948
|
+
uploadAttachment,
|
|
3949
|
+
deleteAttachment
|
|
3950
|
+
};
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
// src/controllers/cap-bldg-act.controller.ts
|
|
3954
|
+
import Joi8 from "joi";
|
|
3955
|
+
import { BadRequestError as BadRequestError19 } from "@goweekdays/utils";
|
|
3956
|
+
function useCapBldgActController() {
|
|
3957
|
+
const {
|
|
3958
|
+
createCapBldgAct: _createCapBldgAct,
|
|
3959
|
+
getCapBldgActs: _getCapBldgActs,
|
|
3960
|
+
getById: _getById,
|
|
3961
|
+
updateCapBldgActBasicInfo: _updateBasicInformation,
|
|
3962
|
+
updateCapBldgActInitRevEval: _updateInitRevEval,
|
|
3963
|
+
updateCapBldgActAssmtCriteria: _updateAssmtCriteria,
|
|
3964
|
+
updateCapBldgActFieldById: _updateFieldById,
|
|
3965
|
+
uploadAttachment: _uploadAttachment,
|
|
3966
|
+
deleteAttachment: _deleteAttachment
|
|
3967
|
+
} = useCapBldgActService();
|
|
3968
|
+
function createCapBldgAct(req, res, next) {
|
|
3969
|
+
return __async(this, null, function* () {
|
|
3970
|
+
const value = req.body;
|
|
3971
|
+
const validation = Joi8.object({
|
|
3972
|
+
title: Joi8.string().required(),
|
|
3973
|
+
subject: Joi8.string().required(),
|
|
3974
|
+
PMISActivityCode: Joi8.string().required(),
|
|
3975
|
+
type: Joi8.string().required(),
|
|
3976
|
+
strandMandateAddressed: Joi8.string().required(),
|
|
3977
|
+
objectives: Joi8.array().items(Joi8.string()).min(3).max(3).required(),
|
|
3978
|
+
withCPDUnits: Joi8.boolean().required(),
|
|
3979
|
+
createdBy: Joi8.string().hex().required()
|
|
3980
|
+
});
|
|
3981
|
+
const { error } = validation.validate(value);
|
|
3982
|
+
if (error) {
|
|
3983
|
+
next(new BadRequestError19(error.message));
|
|
3984
|
+
return;
|
|
3985
|
+
}
|
|
3986
|
+
try {
|
|
3987
|
+
yield _createCapBldgAct(value);
|
|
3988
|
+
res.json({ message: "Successfully created CBA request." });
|
|
3989
|
+
return;
|
|
3990
|
+
} catch (error2) {
|
|
3991
|
+
next(error2);
|
|
3992
|
+
}
|
|
3993
|
+
});
|
|
3994
|
+
}
|
|
3995
|
+
function updateBasicInformation(req, res, next) {
|
|
3996
|
+
return __async(this, null, function* () {
|
|
3997
|
+
var _a;
|
|
3998
|
+
const value = req.body;
|
|
3999
|
+
const id = (_a = req.params.id) != null ? _a : "";
|
|
4000
|
+
const validation = Joi8.object({
|
|
4001
|
+
id: Joi8.string().hex().required(),
|
|
4002
|
+
title: Joi8.string().required(),
|
|
4003
|
+
subject: Joi8.string().required(),
|
|
4004
|
+
PMISActivityCode: Joi8.string().required(),
|
|
4005
|
+
type: Joi8.string().required(),
|
|
4006
|
+
strandMandateAddressed: Joi8.string().required(),
|
|
4007
|
+
objectives: Joi8.array().items(Joi8.string()).min(3).max(3).required(),
|
|
4008
|
+
withCPDUnits: Joi8.boolean().required()
|
|
4009
|
+
});
|
|
4010
|
+
const { error } = validation.validate(__spreadProps(__spreadValues({}, value), { id }));
|
|
4011
|
+
if (error) {
|
|
4012
|
+
next(new BadRequestError19(error.message));
|
|
4013
|
+
return;
|
|
4014
|
+
}
|
|
4015
|
+
try {
|
|
4016
|
+
yield _updateBasicInformation(id, value);
|
|
4017
|
+
res.json({ message: "Successfully updated CBA basic information." });
|
|
4018
|
+
return;
|
|
4019
|
+
} catch (error2) {
|
|
4020
|
+
next(error2);
|
|
4021
|
+
}
|
|
4022
|
+
});
|
|
4023
|
+
}
|
|
4024
|
+
function updateInitRevEval(req, res, next) {
|
|
4025
|
+
return __async(this, null, function* () {
|
|
4026
|
+
var _a;
|
|
4027
|
+
const value = req.body;
|
|
4028
|
+
const id = (_a = req.params.id) != null ? _a : "";
|
|
4029
|
+
const NTP = Joi8.object({
|
|
4030
|
+
teaching: Joi8.number().required(),
|
|
4031
|
+
nonteaching: Joi8.number().required(),
|
|
4032
|
+
teachingRelated: Joi8.number().required()
|
|
4033
|
+
}).required();
|
|
4034
|
+
const tentative = Joi8.object({
|
|
4035
|
+
month: Joi8.string().required(),
|
|
4036
|
+
day: Joi8.number().required()
|
|
4037
|
+
}).required();
|
|
4038
|
+
const list = Joi8.array().items(Joi8.string()).min(3).max(3).required();
|
|
4039
|
+
const validation = Joi8.object({
|
|
4040
|
+
id: Joi8.string().hex().required(),
|
|
4041
|
+
completeStaffWorkReport: Joi8.string().required(),
|
|
4042
|
+
withATC: Joi8.boolean().required(),
|
|
4043
|
+
ATC: Joi8.string().required(),
|
|
4044
|
+
conceptNote: Joi8.string().required(),
|
|
4045
|
+
certOfFundAvailability: Joi8.string().required(),
|
|
4046
|
+
budgetProposal: Joi8.string().required(),
|
|
4047
|
+
targets: list,
|
|
4048
|
+
PRCFormsTemplate: Joi8.string().required(),
|
|
4049
|
+
HGDGTool: Joi8.string().required(),
|
|
4050
|
+
EXECOMLeadEndorsement: Joi8.string().required(),
|
|
4051
|
+
individualResults: list,
|
|
4052
|
+
organizationalResults: list,
|
|
4053
|
+
indicative: Joi8.string().required(),
|
|
4054
|
+
tentative,
|
|
4055
|
+
tentativeOption: tentative,
|
|
4056
|
+
tentativeYear: Joi8.number().required(),
|
|
4057
|
+
GADAttrRate: Joi8.number().required(),
|
|
4058
|
+
GADAttrRateAmount: Joi8.number().required(),
|
|
4059
|
+
NTPCO: NTP,
|
|
4060
|
+
NTPRO: NTP,
|
|
4061
|
+
NTPSDO: NTP,
|
|
4062
|
+
NTPSchool: NTP,
|
|
4063
|
+
withSkeletonWorkforce: Joi8.boolean().required(),
|
|
4064
|
+
skeletonWorkforce: Joi8.string().required()
|
|
4065
|
+
});
|
|
4066
|
+
const { error } = validation.validate(__spreadProps(__spreadValues({}, value), { id }));
|
|
4067
|
+
if (error) {
|
|
4068
|
+
next(new BadRequestError19(error.message));
|
|
4069
|
+
return;
|
|
4070
|
+
}
|
|
4071
|
+
try {
|
|
4072
|
+
yield _updateInitRevEval(id, value);
|
|
4073
|
+
res.json({
|
|
4074
|
+
message: "Successfully updated CBA initial review and evaluation."
|
|
4075
|
+
});
|
|
4076
|
+
return;
|
|
4077
|
+
} catch (error2) {
|
|
4078
|
+
next(error2);
|
|
4079
|
+
}
|
|
4080
|
+
});
|
|
4081
|
+
}
|
|
4082
|
+
function updateAssmtCriteria(req, res, next) {
|
|
4083
|
+
return __async(this, null, function* () {
|
|
4084
|
+
var _a;
|
|
4085
|
+
const value = req.body;
|
|
4086
|
+
const id = (_a = req.params.id) != null ? _a : "";
|
|
4087
|
+
const list = Joi8.array().items(Joi8.string()).min(3).max(3).required();
|
|
4088
|
+
const listOptional = Joi8.array().items(Joi8.number().optional().allow(null)).optional().min(0).max(3);
|
|
4089
|
+
const validation = Joi8.object({
|
|
4090
|
+
id: Joi8.string().hex().required(),
|
|
4091
|
+
roles: list,
|
|
4092
|
+
rolesRate: listOptional,
|
|
4093
|
+
skills: list,
|
|
4094
|
+
skillsRate: listOptional,
|
|
4095
|
+
resourceEfficiencyRate: listOptional,
|
|
4096
|
+
AOOR: Joi8.array().items(Joi8.number().optional().allow(null)).optional().min(0).max(5),
|
|
4097
|
+
AOOS: Joi8.array().items(Joi8.string().optional().allow(null)).min(0).max(5)
|
|
4098
|
+
});
|
|
4099
|
+
const { error } = validation.validate(__spreadProps(__spreadValues({}, value), { id }));
|
|
4100
|
+
if (error) {
|
|
4101
|
+
next(new BadRequestError19(error.message));
|
|
4102
|
+
return;
|
|
4103
|
+
}
|
|
4104
|
+
try {
|
|
4105
|
+
yield _updateAssmtCriteria(id, value);
|
|
4106
|
+
res.json({
|
|
4107
|
+
message: "Successfully updated CBA assessment criteria."
|
|
4108
|
+
});
|
|
4109
|
+
return;
|
|
4110
|
+
} catch (error2) {
|
|
4111
|
+
next(error2);
|
|
4112
|
+
}
|
|
4113
|
+
});
|
|
4114
|
+
}
|
|
4115
|
+
function getCapBldgActs(req, res, next) {
|
|
4116
|
+
return __async(this, null, function* () {
|
|
4117
|
+
var _a, _b;
|
|
4118
|
+
const search = (_a = req.query.search) != null ? _a : "";
|
|
4119
|
+
const page = req.query.page ? Number(req.query.page) : 1;
|
|
4120
|
+
const limit = req.query.limit ? Number(req.query.limit) : 10;
|
|
4121
|
+
const status = (_b = req.query.status) != null ? _b : "";
|
|
4122
|
+
const validation = Joi8.object({
|
|
4123
|
+
search: Joi8.string().allow(""),
|
|
4124
|
+
page: Joi8.number().min(1),
|
|
4125
|
+
limit: Joi8.number().min(1),
|
|
4126
|
+
status: Joi8.string().allow("")
|
|
4127
|
+
});
|
|
4128
|
+
const { error } = validation.validate(req.query);
|
|
4129
|
+
if (error) {
|
|
4130
|
+
next(new BadRequestError19(error.message));
|
|
4131
|
+
return;
|
|
4132
|
+
}
|
|
4133
|
+
try {
|
|
4134
|
+
const data = yield _getCapBldgActs({ search, page, limit, status });
|
|
4135
|
+
res.json(data);
|
|
4136
|
+
return;
|
|
4137
|
+
} catch (error2) {
|
|
4138
|
+
next(error2);
|
|
4139
|
+
}
|
|
4140
|
+
});
|
|
4141
|
+
}
|
|
4142
|
+
function getById(req, res, next) {
|
|
4143
|
+
return __async(this, null, function* () {
|
|
4144
|
+
const { id } = req.params;
|
|
4145
|
+
const validation = Joi8.object({
|
|
4146
|
+
id: Joi8.string().required()
|
|
4147
|
+
});
|
|
4148
|
+
const { error } = validation.validate({ id });
|
|
4149
|
+
if (error) {
|
|
4150
|
+
next(new BadRequestError19(error.message));
|
|
4151
|
+
return;
|
|
4152
|
+
}
|
|
4153
|
+
try {
|
|
4154
|
+
const data = yield _getById(id);
|
|
4155
|
+
res.json(data);
|
|
4156
|
+
return;
|
|
4157
|
+
} catch (error2) {
|
|
4158
|
+
next(error2);
|
|
4159
|
+
}
|
|
4160
|
+
});
|
|
4161
|
+
}
|
|
4162
|
+
function updateFieldById(req, res, next) {
|
|
4163
|
+
return __async(this, null, function* () {
|
|
4164
|
+
const _id = req.params.id;
|
|
4165
|
+
const { field, value } = req.body;
|
|
4166
|
+
const validation = Joi8.object({
|
|
4167
|
+
_id: Joi8.string().hex().required(),
|
|
4168
|
+
field: Joi8.string().valid(
|
|
4169
|
+
"completeStaffWorkReport",
|
|
4170
|
+
"ATC",
|
|
4171
|
+
"certOfFundAvailability",
|
|
4172
|
+
"conceptNote",
|
|
4173
|
+
"budgetProposal",
|
|
4174
|
+
"PRCFormsTemplate",
|
|
4175
|
+
"HGDGTool",
|
|
4176
|
+
"EXECOMLeadEndorsement",
|
|
4177
|
+
"skeletonWorkforce",
|
|
4178
|
+
"status"
|
|
4179
|
+
).required(),
|
|
4180
|
+
value: Joi8.string().required()
|
|
4181
|
+
});
|
|
4182
|
+
const { error } = validation.validate({ _id, field, value });
|
|
4183
|
+
if (error) {
|
|
4184
|
+
next(new BadRequestError19(error.message));
|
|
4185
|
+
return;
|
|
4186
|
+
}
|
|
4187
|
+
try {
|
|
4188
|
+
const message = yield _updateFieldById({ _id, field, value });
|
|
4189
|
+
res.json({ message });
|
|
4190
|
+
} catch (error2) {
|
|
4191
|
+
next(error2);
|
|
4192
|
+
}
|
|
4193
|
+
});
|
|
4194
|
+
}
|
|
4195
|
+
function uploadAttachment(req, res, next) {
|
|
4196
|
+
return __async(this, null, function* () {
|
|
4197
|
+
const file = req.file;
|
|
4198
|
+
if (!file) {
|
|
4199
|
+
res.status(400).send("File is required!");
|
|
4200
|
+
return;
|
|
4201
|
+
}
|
|
4202
|
+
const id = req.params.id;
|
|
4203
|
+
const field = req.body.field;
|
|
4204
|
+
const validation = Joi8.object({
|
|
4205
|
+
id: Joi8.string().required(),
|
|
4206
|
+
field: Joi8.string().required()
|
|
4207
|
+
});
|
|
4208
|
+
const { error } = validation.validate({ id, field });
|
|
4209
|
+
if (error) {
|
|
4210
|
+
next(new BadRequestError19(error.message));
|
|
4211
|
+
return;
|
|
4212
|
+
}
|
|
4213
|
+
try {
|
|
4214
|
+
const _file = yield _uploadAttachment(file, id, field);
|
|
4215
|
+
res.json({ message: "Successfully uploaded attachment.", id: _file });
|
|
4216
|
+
return;
|
|
4217
|
+
} catch (error2) {
|
|
4218
|
+
next(error2);
|
|
4219
|
+
}
|
|
4220
|
+
});
|
|
4221
|
+
}
|
|
4222
|
+
function deleteAttachment(req, res, next) {
|
|
4223
|
+
return __async(this, null, function* () {
|
|
4224
|
+
var _a, _b;
|
|
4225
|
+
const id = req.params.id;
|
|
4226
|
+
const attachment = (_a = req.body.attachment) != null ? _a : "";
|
|
4227
|
+
const field = (_b = req.body.field) != null ? _b : "";
|
|
4228
|
+
const validation = Joi8.string().required();
|
|
4229
|
+
const { error } = validation.validate(id);
|
|
4230
|
+
if (error) {
|
|
4231
|
+
next(new BadRequestError19(error.message));
|
|
4232
|
+
}
|
|
4233
|
+
try {
|
|
4234
|
+
const message = yield _deleteAttachment(attachment, id, field);
|
|
4235
|
+
res.json({ message });
|
|
4236
|
+
return;
|
|
4237
|
+
} catch (error2) {
|
|
4238
|
+
next(error2);
|
|
4239
|
+
}
|
|
4240
|
+
});
|
|
4241
|
+
}
|
|
4242
|
+
return {
|
|
4243
|
+
createCapBldgAct,
|
|
4244
|
+
getCapBldgActs,
|
|
4245
|
+
getById,
|
|
4246
|
+
updateBasicInformation,
|
|
4247
|
+
updateInitRevEval,
|
|
4248
|
+
updateAssmtCriteria,
|
|
4249
|
+
updateFieldById,
|
|
4250
|
+
uploadAttachment,
|
|
4251
|
+
deleteAttachment
|
|
4252
|
+
};
|
|
4253
|
+
}
|
|
4254
|
+
|
|
4255
|
+
// src/models/comment.model.ts
|
|
4256
|
+
import { ObjectId as ObjectId18 } from "mongodb";
|
|
4257
|
+
var MComment = class {
|
|
4258
|
+
constructor(value) {
|
|
4259
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
4260
|
+
this._id = (_a = value._id) != null ? _a : new ObjectId18();
|
|
4261
|
+
this.comment = (_b = value.comment) != null ? _b : "";
|
|
4262
|
+
this.type = (_c = value.type) != null ? _c : "common";
|
|
4263
|
+
if (typeof value.user === "string") {
|
|
4264
|
+
try {
|
|
4265
|
+
value.user = new ObjectId18(value.user);
|
|
4266
|
+
} catch (error) {
|
|
4267
|
+
throw new Error("Invalid user ID.");
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
this.user = (_d = value.user) != null ? _d : "";
|
|
4271
|
+
this.collection = (_e = value.collection) != null ? _e : "";
|
|
4272
|
+
if (typeof value.document === "string") {
|
|
4273
|
+
try {
|
|
4274
|
+
value.document = new ObjectId18(value.document);
|
|
4275
|
+
} catch (error) {
|
|
4276
|
+
throw new Error("Invalid document ID.");
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
this.document = value.document;
|
|
4280
|
+
this.createdAt = (_f = value.createdAt) != null ? _f : (/* @__PURE__ */ new Date()).toISOString();
|
|
4281
|
+
this.updatedAt = (_g = value.updatedAt) != null ? _g : "";
|
|
4282
|
+
this.deletedAt = (_h = value.deletedAt) != null ? _h : "";
|
|
4283
|
+
}
|
|
4284
|
+
};
|
|
4285
|
+
|
|
4286
|
+
// src/repositories/comment.repository.ts
|
|
4287
|
+
import { ObjectId as ObjectId19 } from "mongodb";
|
|
4288
|
+
import {
|
|
4289
|
+
InternalServerError as InternalServerError18,
|
|
4290
|
+
logger as logger10,
|
|
4291
|
+
paginate as paginate8,
|
|
4292
|
+
useAtlas as useAtlas14
|
|
4293
|
+
} from "@goweekdays/utils";
|
|
4294
|
+
function useCommentRepo() {
|
|
4295
|
+
const db = useAtlas14.getDb();
|
|
4296
|
+
if (!db) {
|
|
4297
|
+
throw new Error("Database not initialized");
|
|
4298
|
+
}
|
|
4299
|
+
const collection = db.collection("comments");
|
|
4300
|
+
function createIndex() {
|
|
4301
|
+
return __async(this, null, function* () {
|
|
4302
|
+
try {
|
|
4303
|
+
yield collection.createIndex({ deletedAt: 1, document: 1 });
|
|
4304
|
+
} catch (error) {
|
|
4305
|
+
throw new Error("Failed to create index for cap-bldg-acts.");
|
|
4306
|
+
}
|
|
4307
|
+
});
|
|
4308
|
+
}
|
|
4309
|
+
function addComment(value) {
|
|
4310
|
+
return __async(this, null, function* () {
|
|
4311
|
+
try {
|
|
4312
|
+
value = new MComment(value);
|
|
4313
|
+
yield collection.insertOne(value);
|
|
4314
|
+
return "Comment added successfully.";
|
|
4315
|
+
} catch (error) {
|
|
4316
|
+
throw new InternalServerError18("Failed to add comment.");
|
|
4317
|
+
}
|
|
4318
|
+
});
|
|
4319
|
+
}
|
|
4320
|
+
function getComments() {
|
|
4321
|
+
return __async(this, arguments, function* ({ search = "", page = 1, limit = 10, sort = {}, document = "" } = {}) {
|
|
4322
|
+
page = page > 0 ? page - 1 : 0;
|
|
4323
|
+
if (document) {
|
|
4324
|
+
try {
|
|
4325
|
+
document = new ObjectId19(document);
|
|
4326
|
+
} catch (error) {
|
|
4327
|
+
throw new Error("Invalid document ID.");
|
|
4328
|
+
}
|
|
4329
|
+
}
|
|
4330
|
+
const query = { deletedAt: "", document };
|
|
4331
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: 1 };
|
|
4332
|
+
if (search) {
|
|
4333
|
+
query.$text = { $search: search };
|
|
4334
|
+
}
|
|
4335
|
+
try {
|
|
4336
|
+
const items = yield collection.aggregate([
|
|
4337
|
+
{ $match: query },
|
|
4338
|
+
{ $sort: sort },
|
|
4339
|
+
{ $skip: page * limit },
|
|
4340
|
+
{ $limit: limit }
|
|
4341
|
+
]).toArray();
|
|
4342
|
+
const length = yield collection.countDocuments(query);
|
|
4343
|
+
return paginate8(items, page, limit, length);
|
|
4344
|
+
} catch (error) {
|
|
4345
|
+
logger10.log({ level: "error", message: `${error}` });
|
|
4346
|
+
throw error;
|
|
4347
|
+
}
|
|
4348
|
+
});
|
|
4349
|
+
}
|
|
4350
|
+
return {
|
|
4351
|
+
createIndex,
|
|
4352
|
+
addComment,
|
|
4353
|
+
getComments
|
|
4354
|
+
};
|
|
4355
|
+
}
|
|
4356
|
+
|
|
4357
|
+
// src/services/comment.service.ts
|
|
4358
|
+
function useCommentService() {
|
|
4359
|
+
const { addComment: _addComment, getComments: _getComments } = useCommentRepo();
|
|
4360
|
+
function addComment() {
|
|
4361
|
+
return __async(this, arguments, function* ({ comment, type, user, collection, document } = {}) {
|
|
4362
|
+
try {
|
|
4363
|
+
return yield _addComment({
|
|
4364
|
+
comment,
|
|
4365
|
+
type,
|
|
4366
|
+
user,
|
|
4367
|
+
collection,
|
|
4368
|
+
document
|
|
4369
|
+
});
|
|
4370
|
+
} catch (error) {
|
|
4371
|
+
throw error;
|
|
4372
|
+
}
|
|
4373
|
+
});
|
|
4374
|
+
}
|
|
4375
|
+
function getComments() {
|
|
4376
|
+
return __async(this, arguments, function* ({ page = 1, document = "" } = {}) {
|
|
4377
|
+
try {
|
|
4378
|
+
return yield _getComments({ page, document });
|
|
4379
|
+
} catch (error) {
|
|
4380
|
+
throw error;
|
|
4381
|
+
}
|
|
4382
|
+
});
|
|
4383
|
+
}
|
|
4384
|
+
return {
|
|
4385
|
+
addComment,
|
|
4386
|
+
getComments
|
|
4387
|
+
};
|
|
4388
|
+
}
|
|
4389
|
+
|
|
4390
|
+
// src/controllers/comment.controller.ts
|
|
4391
|
+
import Joi9 from "joi";
|
|
4392
|
+
import { BadRequestError as BadRequestError20 } from "@goweekdays/utils";
|
|
4393
|
+
function useCommentController() {
|
|
4394
|
+
const { addComment: _addComment, getComments: _getComments } = useCommentService();
|
|
4395
|
+
function addComment(req, res, next) {
|
|
4396
|
+
return __async(this, null, function* () {
|
|
4397
|
+
const value = req.body;
|
|
4398
|
+
const validation = Joi9.object({
|
|
4399
|
+
comment: Joi9.string().required(),
|
|
4400
|
+
type: Joi9.string().valid("comment", "approve", "request-changes"),
|
|
4401
|
+
user: Joi9.string().hex().required(),
|
|
4402
|
+
collection: Joi9.string().required(),
|
|
4403
|
+
document: Joi9.string().hex().required()
|
|
4404
|
+
});
|
|
4405
|
+
const { error } = validation.validate(value);
|
|
4406
|
+
if (error) {
|
|
4407
|
+
next(new BadRequestError20(error.message));
|
|
4408
|
+
return;
|
|
4409
|
+
}
|
|
4410
|
+
try {
|
|
4411
|
+
yield _addComment({
|
|
4412
|
+
comment: value.comment,
|
|
4413
|
+
type: value.type,
|
|
4414
|
+
user: value.user,
|
|
4415
|
+
collection: value.collection,
|
|
4416
|
+
document: value.document
|
|
4417
|
+
});
|
|
4418
|
+
res.json({ message: "Successfully added comment." });
|
|
4419
|
+
return;
|
|
4420
|
+
} catch (error2) {
|
|
4421
|
+
next(error2);
|
|
4422
|
+
return;
|
|
4423
|
+
}
|
|
4424
|
+
});
|
|
4425
|
+
}
|
|
4426
|
+
function getComments(req, res, next) {
|
|
4427
|
+
return __async(this, null, function* () {
|
|
4428
|
+
var _a, _b;
|
|
4429
|
+
const page = (_a = Number(req.query.page)) != null ? _a : 1;
|
|
4430
|
+
const document = (_b = req.query.document) != null ? _b : "";
|
|
4431
|
+
const validation = Joi9.object({
|
|
4432
|
+
page: Joi9.number().min(1),
|
|
4433
|
+
document: Joi9.string().hex().required()
|
|
4434
|
+
});
|
|
4435
|
+
const { error } = validation.validate({ page, document });
|
|
4436
|
+
if (error) {
|
|
4437
|
+
next(new BadRequestError20(error.message));
|
|
4438
|
+
return;
|
|
4439
|
+
}
|
|
4440
|
+
try {
|
|
4441
|
+
const comments = yield _getComments({ page, document });
|
|
4442
|
+
res.json(comments);
|
|
4443
|
+
return;
|
|
4444
|
+
} catch (error2) {
|
|
4445
|
+
next(error2);
|
|
4446
|
+
return;
|
|
4447
|
+
}
|
|
4448
|
+
});
|
|
4449
|
+
}
|
|
4450
|
+
return {
|
|
4451
|
+
addComment,
|
|
4452
|
+
getComments
|
|
4453
|
+
};
|
|
4454
|
+
}
|
|
4455
|
+
export {
|
|
4456
|
+
ACCESS_TOKEN_EXPIRY,
|
|
4457
|
+
ACCESS_TOKEN_SECRET,
|
|
4458
|
+
APP_ACCOUNT,
|
|
4459
|
+
AppError,
|
|
4460
|
+
BadRequestError,
|
|
4461
|
+
DEFAULT_USER_EMAIL,
|
|
4462
|
+
DEFAULT_USER_FIRST_NAME,
|
|
4463
|
+
DEFAULT_USER_LAST_NAME,
|
|
4464
|
+
DEFAULT_USER_PASSWORD,
|
|
4465
|
+
InternalServerError,
|
|
4466
|
+
MAILER_EMAIL,
|
|
4467
|
+
MAILER_PASSWORD,
|
|
4468
|
+
MAILER_TRANSPORT_HOST,
|
|
4469
|
+
MAILER_TRANSPORT_PORT,
|
|
4470
|
+
MAILER_TRANSPORT_SECURE,
|
|
4471
|
+
MCapBldgAct,
|
|
4472
|
+
MComment,
|
|
4473
|
+
MEntity,
|
|
4474
|
+
MFile,
|
|
4475
|
+
MONGO_DB,
|
|
4476
|
+
MONGO_URI,
|
|
4477
|
+
MRole,
|
|
4478
|
+
MToken,
|
|
4479
|
+
MUser,
|
|
4480
|
+
MUserRole,
|
|
4481
|
+
MVerification,
|
|
4482
|
+
MWorkflow,
|
|
4483
|
+
NotFoundError,
|
|
4484
|
+
PORT,
|
|
4485
|
+
REDIS_HOST,
|
|
4486
|
+
REDIS_PASSWORD,
|
|
4487
|
+
REDIS_PORT,
|
|
4488
|
+
REFRESH_TOKEN_EXPIRY,
|
|
4489
|
+
REFRESH_TOKEN_SECRET,
|
|
4490
|
+
SECRET_KEY,
|
|
4491
|
+
SPACES_ACCESS_KEY,
|
|
4492
|
+
SPACES_BUCKET,
|
|
4493
|
+
SPACES_ENDPOINT,
|
|
4494
|
+
SPACES_REGION,
|
|
4495
|
+
SPACES_SECRET_KEY,
|
|
4496
|
+
UnauthorizedError,
|
|
4497
|
+
VERIFICATION_FORGET_PASSWORD_DURATION,
|
|
4498
|
+
VERIFICATION_USER_INVITE_DURATION,
|
|
4499
|
+
authMiddleware,
|
|
4500
|
+
comparePassword,
|
|
4501
|
+
compileHandlebar,
|
|
4502
|
+
errorHandler,
|
|
4503
|
+
generateToken,
|
|
4504
|
+
getDirectory,
|
|
4505
|
+
hashPassword,
|
|
4506
|
+
initRedisClient,
|
|
4507
|
+
isDev,
|
|
4508
|
+
logger,
|
|
4509
|
+
paginate,
|
|
4510
|
+
prependZeros,
|
|
4511
|
+
toObjectId,
|
|
4512
|
+
useAtlas,
|
|
4513
|
+
useAuthController,
|
|
4514
|
+
useAuthService,
|
|
4515
|
+
useCapBldgActController,
|
|
4516
|
+
useCapBldgActRepo,
|
|
4517
|
+
useCapBldgActService,
|
|
4518
|
+
useCommentController,
|
|
4519
|
+
useCommentRepo,
|
|
4520
|
+
useCommentService,
|
|
4521
|
+
useEntityController,
|
|
4522
|
+
useEntityRepo,
|
|
4523
|
+
useEntityService,
|
|
4524
|
+
useFileController,
|
|
4525
|
+
useFileRepo,
|
|
4526
|
+
useFileService,
|
|
4527
|
+
useMailer,
|
|
4528
|
+
useRedisClient,
|
|
4529
|
+
useRoleController,
|
|
4530
|
+
useRoleRepo,
|
|
4531
|
+
useRoleService,
|
|
4532
|
+
useS3,
|
|
4533
|
+
useTokenRepo,
|
|
4534
|
+
useUserController,
|
|
4535
|
+
useUserRepo,
|
|
4536
|
+
useUserService,
|
|
4537
|
+
useVerificationController,
|
|
4538
|
+
useVerificationRepo,
|
|
4539
|
+
useVerificationService,
|
|
4540
|
+
useWorkflowController,
|
|
4541
|
+
useWorkflowRepo,
|
|
4542
|
+
useWorkflowService
|
|
4543
|
+
};
|
|
4544
|
+
//# sourceMappingURL=index.mjs.map
|