@7365admin1/core 2.29.0 → 2.30.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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +140 -47
- package/dist/index.js +1131 -510
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1141 -520
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1419,7 +1419,7 @@ import {
|
|
|
1419
1419
|
import { ObjectId as ObjectId6 } from "mongodb";
|
|
1420
1420
|
import Joi5 from "joi";
|
|
1421
1421
|
var schemaOccurrenceEntry = Joi5.object({
|
|
1422
|
-
site: Joi5.string().hex().required(),
|
|
1422
|
+
site: Joi5.string().hex().length(24).required(),
|
|
1423
1423
|
dailyOccurrenceBookId: Joi5.string().hex().optional().allow(null, ""),
|
|
1424
1424
|
serialNumber: Joi5.string().optional().allow(null, ""),
|
|
1425
1425
|
date: Joi5.date().iso().optional().allow(null, ""),
|
|
@@ -1431,14 +1431,14 @@ var schemaOccurrenceEntry = Joi5.object({
|
|
|
1431
1431
|
createdByName: Joi5.string().optional().allow(null, "")
|
|
1432
1432
|
});
|
|
1433
1433
|
var schemaUpdateOccurrenceEntry = Joi5.object({
|
|
1434
|
-
_id: Joi5.string().hex().required(),
|
|
1434
|
+
_id: Joi5.string().hex().length(24).required(),
|
|
1435
1435
|
serialNumber: Joi5.string().optional().allow(null, ""),
|
|
1436
1436
|
date: Joi5.date().iso().optional().allow(null, ""),
|
|
1437
1437
|
subject: Joi5.string().hex().optional().allow(null, ""),
|
|
1438
1438
|
occurrence: Joi5.string().optional().allow(null, ""),
|
|
1439
1439
|
signature: Joi5.string().hex().optional().allow(null, ""),
|
|
1440
1440
|
incidentReportId: Joi5.string().hex().optional().allow(null, ""),
|
|
1441
|
-
eSignature: Joi5.string().
|
|
1441
|
+
eSignature: Joi5.string().hex().length(24).optional().allow(null, ""),
|
|
1442
1442
|
createdByName: Joi5.string().optional().allow(null, "")
|
|
1443
1443
|
});
|
|
1444
1444
|
function MOccurrenceEntry(value) {
|
|
@@ -1484,6 +1484,13 @@ function MOccurrenceEntry(value) {
|
|
|
1484
1484
|
throw new Error("Invalid incident report ID.");
|
|
1485
1485
|
}
|
|
1486
1486
|
}
|
|
1487
|
+
if (value.eSignature && typeof value.eSignature === "string") {
|
|
1488
|
+
try {
|
|
1489
|
+
value.eSignature = new ObjectId6(value.eSignature);
|
|
1490
|
+
} catch {
|
|
1491
|
+
throw new Error("Invalid incident report ID.");
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1487
1494
|
return {
|
|
1488
1495
|
_id: value._id ?? new ObjectId6(),
|
|
1489
1496
|
site: value.site,
|
|
@@ -1840,32 +1847,16 @@ function useOccurrenceEntryRepo() {
|
|
|
1840
1847
|
throw error;
|
|
1841
1848
|
}
|
|
1842
1849
|
}
|
|
1843
|
-
async function getOccurrenceEntryByBookId(dailyOccurrenceBookId
|
|
1850
|
+
async function getOccurrenceEntryByBookId(dailyOccurrenceBookId) {
|
|
1844
1851
|
try {
|
|
1845
1852
|
dailyOccurrenceBookId = new ObjectId7(dailyOccurrenceBookId);
|
|
1846
1853
|
} catch (error) {
|
|
1847
1854
|
throw new BadRequestError7("Invalid occurrence entry ID format.");
|
|
1848
1855
|
}
|
|
1849
|
-
const
|
|
1850
|
-
dailyOccurrenceBookId
|
|
1851
|
-
});
|
|
1852
|
-
const cachedData = await getCache(cacheKey);
|
|
1853
|
-
if (cachedData) {
|
|
1854
|
-
logger6.info(`Cache hit for key: ${cacheKey}`);
|
|
1855
|
-
return cachedData;
|
|
1856
|
-
}
|
|
1856
|
+
const query = { dailyOccurrenceBookId };
|
|
1857
1857
|
try {
|
|
1858
|
-
const data = await collection.findOne(
|
|
1859
|
-
{
|
|
1860
|
-
{
|
|
1861
|
-
sort: { _id: -1 },
|
|
1862
|
-
session
|
|
1863
|
-
}
|
|
1864
|
-
);
|
|
1865
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
1866
|
-
logger6.info(`Cache set for key: ${cacheKey}`);
|
|
1867
|
-
}).catch((err) => {
|
|
1868
|
-
logger6.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1858
|
+
const data = await collection.findOne(query, {
|
|
1859
|
+
sort: { _id: -1 }
|
|
1869
1860
|
});
|
|
1870
1861
|
return data;
|
|
1871
1862
|
} catch (error) {
|
|
@@ -12876,12 +12867,9 @@ import Joi40 from "joi";
|
|
|
12876
12867
|
import {
|
|
12877
12868
|
BadRequestError as BadRequestError66,
|
|
12878
12869
|
InternalServerError as InternalServerError23,
|
|
12879
|
-
logger as logger47,
|
|
12880
|
-
makeCacheKey as makeCacheKey22,
|
|
12881
12870
|
paginate as paginate17,
|
|
12882
12871
|
toObjectId as toObjectId6,
|
|
12883
|
-
useAtlas as useAtlas30
|
|
12884
|
-
useCache as useCache23
|
|
12872
|
+
useAtlas as useAtlas30
|
|
12885
12873
|
} from "@7365admin1/node-server-utils";
|
|
12886
12874
|
|
|
12887
12875
|
// src/models/visitor-transactions.model.ts
|
|
@@ -12901,6 +12889,7 @@ var PersonTypes = /* @__PURE__ */ ((PersonTypes3) => {
|
|
|
12901
12889
|
PersonTypes3["GUEST"] = "guest";
|
|
12902
12890
|
PersonTypes3["TENANT"] = "tenant";
|
|
12903
12891
|
PersonTypes3["RESIDENT"] = "resident";
|
|
12892
|
+
PersonTypes3["VISITOR"] = "visitor";
|
|
12904
12893
|
return PersonTypes3;
|
|
12905
12894
|
})(PersonTypes || {});
|
|
12906
12895
|
var PersonStatus = /* @__PURE__ */ ((PersonStatus2) => {
|
|
@@ -13088,7 +13077,6 @@ var schemaVisitorTransaction = Joi36.object({
|
|
|
13088
13077
|
contact: Joi36.string().optional().allow(null, "")
|
|
13089
13078
|
})
|
|
13090
13079
|
).optional().allow(null),
|
|
13091
|
-
visitorPass: Joi36.string().optional().allow(null, ""),
|
|
13092
13080
|
unitName: Joi36.string().optional().allow(null, ""),
|
|
13093
13081
|
expiredAt: Joi36.date().iso().optional().allow(null, ""),
|
|
13094
13082
|
arrivalTime: Joi36.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
|
|
@@ -13097,7 +13085,15 @@ var schemaVisitorTransaction = Joi36.object({
|
|
|
13097
13085
|
duration: Joi36.number().integer().optional().allow(null),
|
|
13098
13086
|
isOvernightParking: Joi36.boolean().optional().default(false),
|
|
13099
13087
|
email: Joi36.string().email().optional().allow(null, ""),
|
|
13100
|
-
numberOfPassengers: Joi36.number().integer().optional().allow(null, "")
|
|
13088
|
+
numberOfPassengers: Joi36.number().integer().optional().allow(null, ""),
|
|
13089
|
+
visitorPass: Joi36.array().items(
|
|
13090
|
+
Joi36.string().hex().length(24).optional().allow(null)
|
|
13091
|
+
),
|
|
13092
|
+
passKeys: Joi36.array().items(
|
|
13093
|
+
Joi36.string().hex().length(24).optional().allow(null)
|
|
13094
|
+
),
|
|
13095
|
+
checkInRemarks: Joi36.string().optional().allow("", null),
|
|
13096
|
+
checkOutRemarks: Joi36.string().optional().allow("", null)
|
|
13101
13097
|
});
|
|
13102
13098
|
var schemaUpdateVisTrans = Joi36.object({
|
|
13103
13099
|
_id: Joi36.string().hex().length(24).required(),
|
|
@@ -13123,7 +13119,15 @@ var schemaUpdateVisTrans = Joi36.object({
|
|
|
13123
13119
|
status: Joi36.string().optional().allow(null, ""),
|
|
13124
13120
|
remarks: Joi36.string().optional().allow(null, ""),
|
|
13125
13121
|
manualCheckout: Joi36.boolean().optional().allow(null),
|
|
13126
|
-
expiredAt: Joi36.date().iso().optional().allow(null, "")
|
|
13122
|
+
expiredAt: Joi36.date().iso().optional().allow(null, ""),
|
|
13123
|
+
visitorPass: Joi36.array().items(
|
|
13124
|
+
Joi36.string().hex().length(24).optional().allow(null)
|
|
13125
|
+
),
|
|
13126
|
+
passKeys: Joi36.array().items(
|
|
13127
|
+
Joi36.string().hex().length(24).optional().allow(null)
|
|
13128
|
+
),
|
|
13129
|
+
checkInRemarks: Joi36.string().optional().allow("", null),
|
|
13130
|
+
checkOutRemarks: Joi36.string().optional().allow("", null)
|
|
13127
13131
|
});
|
|
13128
13132
|
function MVisitorTransaction(value) {
|
|
13129
13133
|
const { error } = schemaVisitorTransaction.validate(value, {
|
|
@@ -13167,6 +13171,14 @@ function MVisitorTransaction(value) {
|
|
|
13167
13171
|
throw new Error("Invalid type for manualCheckout key.");
|
|
13168
13172
|
}
|
|
13169
13173
|
}
|
|
13174
|
+
if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0)
|
|
13175
|
+
value.visitorPass = value.visitorPass.map(
|
|
13176
|
+
(v) => typeof v === "string" ? new ObjectId39(v) : v
|
|
13177
|
+
);
|
|
13178
|
+
if (value.passKeys && Array.isArray(value.passKeys) && value.passKeys.length > 0)
|
|
13179
|
+
value.passKeys = value.passKeys.map(
|
|
13180
|
+
(p) => typeof p === "string" ? new ObjectId39(p) : p
|
|
13181
|
+
);
|
|
13170
13182
|
const newDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
13171
13183
|
return {
|
|
13172
13184
|
_id: value._id,
|
|
@@ -13193,7 +13205,10 @@ function MVisitorTransaction(value) {
|
|
|
13193
13205
|
contractorType: value.contractorType,
|
|
13194
13206
|
manualCheckout: value.manualCheckout ?? false,
|
|
13195
13207
|
direction: value.direction,
|
|
13196
|
-
visitorPass: value.visitorPass,
|
|
13208
|
+
visitorPass: value.visitorPass ?? [],
|
|
13209
|
+
passKeys: value.passKeys ?? [],
|
|
13210
|
+
checkInRemarks: value.checkInRemarks,
|
|
13211
|
+
checkOutRemarks: value.checkOutRemarks,
|
|
13197
13212
|
unitName: value.unitName,
|
|
13198
13213
|
expiredAt: value.expiredAt ?? null,
|
|
13199
13214
|
createdAt: value.createdAt ?? newDate,
|
|
@@ -13211,9 +13226,6 @@ function useVisitorTransactionRepo() {
|
|
|
13211
13226
|
throw new InternalServerError23("Unable to connect to server.");
|
|
13212
13227
|
}
|
|
13213
13228
|
const collection = db.collection(visitors_namespace_collection);
|
|
13214
|
-
const { delNamespace, getCache, setCache } = useCache23(
|
|
13215
|
-
visitors_namespace_collection
|
|
13216
|
-
);
|
|
13217
13229
|
async function createTextIndex() {
|
|
13218
13230
|
try {
|
|
13219
13231
|
await collection.createIndex({
|
|
@@ -13234,16 +13246,6 @@ function useVisitorTransactionRepo() {
|
|
|
13234
13246
|
try {
|
|
13235
13247
|
value = MVisitorTransaction(value);
|
|
13236
13248
|
const res = await collection.insertOne(value, { session });
|
|
13237
|
-
delNamespace().then(() => {
|
|
13238
|
-
logger47.info(
|
|
13239
|
-
`Cache cleared for namespace: ${visitors_namespace_collection}`
|
|
13240
|
-
);
|
|
13241
|
-
}).catch((err) => {
|
|
13242
|
-
logger47.error(
|
|
13243
|
-
`Failed to clear cache for namespace: ${visitors_namespace_collection}`,
|
|
13244
|
-
err
|
|
13245
|
-
);
|
|
13246
|
-
});
|
|
13247
13249
|
return res.insertedId;
|
|
13248
13250
|
} catch (error) {
|
|
13249
13251
|
const isDuplicated = error.message.includes("duplicate");
|
|
@@ -13266,7 +13268,7 @@ function useVisitorTransactionRepo() {
|
|
|
13266
13268
|
type = "",
|
|
13267
13269
|
checkedOut,
|
|
13268
13270
|
plateNumber = ""
|
|
13269
|
-
}
|
|
13271
|
+
}) {
|
|
13270
13272
|
page = page > 0 ? page - 1 : 0;
|
|
13271
13273
|
const skip = page * limit;
|
|
13272
13274
|
let checkOutFilter;
|
|
@@ -13301,26 +13303,6 @@ function useVisitorTransactionRepo() {
|
|
|
13301
13303
|
...plateNumber && { plateNumber }
|
|
13302
13304
|
};
|
|
13303
13305
|
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
13304
|
-
const cacheOptions = {
|
|
13305
|
-
status,
|
|
13306
|
-
page,
|
|
13307
|
-
limit,
|
|
13308
|
-
sort: JSON.stringify(sort),
|
|
13309
|
-
...search && { search },
|
|
13310
|
-
...query.org && { org: query.org.toString() },
|
|
13311
|
-
...query.site && { site: query.site.toString() },
|
|
13312
|
-
...checkIn && { checkIn: JSON.stringify(checkIn) },
|
|
13313
|
-
...checkOutFilter && { checkOut: JSON.stringify(checkOutFilter) },
|
|
13314
|
-
...type && (Array.isArray(type) ? { type: JSON.stringify(type) } : { type }),
|
|
13315
|
-
...checkedOut !== void 0 && { checkedOut },
|
|
13316
|
-
...plateNumber && { plateNumber }
|
|
13317
|
-
};
|
|
13318
|
-
const cacheKey = makeCacheKey22(visitors_namespace_collection, cacheOptions);
|
|
13319
|
-
const cachedData = await getCache(cacheKey);
|
|
13320
|
-
if (cachedData) {
|
|
13321
|
-
logger47.info(`Cache hit for key: ${cacheKey}`);
|
|
13322
|
-
return cachedData;
|
|
13323
|
-
}
|
|
13324
13306
|
try {
|
|
13325
13307
|
const basePipeline = [{ $match: query }];
|
|
13326
13308
|
const [items, countResult] = await Promise.all([
|
|
@@ -13364,23 +13346,12 @@ function useVisitorTransactionRepo() {
|
|
|
13364
13346
|
]);
|
|
13365
13347
|
const totalCount = countResult[0]?.total || 0;
|
|
13366
13348
|
const data = paginate17(items, page, limit, totalCount);
|
|
13367
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
13368
|
-
logger47.info(`Cache set for key: ${cacheKey}`);
|
|
13369
|
-
}).catch((err) => {
|
|
13370
|
-
logger47.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
13371
|
-
});
|
|
13372
13349
|
return data;
|
|
13373
13350
|
} catch (error) {
|
|
13374
13351
|
throw error;
|
|
13375
13352
|
}
|
|
13376
13353
|
}
|
|
13377
13354
|
async function getVisitorTransactionById(id) {
|
|
13378
|
-
const cacheKey = makeCacheKey22(visitors_namespace_collection, { id });
|
|
13379
|
-
const cachedData = await getCache(cacheKey);
|
|
13380
|
-
if (cachedData) {
|
|
13381
|
-
logger47.info(`Cache hit for key: ${cacheKey}`);
|
|
13382
|
-
return cachedData;
|
|
13383
|
-
}
|
|
13384
13355
|
const _id = toObjectId6(id);
|
|
13385
13356
|
try {
|
|
13386
13357
|
const basePipeline = [{ $match: { _id } }];
|
|
@@ -13417,38 +13388,20 @@ function useVisitorTransactionRepo() {
|
|
|
13417
13388
|
}
|
|
13418
13389
|
}
|
|
13419
13390
|
]).toArray();
|
|
13420
|
-
setCache(cacheKey, result, 15 * 60).then(() => {
|
|
13421
|
-
logger47.info(`Cache set for key: ${cacheKey}`);
|
|
13422
|
-
}).catch((err) => {
|
|
13423
|
-
logger47.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
13424
|
-
});
|
|
13425
13391
|
return result;
|
|
13426
13392
|
} catch (error) {
|
|
13427
13393
|
throw error;
|
|
13428
13394
|
}
|
|
13429
13395
|
}
|
|
13430
13396
|
async function getOpenByPlateNumber(plateNumber, site) {
|
|
13431
|
-
const _site = typeof site === "string" ? site :
|
|
13432
|
-
const
|
|
13397
|
+
const _site = typeof site === "string" ? toObjectId6(site) : site;
|
|
13398
|
+
const query = {
|
|
13433
13399
|
plateNumber,
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
}
|
|
13400
|
+
site: _site,
|
|
13401
|
+
checkOut: null
|
|
13402
|
+
};
|
|
13437
13403
|
try {
|
|
13438
|
-
const
|
|
13439
|
-
if (cacheData) {
|
|
13440
|
-
logger47.info(`Cache hit for key: ${cacheKey}`);
|
|
13441
|
-
return cacheData;
|
|
13442
|
-
}
|
|
13443
|
-
const data = await collection.findOne(
|
|
13444
|
-
{ plateNumber, site: _site, checkOut: null },
|
|
13445
|
-
{ sort: { _id: -1 } }
|
|
13446
|
-
);
|
|
13447
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
13448
|
-
logger47.info(`Cache set for key: ${cacheKey}`);
|
|
13449
|
-
}).catch((err) => {
|
|
13450
|
-
logger47.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
13451
|
-
});
|
|
13404
|
+
const data = await collection.findOne(query);
|
|
13452
13405
|
return data;
|
|
13453
13406
|
} catch (error) {
|
|
13454
13407
|
throw new InternalServerError23(
|
|
@@ -13472,16 +13425,6 @@ function useVisitorTransactionRepo() {
|
|
|
13472
13425
|
{ $set: value },
|
|
13473
13426
|
{ session }
|
|
13474
13427
|
);
|
|
13475
|
-
delNamespace().then(() => {
|
|
13476
|
-
logger47.info(
|
|
13477
|
-
`Cache cleared for namespace: ${visitors_namespace_collection}`
|
|
13478
|
-
);
|
|
13479
|
-
}).catch((err) => {
|
|
13480
|
-
logger47.error(
|
|
13481
|
-
`Failed to clear cache for namespace: ${visitors_namespace_collection}`,
|
|
13482
|
-
err
|
|
13483
|
-
);
|
|
13484
|
-
});
|
|
13485
13428
|
return result;
|
|
13486
13429
|
} catch (error) {
|
|
13487
13430
|
throw error;
|
|
@@ -13503,16 +13446,6 @@ function useVisitorTransactionRepo() {
|
|
|
13503
13446
|
if (res.modifiedCount === 0) {
|
|
13504
13447
|
throw new InternalServerError23("Unable to delete visitor transaction.");
|
|
13505
13448
|
}
|
|
13506
|
-
delNamespace().then(() => {
|
|
13507
|
-
logger47.info(
|
|
13508
|
-
`Cache cleared for namespace: ${visitors_namespace_collection}`
|
|
13509
|
-
);
|
|
13510
|
-
}).catch((err) => {
|
|
13511
|
-
logger47.error(
|
|
13512
|
-
`Failed to clear cache for namespace: ${visitors_namespace_collection}`,
|
|
13513
|
-
err
|
|
13514
|
-
);
|
|
13515
|
-
});
|
|
13516
13449
|
return res.modifiedCount;
|
|
13517
13450
|
} catch (error) {
|
|
13518
13451
|
throw error;
|
|
@@ -13578,16 +13511,6 @@ function useVisitorTransactionRepo() {
|
|
|
13578
13511
|
},
|
|
13579
13512
|
{ session }
|
|
13580
13513
|
);
|
|
13581
|
-
delNamespace().then(() => {
|
|
13582
|
-
logger47.info(
|
|
13583
|
-
`Cache cleared for namespace: ${visitors_namespace_collection}`
|
|
13584
|
-
);
|
|
13585
|
-
}).catch((err) => {
|
|
13586
|
-
logger47.error(
|
|
13587
|
-
`Failed to clear cache for namespace: ${visitors_namespace_collection}`,
|
|
13588
|
-
err
|
|
13589
|
-
);
|
|
13590
|
-
});
|
|
13591
13514
|
return res;
|
|
13592
13515
|
} catch (error) {
|
|
13593
13516
|
throw error;
|
|
@@ -13619,6 +13542,7 @@ var VehicleType = /* @__PURE__ */ ((VehicleType2) => {
|
|
|
13619
13542
|
var VehicleCategory = /* @__PURE__ */ ((VehicleCategory2) => {
|
|
13620
13543
|
VehicleCategory2["RESIDENT"] = "resident";
|
|
13621
13544
|
VehicleCategory2["VISITOR"] = "visitor";
|
|
13545
|
+
VehicleCategory2["GUEST"] = "guest";
|
|
13622
13546
|
return VehicleCategory2;
|
|
13623
13547
|
})(VehicleCategory || {});
|
|
13624
13548
|
var VehicleStatus = /* @__PURE__ */ ((VehicleStatus2) => {
|
|
@@ -13663,7 +13587,7 @@ var vehicleSchema = Joi37.object({
|
|
|
13663
13587
|
return value;
|
|
13664
13588
|
}).required(),
|
|
13665
13589
|
type: Joi37.string().required().valid(...Object.values(VehicleType)),
|
|
13666
|
-
category: Joi37.string().required().valid(...Object.values(
|
|
13590
|
+
category: Joi37.string().required().valid(...Object.values(PersonTypes)),
|
|
13667
13591
|
name: Joi37.string().required(),
|
|
13668
13592
|
phoneNumber: Joi37.string().optional().allow("", null),
|
|
13669
13593
|
recNo: Joi37.string().optional().allow("", null),
|
|
@@ -13801,12 +13725,10 @@ import {
|
|
|
13801
13725
|
BadRequestError as BadRequestError68,
|
|
13802
13726
|
InternalServerError as InternalServerError24,
|
|
13803
13727
|
logger as logger49,
|
|
13804
|
-
makeCacheKey as makeCacheKey23,
|
|
13805
13728
|
NotFoundError as NotFoundError17,
|
|
13806
13729
|
paginate as paginate18,
|
|
13807
13730
|
toObjectId as toObjectId7,
|
|
13808
|
-
useAtlas as useAtlas31
|
|
13809
|
-
useCache as useCache24
|
|
13731
|
+
useAtlas as useAtlas31
|
|
13810
13732
|
} from "@7365admin1/node-server-utils";
|
|
13811
13733
|
import { ObjectId as ObjectId42 } from "mongodb";
|
|
13812
13734
|
import Joi38 from "joi";
|
|
@@ -13818,9 +13740,6 @@ function useVehicleRepo() {
|
|
|
13818
13740
|
throw new InternalServerError24("Unable to connect to server.");
|
|
13819
13741
|
}
|
|
13820
13742
|
const collection = db.collection(vehicles_namespace_collection);
|
|
13821
|
-
const { delNamespace, setCache, getCache } = useCache24(
|
|
13822
|
-
vehicles_namespace_collection
|
|
13823
|
-
);
|
|
13824
13743
|
async function createIndex() {
|
|
13825
13744
|
try {
|
|
13826
13745
|
await collection.createIndexes([
|
|
@@ -13852,16 +13771,6 @@ function useVehicleRepo() {
|
|
|
13852
13771
|
try {
|
|
13853
13772
|
value = MVehicle(value);
|
|
13854
13773
|
const res = await collection.insertOne(value, { session });
|
|
13855
|
-
delNamespace().then(() => {
|
|
13856
|
-
logger49.info(
|
|
13857
|
-
`Cache cleared for namespace: ${vehicles_namespace_collection}`
|
|
13858
|
-
);
|
|
13859
|
-
}).catch((err) => {
|
|
13860
|
-
logger49.error(
|
|
13861
|
-
`Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
|
|
13862
|
-
err
|
|
13863
|
-
);
|
|
13864
|
-
});
|
|
13865
13774
|
return res.insertedId;
|
|
13866
13775
|
} catch (error) {
|
|
13867
13776
|
logger49.log({
|
|
@@ -13886,29 +13795,12 @@ function useVehicleRepo() {
|
|
|
13886
13795
|
}) {
|
|
13887
13796
|
page = page > 0 ? page - 1 : 0;
|
|
13888
13797
|
const baseQuery = {
|
|
13889
|
-
...status && { status },
|
|
13890
|
-
...type && { type },
|
|
13891
|
-
...category && { category }
|
|
13892
|
-
};
|
|
13893
|
-
let query = { ...baseQuery };
|
|
13894
|
-
const cacheOptions = {
|
|
13895
13798
|
...status && { status },
|
|
13896
13799
|
...type && { type },
|
|
13897
13800
|
...category && { category },
|
|
13898
|
-
|
|
13899
|
-
limit: String(limit),
|
|
13900
|
-
sort: JSON.stringify(sort)
|
|
13801
|
+
...search && { $text: { search } }
|
|
13901
13802
|
};
|
|
13902
|
-
|
|
13903
|
-
query.$text = { $search: search };
|
|
13904
|
-
cacheOptions.search = search;
|
|
13905
|
-
}
|
|
13906
|
-
const cacheKey = makeCacheKey23(vehicles_namespace_collection, cacheOptions);
|
|
13907
|
-
const cachedData = await getCache(cacheKey);
|
|
13908
|
-
if (cachedData) {
|
|
13909
|
-
logger49.info(`Cache hit for key: ${cacheKey}`);
|
|
13910
|
-
return cachedData;
|
|
13911
|
-
}
|
|
13803
|
+
let query = { ...baseQuery };
|
|
13912
13804
|
const escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13913
13805
|
const buildGroupedPipeline = (matchQuery) => [
|
|
13914
13806
|
{ $match: matchQuery },
|
|
@@ -14066,9 +13958,6 @@ function useVehicleRepo() {
|
|
|
14066
13958
|
length = regexCountResult[0]?.total || 0;
|
|
14067
13959
|
}
|
|
14068
13960
|
const data = paginate18(items, page, limit, length);
|
|
14069
|
-
setCache(cacheKey, data, 15 * 60).then(() => logger49.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
14070
|
-
(err) => logger49.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
14071
|
-
);
|
|
14072
13961
|
return data;
|
|
14073
13962
|
} catch (error) {
|
|
14074
13963
|
throw error;
|
|
@@ -14080,14 +13969,6 @@ function useVehicleRepo() {
|
|
|
14080
13969
|
} catch (error) {
|
|
14081
13970
|
throw new BadRequestError68("Invalid site ID format.");
|
|
14082
13971
|
}
|
|
14083
|
-
const cacheKey = makeCacheKey23(vehicles_namespace_collection, {
|
|
14084
|
-
site,
|
|
14085
|
-
type: "season-pass-type-as-options"
|
|
14086
|
-
});
|
|
14087
|
-
const cachedData = await getCache(cacheKey);
|
|
14088
|
-
if (cachedData) {
|
|
14089
|
-
return cachedData;
|
|
14090
|
-
}
|
|
14091
13972
|
try {
|
|
14092
13973
|
const categories = await collection.aggregate([
|
|
14093
13974
|
{ $match: { site } },
|
|
@@ -14107,17 +13988,6 @@ function useVehicleRepo() {
|
|
|
14107
13988
|
},
|
|
14108
13989
|
{ $sort: { title: 1 } }
|
|
14109
13990
|
]).toArray();
|
|
14110
|
-
setCache(cacheKey, categories).then(() => {
|
|
14111
|
-
logger49.log({
|
|
14112
|
-
level: "info",
|
|
14113
|
-
message: `Cache set for get season pass type: ${cacheKey}`
|
|
14114
|
-
});
|
|
14115
|
-
}).catch((err) => {
|
|
14116
|
-
logger49.log({
|
|
14117
|
-
level: "error",
|
|
14118
|
-
message: `Failed to set cache for season pass type: ${err.message}`
|
|
14119
|
-
});
|
|
14120
|
-
});
|
|
14121
13991
|
return categories;
|
|
14122
13992
|
} catch (error) {
|
|
14123
13993
|
if (error instanceof BadRequestError68) {
|
|
@@ -14133,12 +14003,6 @@ function useVehicleRepo() {
|
|
|
14133
14003
|
throw new BadRequestError68("Invalid vehicle ID format.");
|
|
14134
14004
|
}
|
|
14135
14005
|
try {
|
|
14136
|
-
const cacheKey = makeCacheKey23(vehicles_namespace_collection, { _id });
|
|
14137
|
-
const cachedData = await getCache(cacheKey);
|
|
14138
|
-
if (cachedData) {
|
|
14139
|
-
logger49.info(`Cache hit for key: ${cacheKey}`);
|
|
14140
|
-
return cachedData;
|
|
14141
|
-
}
|
|
14142
14006
|
const data = await collection.aggregate([
|
|
14143
14007
|
{ $match: { _id } },
|
|
14144
14008
|
{ $limit: 1 },
|
|
@@ -14308,11 +14172,6 @@ function useVehicleRepo() {
|
|
|
14308
14172
|
throw new NotFoundError17("Vehicle not found.");
|
|
14309
14173
|
}
|
|
14310
14174
|
const result = data[0];
|
|
14311
|
-
setCache(cacheKey, result, 15 * 60).then(() => {
|
|
14312
|
-
logger49.info(`Cache set for key: ${cacheKey}`);
|
|
14313
|
-
}).catch((err) => {
|
|
14314
|
-
logger49.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
14315
|
-
});
|
|
14316
14175
|
return result;
|
|
14317
14176
|
} catch (error) {
|
|
14318
14177
|
throw error;
|
|
@@ -14324,15 +14183,6 @@ function useVehicleRepo() {
|
|
|
14324
14183
|
throw new BadRequestError68(error.details[0].message);
|
|
14325
14184
|
}
|
|
14326
14185
|
try {
|
|
14327
|
-
const cacheKey = makeCacheKey23(vehicles_namespace_collection, {
|
|
14328
|
-
plateNumber: value,
|
|
14329
|
-
status: "active"
|
|
14330
|
-
});
|
|
14331
|
-
const cachedData = await getCache(cacheKey);
|
|
14332
|
-
if (cachedData) {
|
|
14333
|
-
logger49.info(`Cache hit for key: ${cacheKey}`);
|
|
14334
|
-
return cachedData;
|
|
14335
|
-
}
|
|
14336
14186
|
const data = await collection.findOne({
|
|
14337
14187
|
plateNumber: value,
|
|
14338
14188
|
status: "active"
|
|
@@ -14340,11 +14190,6 @@ function useVehicleRepo() {
|
|
|
14340
14190
|
if (!data) {
|
|
14341
14191
|
throw new NotFoundError17("Vehicle not found.");
|
|
14342
14192
|
}
|
|
14343
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
14344
|
-
logger49.info(`Cache set for key: ${cacheKey}`);
|
|
14345
|
-
}).catch((err) => {
|
|
14346
|
-
logger49.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
14347
|
-
});
|
|
14348
14193
|
return data;
|
|
14349
14194
|
} catch (error2) {
|
|
14350
14195
|
throw error2;
|
|
@@ -14369,16 +14214,6 @@ function useVehicleRepo() {
|
|
|
14369
14214
|
if (res.modifiedCount === 0) {
|
|
14370
14215
|
throw new InternalServerError24("Unable to update vehicle.");
|
|
14371
14216
|
}
|
|
14372
|
-
delNamespace().then(() => {
|
|
14373
|
-
logger49.info(
|
|
14374
|
-
`Cache cleared for namespace: ${vehicles_namespace_collection}`
|
|
14375
|
-
);
|
|
14376
|
-
}).catch((err) => {
|
|
14377
|
-
logger49.error(
|
|
14378
|
-
`Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
|
|
14379
|
-
err
|
|
14380
|
-
);
|
|
14381
|
-
});
|
|
14382
14217
|
return res.modifiedCount;
|
|
14383
14218
|
} catch (error) {
|
|
14384
14219
|
throw error;
|
|
@@ -14402,16 +14237,6 @@ function useVehicleRepo() {
|
|
|
14402
14237
|
);
|
|
14403
14238
|
if (res.modifiedCount === 0)
|
|
14404
14239
|
throw new InternalServerError24("Unable to delete vehicle.");
|
|
14405
|
-
delNamespace().then(() => {
|
|
14406
|
-
logger49.info(
|
|
14407
|
-
`Cache cleared for namespace: ${vehicles_namespace_collection}`
|
|
14408
|
-
);
|
|
14409
|
-
}).catch((err) => {
|
|
14410
|
-
logger49.error(
|
|
14411
|
-
`Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
|
|
14412
|
-
err
|
|
14413
|
-
);
|
|
14414
|
-
});
|
|
14415
14240
|
return res.modifiedCount;
|
|
14416
14241
|
} catch (error) {
|
|
14417
14242
|
throw error;
|
|
@@ -14422,25 +14247,11 @@ function useVehicleRepo() {
|
|
|
14422
14247
|
if (error) {
|
|
14423
14248
|
throw new BadRequestError68(error.details[0].message);
|
|
14424
14249
|
}
|
|
14425
|
-
const cacheKey = makeCacheKey23(vehicles_namespace_collection, {
|
|
14426
|
-
plateNumber,
|
|
14427
|
-
status: "active"
|
|
14428
|
-
});
|
|
14429
14250
|
try {
|
|
14430
|
-
const cacheData = await getCache(cacheKey);
|
|
14431
|
-
if (cacheData) {
|
|
14432
|
-
logger49.info(`Cache hit for key: ${cacheKey}`);
|
|
14433
|
-
return cacheData;
|
|
14434
|
-
}
|
|
14435
14251
|
const data = await collection.findOne(
|
|
14436
14252
|
{ plateNumber, status: "active" },
|
|
14437
14253
|
{ sort: { _id: -1 } }
|
|
14438
14254
|
);
|
|
14439
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
14440
|
-
logger49.info(`Cache set for key: ${cacheKey}`);
|
|
14441
|
-
}).catch((err) => {
|
|
14442
|
-
logger49.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
14443
|
-
});
|
|
14444
14255
|
return data;
|
|
14445
14256
|
} catch (error2) {
|
|
14446
14257
|
throw new InternalServerError24(
|
|
@@ -14464,19 +14275,6 @@ function useVehicleRepo() {
|
|
|
14464
14275
|
nric: _nric
|
|
14465
14276
|
};
|
|
14466
14277
|
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
14467
|
-
const cacheOptions = {
|
|
14468
|
-
deletedAt: "",
|
|
14469
|
-
nric: _nric,
|
|
14470
|
-
page: String(page),
|
|
14471
|
-
limit: String(limit),
|
|
14472
|
-
sort: JSON.stringify(sort)
|
|
14473
|
-
};
|
|
14474
|
-
const cacheKey = makeCacheKey23(vehicles_namespace_collection, cacheOptions);
|
|
14475
|
-
const cachedData = await getCache(cacheKey);
|
|
14476
|
-
if (cachedData) {
|
|
14477
|
-
logger49.info(`Cache hit for key: ${cacheKey}`);
|
|
14478
|
-
return cachedData;
|
|
14479
|
-
}
|
|
14480
14278
|
try {
|
|
14481
14279
|
const items = await collection.aggregate([
|
|
14482
14280
|
{ $match: query },
|
|
@@ -14497,9 +14295,6 @@ function useVehicleRepo() {
|
|
|
14497
14295
|
]).toArray();
|
|
14498
14296
|
const length = await collection.countDocuments(query);
|
|
14499
14297
|
const data = paginate18(items, page, limit, length);
|
|
14500
|
-
setCache(cacheKey, data, 15 * 60).then(() => logger49.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
14501
|
-
(err) => logger49.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
14502
|
-
);
|
|
14503
14298
|
return data;
|
|
14504
14299
|
} catch (error) {
|
|
14505
14300
|
throw error;
|
|
@@ -14514,19 +14309,9 @@ function useVehicleRepo() {
|
|
|
14514
14309
|
end: { $exists: true, $lte: now }
|
|
14515
14310
|
// check only end
|
|
14516
14311
|
},
|
|
14517
|
-
{ $set: { status: "deleted", deletedAt: now } },
|
|
14312
|
+
{ $set: { status: "deleted", deletedAt: now, isDeletedInDahua: true } },
|
|
14518
14313
|
{ session }
|
|
14519
14314
|
);
|
|
14520
|
-
delNamespace().then(() => {
|
|
14521
|
-
logger49.info(
|
|
14522
|
-
`Cache cleared for namespace: ${vehicles_namespace_collection}`
|
|
14523
|
-
);
|
|
14524
|
-
}).catch((err) => {
|
|
14525
|
-
logger49.error(
|
|
14526
|
-
`Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
|
|
14527
|
-
err
|
|
14528
|
-
);
|
|
14529
|
-
});
|
|
14530
14315
|
return res.modifiedCount;
|
|
14531
14316
|
} catch (error) {
|
|
14532
14317
|
throw error;
|
|
@@ -14545,21 +14330,6 @@ function useVehicleRepo() {
|
|
|
14545
14330
|
const query = {
|
|
14546
14331
|
unit
|
|
14547
14332
|
};
|
|
14548
|
-
const cacheOptions = {
|
|
14549
|
-
unit: unitId,
|
|
14550
|
-
page,
|
|
14551
|
-
limit,
|
|
14552
|
-
sort: JSON.stringify(sort)
|
|
14553
|
-
};
|
|
14554
|
-
const cacheKey = makeCacheKey23(
|
|
14555
|
-
vehicles_namespace_collection,
|
|
14556
|
-
cacheOptions
|
|
14557
|
-
);
|
|
14558
|
-
const cachedData = await getCache(cacheKey);
|
|
14559
|
-
if (cachedData) {
|
|
14560
|
-
logger49.info(`Cache hit for key: ${cacheKey}`);
|
|
14561
|
-
return cachedData;
|
|
14562
|
-
}
|
|
14563
14333
|
const items = await collection.find(query, {
|
|
14564
14334
|
projection: {
|
|
14565
14335
|
createdAt: 0,
|
|
@@ -14572,14 +14342,24 @@ function useVehicleRepo() {
|
|
|
14572
14342
|
}).toArray();
|
|
14573
14343
|
const length = await collection.countDocuments(query);
|
|
14574
14344
|
const data = paginate18(items, page, limit, length);
|
|
14575
|
-
setCache(cacheKey, data, 15 * 60).then(() => logger49.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
14576
|
-
(err) => logger49.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
14577
|
-
);
|
|
14578
14345
|
return data;
|
|
14579
14346
|
} catch (error) {
|
|
14580
14347
|
throw error;
|
|
14581
14348
|
}
|
|
14582
14349
|
}
|
|
14350
|
+
async function getAllExpiredVehicles() {
|
|
14351
|
+
try {
|
|
14352
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14353
|
+
const query = {
|
|
14354
|
+
end: { $lte: now },
|
|
14355
|
+
status: { $ne: "deleted" }
|
|
14356
|
+
};
|
|
14357
|
+
const items = await collection.find(query).toArray();
|
|
14358
|
+
return items;
|
|
14359
|
+
} catch (error) {
|
|
14360
|
+
throw error;
|
|
14361
|
+
}
|
|
14362
|
+
}
|
|
14583
14363
|
return {
|
|
14584
14364
|
createIndex,
|
|
14585
14365
|
createTextIndex,
|
|
@@ -14593,7 +14373,8 @@ function useVehicleRepo() {
|
|
|
14593
14373
|
getVehicleByPlateNumber,
|
|
14594
14374
|
getVehiclesByNRIC,
|
|
14595
14375
|
deleteExpiredVehicles,
|
|
14596
|
-
getAllVehiclesByUnitId
|
|
14376
|
+
getAllVehiclesByUnitId,
|
|
14377
|
+
getAllExpiredVehicles
|
|
14597
14378
|
};
|
|
14598
14379
|
}
|
|
14599
14380
|
|
|
@@ -15220,18 +15001,32 @@ function formatDahuaDate(date) {
|
|
|
15220
15001
|
date.getSeconds()
|
|
15221
15002
|
)}`;
|
|
15222
15003
|
}
|
|
15004
|
+
function parseDahuaFind(text) {
|
|
15005
|
+
const found = Number(text.match(/found=(\d+)/)?.[1] || 0);
|
|
15006
|
+
if (!found) {
|
|
15007
|
+
return { exists: false };
|
|
15008
|
+
}
|
|
15009
|
+
return {
|
|
15010
|
+
exists: true,
|
|
15011
|
+
recNo: text.match(/records\[0\]\.RecNo=(.*)/)?.[1]?.trim(),
|
|
15012
|
+
plateNumber: text.match(/records\[0\]\.PlateNumber=(.*)/)?.[1]?.trim()
|
|
15013
|
+
};
|
|
15014
|
+
}
|
|
15223
15015
|
function useVehicleService() {
|
|
15224
15016
|
const {
|
|
15225
15017
|
add: _add,
|
|
15226
15018
|
deleteVehicle: _deleteVehicle,
|
|
15227
15019
|
updateVehicleById: _updateVehicleById,
|
|
15228
15020
|
getVehicleById: _getVehicleById,
|
|
15229
|
-
deleteExpiredVehicles: _deleteExpiredVehicles
|
|
15021
|
+
deleteExpiredVehicles: _deleteExpiredVehicles,
|
|
15022
|
+
getVehicleByPlateNumber: _getVehicleByPlateNumber,
|
|
15023
|
+
getAllExpiredVehicles: _getAllExpiredVehicles
|
|
15230
15024
|
} = useVehicleRepo();
|
|
15231
15025
|
const {
|
|
15232
15026
|
addPlateNumber: _addPlateNumber,
|
|
15233
15027
|
removePlateNumber: _removePlateNumber,
|
|
15234
|
-
updatePlateNumber: _updatePlateNumber
|
|
15028
|
+
updatePlateNumber: _updatePlateNumber,
|
|
15029
|
+
getPlateNumber: _getPlateNumber
|
|
15235
15030
|
} = useDahuaService();
|
|
15236
15031
|
const { getAllCameraWithPassword: _getAllSiteCameras } = useSiteCameraRepo();
|
|
15237
15032
|
const { getById: _getById } = useOrgRepo();
|
|
@@ -15242,9 +15037,15 @@ function useVehicleService() {
|
|
|
15242
15037
|
if (!session) {
|
|
15243
15038
|
throw new Error("Unable to start session for vehicle service.");
|
|
15244
15039
|
}
|
|
15245
|
-
const
|
|
15040
|
+
const [_vehiclePlateNumber] = value.plateNumber;
|
|
15041
|
+
const [existingPlateNumber, org] = await Promise.all([
|
|
15042
|
+
_getVehicleByPlateNumber(_vehiclePlateNumber),
|
|
15043
|
+
_getById(value.org)
|
|
15044
|
+
]);
|
|
15246
15045
|
if (!org)
|
|
15247
15046
|
throw new BadRequestError70("Org not found");
|
|
15047
|
+
if (existingPlateNumber)
|
|
15048
|
+
throw new BadRequestError70("Vehicle plate number already exists");
|
|
15248
15049
|
if (!Object.values(OrgNature).includes(org.nature)) {
|
|
15249
15050
|
throw new BadRequestError70(
|
|
15250
15051
|
"This organization is not allowed to add vehicles."
|
|
@@ -15324,29 +15125,61 @@ function useVehicleService() {
|
|
|
15324
15125
|
if (vehicleValue.status && vehicleValue.status !== "pending" /* PENDING */) {
|
|
15325
15126
|
for (const camera of siteCameras) {
|
|
15326
15127
|
const { host, username, password } = camera;
|
|
15327
|
-
const
|
|
15128
|
+
const plateNumber2 = vehicleValue.plateNumber;
|
|
15129
|
+
const dahuaQuery = {
|
|
15328
15130
|
host,
|
|
15329
15131
|
username,
|
|
15330
15132
|
password,
|
|
15331
|
-
plateNumber,
|
|
15332
|
-
mode: _mode
|
|
15333
|
-
owner,
|
|
15334
|
-
...startDateDahua ? { start: startDateDahua } : {},
|
|
15335
|
-
...endDateDahua ? { end: endDateDahua } : {}
|
|
15133
|
+
plateNumber: plateNumber2,
|
|
15134
|
+
mode: _mode
|
|
15336
15135
|
};
|
|
15337
|
-
const
|
|
15338
|
-
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15136
|
+
const raw = await _getPlateNumber(dahuaQuery);
|
|
15137
|
+
const parsed = parseDahuaFind(raw);
|
|
15138
|
+
if (!parsed.exists) {
|
|
15139
|
+
const dahuaPayload = {
|
|
15140
|
+
host,
|
|
15141
|
+
username,
|
|
15142
|
+
password,
|
|
15143
|
+
plateNumber: plateNumber2,
|
|
15144
|
+
mode: _mode,
|
|
15145
|
+
owner,
|
|
15146
|
+
...startDateDahua ? { start: startDateDahua } : {},
|
|
15147
|
+
...endDateDahua ? { end: endDateDahua } : {}
|
|
15148
|
+
};
|
|
15149
|
+
const dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
15150
|
+
if (dahuaResponse?.statusCode !== 200) {
|
|
15151
|
+
throw new BadRequestError70(
|
|
15152
|
+
`Failed to add plate number to ANPR ${_type}`
|
|
15153
|
+
);
|
|
15154
|
+
}
|
|
15155
|
+
const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
|
|
15156
|
+
vehicleValue.recNo = responseData.split("=")[1]?.trim();
|
|
15157
|
+
} else {
|
|
15158
|
+
const dahuaPayload = {
|
|
15159
|
+
host,
|
|
15160
|
+
username,
|
|
15161
|
+
password,
|
|
15162
|
+
plateNumber: plateNumber2,
|
|
15163
|
+
recno: parsed.recNo,
|
|
15164
|
+
mode: _mode,
|
|
15165
|
+
...startDateDahua ? { start: startDateDahua } : {},
|
|
15166
|
+
...endDateDahua ? { end: endDateDahua } : {},
|
|
15167
|
+
owner,
|
|
15168
|
+
isOpenGate: true
|
|
15169
|
+
};
|
|
15170
|
+
const dahuaResponse = await _updatePlateNumber(dahuaPayload);
|
|
15171
|
+
if (dahuaResponse?.statusCode !== 200) {
|
|
15172
|
+
throw new BadRequestError70(
|
|
15173
|
+
`Failed to update plate number to ANPR ${_type}`
|
|
15174
|
+
);
|
|
15175
|
+
}
|
|
15176
|
+
vehicleValue.recNo = parsed.recNo;
|
|
15342
15177
|
}
|
|
15343
|
-
const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
|
|
15344
|
-
vehicleValue.recNo = responseData.split("=")[1]?.trim();
|
|
15345
15178
|
if (value.peopleId && vehicleValue.recNo) {
|
|
15346
15179
|
await _pushVehicleById(
|
|
15347
15180
|
value.peopleId,
|
|
15348
15181
|
{
|
|
15349
|
-
plateNumber,
|
|
15182
|
+
plateNumber: plateNumber2,
|
|
15350
15183
|
recNo: vehicleValue.recNo
|
|
15351
15184
|
},
|
|
15352
15185
|
session
|
|
@@ -15537,6 +15370,43 @@ function useVehicleService() {
|
|
|
15537
15370
|
}
|
|
15538
15371
|
try {
|
|
15539
15372
|
session.startTransaction();
|
|
15373
|
+
const vehicles = await _getAllExpiredVehicles();
|
|
15374
|
+
let siteCameras = [];
|
|
15375
|
+
for (const vehicle of vehicles) {
|
|
15376
|
+
const site = vehicle.site;
|
|
15377
|
+
const recno = vehicle.recNo;
|
|
15378
|
+
let page = 1;
|
|
15379
|
+
let pages = 1;
|
|
15380
|
+
const limit = 20;
|
|
15381
|
+
do {
|
|
15382
|
+
const siteCameraReq = await _getAllSiteCameras({
|
|
15383
|
+
site,
|
|
15384
|
+
type: "anpr",
|
|
15385
|
+
direction: ["both", "entry"],
|
|
15386
|
+
page,
|
|
15387
|
+
limit
|
|
15388
|
+
});
|
|
15389
|
+
pages = siteCameraReq.pages || 1;
|
|
15390
|
+
siteCameras.push(...siteCameraReq.items);
|
|
15391
|
+
page++;
|
|
15392
|
+
} while (page < pages);
|
|
15393
|
+
if (!siteCameras.length) {
|
|
15394
|
+
throw new BadRequestError70("No site cameras found.");
|
|
15395
|
+
}
|
|
15396
|
+
for (const camera of siteCameras) {
|
|
15397
|
+
const host = camera.host;
|
|
15398
|
+
const username = camera.username;
|
|
15399
|
+
const password = camera.password;
|
|
15400
|
+
const dahuaPayload = {
|
|
15401
|
+
host,
|
|
15402
|
+
username,
|
|
15403
|
+
password,
|
|
15404
|
+
recno,
|
|
15405
|
+
mode: "TrafficRedList" /* TRAFFIC_REDLIST */
|
|
15406
|
+
};
|
|
15407
|
+
await _removePlateNumber(dahuaPayload);
|
|
15408
|
+
}
|
|
15409
|
+
}
|
|
15540
15410
|
await _deleteExpiredVehicles();
|
|
15541
15411
|
await session.commitTransaction();
|
|
15542
15412
|
return `Expired Vehicle plate numbers deleted successfully.`;
|
|
@@ -15927,21 +15797,21 @@ function useDahuaService() {
|
|
|
15927
15797
|
org,
|
|
15928
15798
|
status: "unregistered" /* UNREGISTERED */
|
|
15929
15799
|
};
|
|
15930
|
-
const typesForAutoRegister =
|
|
15931
|
-
|
|
15932
|
-
|
|
15933
|
-
"tenant" /* TENANT */
|
|
15934
|
-
];
|
|
15800
|
+
const typesForAutoRegister = Object.values(PersonTypes);
|
|
15801
|
+
let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
|
|
15802
|
+
let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
|
|
15935
15803
|
if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
|
|
15936
15804
|
visitorTransaction.name = vehicle.name;
|
|
15937
15805
|
visitorTransaction.nric = vehicle.nric;
|
|
15938
15806
|
visitorTransaction.contact = vehicle.phoneNumber;
|
|
15939
15807
|
visitorTransaction.block = Number(vehicle.block);
|
|
15940
15808
|
visitorTransaction.level = vehicle.level;
|
|
15941
|
-
visitorTransaction.unit = vehicle.unit;
|
|
15809
|
+
visitorTransaction.unit = vehicle.unit?.toString();
|
|
15942
15810
|
visitorTransaction.unitName = vehicle.unitName;
|
|
15943
15811
|
visitorTransaction.type = vehicle.category;
|
|
15944
15812
|
visitorTransaction.status = "registered" /* REGISTERED */;
|
|
15813
|
+
visitorTransaction.recNo = vehicle.recNo;
|
|
15814
|
+
visitorTransaction.expiredAt = vehicle.end;
|
|
15945
15815
|
}
|
|
15946
15816
|
const dahuaPayload = {
|
|
15947
15817
|
host,
|
|
@@ -15951,13 +15821,15 @@ function useDahuaService() {
|
|
|
15951
15821
|
mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
|
|
15952
15822
|
owner: vehicle?.name ?? ""
|
|
15953
15823
|
};
|
|
15824
|
+
dahuaPayload.start = formatDahuaDate(startDate);
|
|
15825
|
+
dahuaPayload.end = formatDahuaDate(endDate);
|
|
15954
15826
|
const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
|
|
15955
15827
|
if (shouldHaveTimeLimit) {
|
|
15956
|
-
const
|
|
15957
|
-
const
|
|
15958
|
-
dahuaPayload.start = formatDahuaDate(
|
|
15959
|
-
dahuaPayload.end = formatDahuaDate(
|
|
15960
|
-
visitorTransaction.expiredAt =
|
|
15828
|
+
const startDate2 = /* @__PURE__ */ new Date();
|
|
15829
|
+
const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
|
|
15830
|
+
dahuaPayload.start = formatDahuaDate(startDate2);
|
|
15831
|
+
dahuaPayload.end = formatDahuaDate(endDate2);
|
|
15832
|
+
visitorTransaction.expiredAt = endDate2.toISOString();
|
|
15961
15833
|
}
|
|
15962
15834
|
try {
|
|
15963
15835
|
await addPlateNumber(dahuaPayload);
|
|
@@ -16206,14 +16078,14 @@ function useDahuaService() {
|
|
|
16206
16078
|
start: Joi39.string().isoDate().optional().allow("", null),
|
|
16207
16079
|
end: Joi39.string().isoDate().optional().allow("", null),
|
|
16208
16080
|
owner: Joi39.string().optional().allow("", null),
|
|
16209
|
-
|
|
16081
|
+
isOpenGate: Joi39.boolean().optional().allow(null)
|
|
16210
16082
|
});
|
|
16211
16083
|
const { error } = validation.validate(value);
|
|
16212
16084
|
if (error) {
|
|
16213
16085
|
throw new BadRequestError71(`Validation error: ${error.message}`);
|
|
16214
16086
|
}
|
|
16215
16087
|
value.owner = String(value.owner ?? "").substring(0, 15) || "unknown";
|
|
16216
|
-
const _openGate = String(value.
|
|
16088
|
+
const _openGate = String(value.isOpenGate);
|
|
16217
16089
|
const isOpenGateString = _openGate && _openGate !== "undefined" ? _openGate : "true";
|
|
16218
16090
|
const endpoint = `/cgi-bin/recordUpdater.cgi?action=insert&name=${value.mode}&PlateNumber=${value.plateNumber}&BeginTime=${value.start}&CancelTime=${value.end}&+OpenGate=${isOpenGateString}&MasterOfCar=${value.owner}`;
|
|
16219
16091
|
try {
|
|
@@ -16274,7 +16146,7 @@ function useDahuaService() {
|
|
|
16274
16146
|
username: Joi39.string().required(),
|
|
16275
16147
|
password: Joi39.string().required(),
|
|
16276
16148
|
recno: Joi39.string().required(),
|
|
16277
|
-
mode: Joi39.string().valid(
|
|
16149
|
+
mode: Joi39.string().valid(...Object.values(ANPRMode)).required()
|
|
16278
16150
|
});
|
|
16279
16151
|
const { error } = validation.validate(value);
|
|
16280
16152
|
if (error) {
|
|
@@ -16292,12 +16164,39 @@ function useDahuaService() {
|
|
|
16292
16164
|
logger52.error(`[${value.host}] Error removing plate number:`, error2);
|
|
16293
16165
|
}
|
|
16294
16166
|
}
|
|
16167
|
+
async function getPlateNumber(value) {
|
|
16168
|
+
const validation = Joi39.object({
|
|
16169
|
+
host: Joi39.string().required(),
|
|
16170
|
+
username: Joi39.string().required(),
|
|
16171
|
+
password: Joi39.string().required(),
|
|
16172
|
+
plateNumber: Joi39.string().required(),
|
|
16173
|
+
mode: Joi39.string().valid(...Object.values(ANPRMode)).required()
|
|
16174
|
+
});
|
|
16175
|
+
const { error } = validation.validate(value);
|
|
16176
|
+
if (error) {
|
|
16177
|
+
throw new BadRequestError71(`Validation error: ${error.message}`);
|
|
16178
|
+
}
|
|
16179
|
+
try {
|
|
16180
|
+
const response = await useDahuaDigest({
|
|
16181
|
+
host: value.host,
|
|
16182
|
+
username: value.username,
|
|
16183
|
+
password: value.password,
|
|
16184
|
+
endpoint: `/cgi-bin/recordFinder.cgi?action=find&name=${value.mode}&condition.PlateNumber=${encodeURIComponent(value.plateNumber)}`
|
|
16185
|
+
});
|
|
16186
|
+
const text = response?.data?.toString?.("utf-8");
|
|
16187
|
+
return text;
|
|
16188
|
+
} catch (error2) {
|
|
16189
|
+
logger52.error(`[${value.host}] Error finding plate number:`, error2);
|
|
16190
|
+
throw error2;
|
|
16191
|
+
}
|
|
16192
|
+
}
|
|
16295
16193
|
return {
|
|
16296
16194
|
getSnapshot,
|
|
16297
16195
|
getTrafficJunction,
|
|
16298
16196
|
addPlateNumber,
|
|
16299
16197
|
removePlateNumber,
|
|
16300
|
-
updatePlateNumber
|
|
16198
|
+
updatePlateNumber,
|
|
16199
|
+
getPlateNumber
|
|
16301
16200
|
};
|
|
16302
16201
|
}
|
|
16303
16202
|
|
|
@@ -20630,10 +20529,13 @@ function useVisitorTransactionService() {
|
|
|
20630
20529
|
const { getSiteById: _getSiteById } = useSiteRepo();
|
|
20631
20530
|
const {
|
|
20632
20531
|
addPlateNumber: _addPlateNumber,
|
|
20633
|
-
removePlateNumber: _removePlateNumber
|
|
20532
|
+
removePlateNumber: _removePlateNumber,
|
|
20533
|
+
getPlateNumber: _getPlateNumber,
|
|
20534
|
+
updatePlateNumber: _updatePlateNumber
|
|
20634
20535
|
} = useDahuaService();
|
|
20635
20536
|
const { getAllSites: _getAllSites } = useSiteRepo();
|
|
20636
20537
|
const { getByUserId: _getByUserId } = usePersonRepo();
|
|
20538
|
+
const { add: addVehicle } = useVehicleRepo();
|
|
20637
20539
|
async function add(value) {
|
|
20638
20540
|
const session = useAtlas47.getClient()?.startSession();
|
|
20639
20541
|
const allowedPersonTypes = [
|
|
@@ -20650,12 +20552,12 @@ function useVisitorTransactionService() {
|
|
|
20650
20552
|
let site;
|
|
20651
20553
|
if (value.site) {
|
|
20652
20554
|
[camera, site] = await Promise.all([
|
|
20653
|
-
_getBySite(value.site, { type: "anpr" }),
|
|
20555
|
+
_getBySite(value.site, { type: "anpr" /* ANPR */ }),
|
|
20654
20556
|
_getSiteById(value.site)
|
|
20655
20557
|
]);
|
|
20656
20558
|
}
|
|
20657
|
-
const
|
|
20658
|
-
const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() +
|
|
20559
|
+
const hourExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 24 * 60;
|
|
20560
|
+
const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + hourExpiration * 60 * 1e3);
|
|
20659
20561
|
const startString = start.toISOString();
|
|
20660
20562
|
const endString = end.toISOString();
|
|
20661
20563
|
const startDahuaDate = formatDahuaDate(start);
|
|
@@ -20731,27 +20633,76 @@ function useVisitorTransactionService() {
|
|
|
20731
20633
|
}
|
|
20732
20634
|
}
|
|
20733
20635
|
if (camera && value.plateNumber && camera.host && camera.username && camera.password) {
|
|
20734
|
-
const
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
|
|
20738
|
-
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
20743
|
-
|
|
20636
|
+
const host = camera.host;
|
|
20637
|
+
const username = camera.username;
|
|
20638
|
+
const password = camera.password;
|
|
20639
|
+
const mode = "TrafficRedList" /* TRAFFIC_REDLIST */;
|
|
20640
|
+
const _plateNumber = value.plateNumber;
|
|
20641
|
+
const dahuaQuery = {
|
|
20642
|
+
host,
|
|
20643
|
+
username,
|
|
20644
|
+
password,
|
|
20645
|
+
plateNumber: _plateNumber,
|
|
20646
|
+
mode
|
|
20744
20647
|
};
|
|
20745
|
-
const
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
|
|
20749
|
-
|
|
20648
|
+
const raw = await _getPlateNumber(dahuaQuery);
|
|
20649
|
+
const parsed = parseDahuaFind(raw);
|
|
20650
|
+
if (!parsed.exists) {
|
|
20651
|
+
const dahuaPayload = {
|
|
20652
|
+
host,
|
|
20653
|
+
username,
|
|
20654
|
+
password,
|
|
20655
|
+
plateNumber: _plateNumber,
|
|
20656
|
+
mode,
|
|
20657
|
+
start: startDahuaDate,
|
|
20658
|
+
end: endDahuaDate,
|
|
20659
|
+
owner: value.name ?? "",
|
|
20660
|
+
isOpenGate: site?.isOpenGate ?? true
|
|
20661
|
+
};
|
|
20662
|
+
const dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
20663
|
+
if (dahuaResponse?.statusCode !== 200) {
|
|
20664
|
+
throw new BadRequestError96(
|
|
20665
|
+
`Failed to add plate number to ANPR whitelist`
|
|
20666
|
+
);
|
|
20667
|
+
}
|
|
20668
|
+
const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
|
|
20669
|
+
value.recNo = responseData.split("=")[1]?.trim();
|
|
20670
|
+
value.checkIn = startString;
|
|
20671
|
+
value.expiredAt = endString;
|
|
20672
|
+
const vehiclePayload = {
|
|
20673
|
+
name: value.name ?? "",
|
|
20674
|
+
category: value.type,
|
|
20675
|
+
org: value.org,
|
|
20676
|
+
site: value.site,
|
|
20677
|
+
plateNumber: value.plateNumber,
|
|
20678
|
+
type: "whitelist" /* WHITELIST */,
|
|
20679
|
+
nric: value.nric,
|
|
20680
|
+
start: startString,
|
|
20681
|
+
end: endString,
|
|
20682
|
+
recNo: value.recNo
|
|
20683
|
+
};
|
|
20684
|
+
await addVehicle(vehiclePayload);
|
|
20685
|
+
} else {
|
|
20686
|
+
const dahuaPayload = {
|
|
20687
|
+
host,
|
|
20688
|
+
username,
|
|
20689
|
+
password,
|
|
20690
|
+
plateNumber: _plateNumber,
|
|
20691
|
+
recno: parsed.recNo,
|
|
20692
|
+
mode,
|
|
20693
|
+
start: startDahuaDate,
|
|
20694
|
+
end: endDahuaDate,
|
|
20695
|
+
owner: value.name ?? "",
|
|
20696
|
+
isOpenGate: site?.isOpenGate ?? true
|
|
20697
|
+
};
|
|
20698
|
+
const dahuaResponse = await _updatePlateNumber(dahuaPayload);
|
|
20699
|
+
if (dahuaResponse?.statusCode !== 200) {
|
|
20700
|
+
throw new BadRequestError96(
|
|
20701
|
+
`Failed to update plate number to ANPR ${"whitelist" /* WHITELIST */}`
|
|
20702
|
+
);
|
|
20703
|
+
}
|
|
20704
|
+
value.recNo = parsed.recNo;
|
|
20750
20705
|
}
|
|
20751
|
-
const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
|
|
20752
|
-
value.recNo = responseData.split("=")[1]?.trim();
|
|
20753
|
-
value.checkIn = startString;
|
|
20754
|
-
value.expiredAt = endString;
|
|
20755
20706
|
}
|
|
20756
20707
|
const result = await _add(value, session);
|
|
20757
20708
|
await session?.commitTransaction();
|
|
@@ -21085,7 +21036,6 @@ function useVisitorTransactionController() {
|
|
|
21085
21036
|
}
|
|
21086
21037
|
}
|
|
21087
21038
|
async function inviteVisitor(req, res, next) {
|
|
21088
|
-
const inviter = req.params.inviterId;
|
|
21089
21039
|
const schema2 = Joi55.object({
|
|
21090
21040
|
name: Joi55.string().required(),
|
|
21091
21041
|
contact: Joi55.string().required(),
|
|
@@ -39091,8 +39041,7 @@ function useOccurrenceEntryController() {
|
|
|
39091
39041
|
getLatestSerialNumber: _getLatestSerialNumber
|
|
39092
39042
|
} = useOccurrenceEntryRepo();
|
|
39093
39043
|
async function add(req, res, next) {
|
|
39094
|
-
const
|
|
39095
|
-
const { error } = schemaOccurrenceEntry.validate(payload, {
|
|
39044
|
+
const { error, value } = schemaOccurrenceEntry.validate(req.body, {
|
|
39096
39045
|
abortEarly: false
|
|
39097
39046
|
});
|
|
39098
39047
|
if (error) {
|
|
@@ -39102,7 +39051,7 @@ function useOccurrenceEntryController() {
|
|
|
39102
39051
|
return;
|
|
39103
39052
|
}
|
|
39104
39053
|
try {
|
|
39105
|
-
const data = await _add(
|
|
39054
|
+
const data = await _add(value);
|
|
39106
39055
|
res.status(201).json(data);
|
|
39107
39056
|
return;
|
|
39108
39057
|
} catch (error2) {
|
|
@@ -39184,9 +39133,8 @@ function useOccurrenceEntryController() {
|
|
|
39184
39133
|
}
|
|
39185
39134
|
}
|
|
39186
39135
|
async function updateOccurrenceEntryById(req, res, next) {
|
|
39187
|
-
const
|
|
39188
|
-
const
|
|
39189
|
-
const { error } = schemaUpdateOccurrenceEntry.validate(payload, {
|
|
39136
|
+
const payload = { _id: req.params.id, ...req.body };
|
|
39137
|
+
const { error, value } = schemaUpdateOccurrenceEntry.validate(payload, {
|
|
39190
39138
|
abortEarly: false
|
|
39191
39139
|
});
|
|
39192
39140
|
if (error) {
|
|
@@ -39195,8 +39143,9 @@ function useOccurrenceEntryController() {
|
|
|
39195
39143
|
next(new BadRequestError170(messages));
|
|
39196
39144
|
return;
|
|
39197
39145
|
}
|
|
39146
|
+
const { _id, ...rest } = value;
|
|
39198
39147
|
try {
|
|
39199
|
-
const result = await _updateOccurrenceEntryById(_id,
|
|
39148
|
+
const result = await _updateOccurrenceEntryById(_id, rest);
|
|
39200
39149
|
res.status(200).json({ message: result });
|
|
39201
39150
|
return;
|
|
39202
39151
|
} catch (error2) {
|
|
@@ -45503,12 +45452,6 @@ function useVerificationRepoV2() {
|
|
|
45503
45452
|
err
|
|
45504
45453
|
);
|
|
45505
45454
|
});
|
|
45506
|
-
const cacheKey = makeCacheKey64(namespace_collection, { _id });
|
|
45507
|
-
delCache(cacheKey).then(() => {
|
|
45508
|
-
logger175.info(`Cache deleted for key: ${cacheKey}`);
|
|
45509
|
-
}).catch((err) => {
|
|
45510
|
-
logger175.error(`Failed to delete cache for key: ${cacheKey}`, err);
|
|
45511
|
-
});
|
|
45512
45455
|
return result;
|
|
45513
45456
|
} catch (error) {
|
|
45514
45457
|
throw new InternalServerError68("Error updating verification status.");
|
|
@@ -45924,9 +45867,12 @@ function useVerificationControllerV2() {
|
|
|
45924
45867
|
async function verify(req, res, next) {
|
|
45925
45868
|
try {
|
|
45926
45869
|
const schema2 = Joi126.object({ verificationCode: Joi126.string().required() });
|
|
45927
|
-
const { error, value } = schema2.validate(
|
|
45928
|
-
|
|
45929
|
-
|
|
45870
|
+
const { error, value } = schema2.validate(
|
|
45871
|
+
{
|
|
45872
|
+
verificationCode: req.params.verificationCode
|
|
45873
|
+
},
|
|
45874
|
+
{ abortEarly: false }
|
|
45875
|
+
);
|
|
45930
45876
|
if (error) {
|
|
45931
45877
|
const messages = error.details.map((d) => d.message).join(", ");
|
|
45932
45878
|
logger177.log({ level: "error", message: messages });
|
|
@@ -45952,7 +45898,7 @@ function useVerificationControllerV2() {
|
|
|
45952
45898
|
siteId: Joi126.string().hex().length(24).optional().allow("", null),
|
|
45953
45899
|
siteName: Joi126.string().optional().allow("", null)
|
|
45954
45900
|
});
|
|
45955
|
-
const { error, value } = schema2.validate(req.body);
|
|
45901
|
+
const { error, value } = schema2.validate(req.body, { abortEarly: false });
|
|
45956
45902
|
if (error) {
|
|
45957
45903
|
const messages = error.details.map((d) => d.message).join(", ");
|
|
45958
45904
|
logger177.log({ level: "error", message: messages });
|
|
@@ -45987,7 +45933,7 @@ function useVerificationControllerV2() {
|
|
|
45987
45933
|
siteId: Joi126.string().hex().length(24).required(),
|
|
45988
45934
|
siteName: Joi126.string().required()
|
|
45989
45935
|
});
|
|
45990
|
-
const { error, value } = schema2.validate(req.body);
|
|
45936
|
+
const { error, value } = schema2.validate(req.body, { abortEarly: false });
|
|
45991
45937
|
if (error) {
|
|
45992
45938
|
const messages = error.details.map((d) => d.message).join(", ");
|
|
45993
45939
|
logger177.log({ level: "error", message: messages });
|
|
@@ -46013,7 +45959,7 @@ function useVerificationControllerV2() {
|
|
|
46013
45959
|
const schema2 = Joi126.object({
|
|
46014
45960
|
email: Joi126.string().email().lowercase().required()
|
|
46015
45961
|
});
|
|
46016
|
-
const { error, value } = schema2.validate(req.body);
|
|
45962
|
+
const { error, value } = schema2.validate(req.body, { abortEarly: false });
|
|
46017
45963
|
if (error) {
|
|
46018
45964
|
const messages = error.details.map((d) => d.message).join(", ");
|
|
46019
45965
|
logger177.log({ level: "error", message: messages });
|
|
@@ -46043,7 +45989,7 @@ function useVerificationControllerV2() {
|
|
|
46043
45989
|
|
|
46044
45990
|
// src/controllers/auth-v2.controller.ts
|
|
46045
45991
|
import Joi127 from "joi";
|
|
46046
|
-
import { BadRequestError as
|
|
45992
|
+
import { BadRequestError as BadRequestError201, logger as logger180 } from "@7365admin1/node-server-utils";
|
|
46047
45993
|
|
|
46048
45994
|
// src/services/auth-v2.service.ts
|
|
46049
45995
|
import {
|
|
@@ -46056,11 +46002,13 @@ import {
|
|
|
46056
46002
|
import { v4 as uuidv42 } from "uuid";
|
|
46057
46003
|
|
|
46058
46004
|
// src/repositories/user-v2.repo.ts
|
|
46005
|
+
import { ObjectId as ObjectId123 } from "mongodb";
|
|
46059
46006
|
import {
|
|
46060
46007
|
useAtlas as useAtlas113,
|
|
46061
46008
|
InternalServerError as InternalServerError70,
|
|
46062
46009
|
logger as logger178,
|
|
46063
46010
|
BadRequestError as BadRequestError198,
|
|
46011
|
+
paginate as paginate58,
|
|
46064
46012
|
NotFoundError as NotFoundError52,
|
|
46065
46013
|
AppError as AppError27,
|
|
46066
46014
|
useCache as useCache67,
|
|
@@ -46077,6 +46025,7 @@ function useUserRepoV2() {
|
|
|
46077
46025
|
}
|
|
46078
46026
|
const namespace_collection = "users";
|
|
46079
46027
|
const collection = db.collection(namespace_collection);
|
|
46028
|
+
const { delNamespace, setCache, getCache, delCache } = useCache67(namespace_collection);
|
|
46080
46029
|
async function createIndex() {
|
|
46081
46030
|
try {
|
|
46082
46031
|
await collection.createIndexes([{ key: { email: 1 } }]);
|
|
@@ -46086,10 +46035,7 @@ function useUserRepoV2() {
|
|
|
46086
46035
|
}
|
|
46087
46036
|
async function createTextIndex() {
|
|
46088
46037
|
try {
|
|
46089
|
-
await collection.createIndex({
|
|
46090
|
-
name: "text",
|
|
46091
|
-
email: "text"
|
|
46092
|
-
});
|
|
46038
|
+
await collection.createIndex({ name: "text", email: "text" });
|
|
46093
46039
|
} catch (error) {
|
|
46094
46040
|
throw new InternalServerError70("Failed to create text index on user.");
|
|
46095
46041
|
}
|
|
@@ -46104,24 +46050,22 @@ function useUserRepoV2() {
|
|
|
46104
46050
|
throw new InternalServerError70("Failed to create unique index on user.");
|
|
46105
46051
|
}
|
|
46106
46052
|
}
|
|
46107
|
-
const { delNamespace, setCache, getCache, delCache } = useCache67(namespace_collection);
|
|
46108
46053
|
async function createUser(value, session) {
|
|
46109
46054
|
try {
|
|
46110
46055
|
value = MUser(value);
|
|
46111
46056
|
const res = await collection.insertOne(value, { session });
|
|
46112
|
-
delNamespace().then(
|
|
46113
|
-
logger178.info(`Cache cleared for namespace: ${namespace_collection}`)
|
|
46114
|
-
|
|
46115
|
-
logger178.error(
|
|
46057
|
+
delNamespace().then(
|
|
46058
|
+
() => logger178.info(`Cache cleared for namespace: ${namespace_collection}`)
|
|
46059
|
+
).catch(
|
|
46060
|
+
(err) => logger178.error(
|
|
46116
46061
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
46117
46062
|
err
|
|
46118
|
-
)
|
|
46119
|
-
|
|
46063
|
+
)
|
|
46064
|
+
);
|
|
46120
46065
|
return res.insertedId;
|
|
46121
46066
|
} catch (error) {
|
|
46122
46067
|
logger178.log({ level: "error", message: `${error}` });
|
|
46123
|
-
|
|
46124
|
-
if (isDuplicated) {
|
|
46068
|
+
if (error.message.includes("duplicate")) {
|
|
46125
46069
|
throw new BadRequestError198("User already exists.");
|
|
46126
46070
|
}
|
|
46127
46071
|
throw error;
|
|
@@ -46138,11 +46082,9 @@ function useUserRepoV2() {
|
|
|
46138
46082
|
const data = await collection.findOne({
|
|
46139
46083
|
email: { $regex: `^${email}$`, $options: "i" }
|
|
46140
46084
|
});
|
|
46141
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
46142
|
-
logger178.
|
|
46143
|
-
|
|
46144
|
-
logger178.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
46145
|
-
});
|
|
46085
|
+
setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
46086
|
+
(err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
46087
|
+
);
|
|
46146
46088
|
return data;
|
|
46147
46089
|
} catch (error) {
|
|
46148
46090
|
throw new InternalServerError70("Failed to get user by email.");
|
|
@@ -46150,26 +46092,22 @@ function useUserRepoV2() {
|
|
|
46150
46092
|
}
|
|
46151
46093
|
async function getUserByEmailStatus(email) {
|
|
46152
46094
|
try {
|
|
46153
|
-
const
|
|
46095
|
+
const cacheKey = makeCacheKey65(namespace_collection, {
|
|
46154
46096
|
email,
|
|
46155
46097
|
status: "complete" /* COMPLETE */
|
|
46156
|
-
};
|
|
46157
|
-
const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
|
|
46098
|
+
});
|
|
46158
46099
|
const cachedData = await getCache(cacheKey);
|
|
46159
46100
|
if (cachedData) {
|
|
46160
46101
|
logger178.info(`Cache hit for key: ${cacheKey}`);
|
|
46161
46102
|
return cachedData;
|
|
46162
46103
|
}
|
|
46163
|
-
const
|
|
46104
|
+
const data = await collection.findOne({
|
|
46164
46105
|
email: { $regex: `^${email}$`, $options: "i" },
|
|
46165
46106
|
status: "complete" /* COMPLETE */
|
|
46166
|
-
};
|
|
46167
|
-
const data = await collection.findOne(query);
|
|
46168
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
46169
|
-
logger178.info(`Cache set for key: ${cacheKey}`);
|
|
46170
|
-
}).catch((err) => {
|
|
46171
|
-
logger178.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
46172
46107
|
});
|
|
46108
|
+
setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
46109
|
+
(err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
46110
|
+
);
|
|
46173
46111
|
return data;
|
|
46174
46112
|
} catch (error) {
|
|
46175
46113
|
throw new InternalServerError70("Failed to get user by email.");
|
|
@@ -46192,17 +46130,10 @@ function useUserRepoV2() {
|
|
|
46192
46130
|
let: { userOrgId: "$defaultOrg" },
|
|
46193
46131
|
pipeline: [
|
|
46194
46132
|
{
|
|
46195
|
-
$match: {
|
|
46196
|
-
$expr: { $eq: ["$orgId", "$$userOrgId"] }
|
|
46197
|
-
}
|
|
46133
|
+
$match: { $expr: { $eq: ["$orgId", "$$userOrgId"] } }
|
|
46198
46134
|
},
|
|
46199
46135
|
{
|
|
46200
|
-
$project: {
|
|
46201
|
-
_id: 1,
|
|
46202
|
-
name: 1,
|
|
46203
|
-
type: 1,
|
|
46204
|
-
siteId: 1
|
|
46205
|
-
}
|
|
46136
|
+
$project: { _id: 1, name: 1, type: 1, siteId: 1 }
|
|
46206
46137
|
}
|
|
46207
46138
|
],
|
|
46208
46139
|
as: "serviceProviders"
|
|
@@ -46210,9 +46141,117 @@ function useUserRepoV2() {
|
|
|
46210
46141
|
}
|
|
46211
46142
|
]).toArray();
|
|
46212
46143
|
const data = results.length > 0 ? results[0] : null;
|
|
46213
|
-
if (!data)
|
|
46144
|
+
if (!data)
|
|
46214
46145
|
throw new NotFoundError52("User not found.");
|
|
46146
|
+
setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
46147
|
+
(err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
46148
|
+
);
|
|
46149
|
+
return data;
|
|
46150
|
+
} catch (error) {
|
|
46151
|
+
if (error instanceof AppError27)
|
|
46152
|
+
throw error;
|
|
46153
|
+
throw new InternalServerError70("Failed to get user by id.");
|
|
46154
|
+
}
|
|
46155
|
+
}
|
|
46156
|
+
async function getUserByReferralCode(referralCode) {
|
|
46157
|
+
try {
|
|
46158
|
+
const cacheKey = makeCacheKey65(namespace_collection, { referralCode });
|
|
46159
|
+
const cachedData = await getCache(cacheKey);
|
|
46160
|
+
if (cachedData) {
|
|
46161
|
+
logger178.info(`Cache hit for key: ${cacheKey}`);
|
|
46162
|
+
return cachedData;
|
|
46163
|
+
}
|
|
46164
|
+
const data = await collection.findOne({ referralCode });
|
|
46165
|
+
setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
46166
|
+
(err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
46167
|
+
);
|
|
46168
|
+
return data;
|
|
46169
|
+
} catch (error) {
|
|
46170
|
+
throw new InternalServerError70("Failed to get user by referral code.");
|
|
46171
|
+
}
|
|
46172
|
+
}
|
|
46173
|
+
async function getByEmailApp(email, app) {
|
|
46174
|
+
try {
|
|
46175
|
+
const cacheKey = makeCacheKey65(namespace_collection, { email, app });
|
|
46176
|
+
const cachedData = await getCache(cacheKey);
|
|
46177
|
+
if (cachedData) {
|
|
46178
|
+
logger178.info(`Cache hit for key: ${cacheKey}`);
|
|
46179
|
+
return cachedData;
|
|
46215
46180
|
}
|
|
46181
|
+
const data = await collection.findOne({
|
|
46182
|
+
email,
|
|
46183
|
+
"roles.app": app
|
|
46184
|
+
});
|
|
46185
|
+
setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
46186
|
+
(err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
46187
|
+
);
|
|
46188
|
+
return data;
|
|
46189
|
+
} catch (error) {
|
|
46190
|
+
throw new InternalServerError70("Failed to get user by email and app.");
|
|
46191
|
+
}
|
|
46192
|
+
}
|
|
46193
|
+
async function getUsersByOrgId({
|
|
46194
|
+
organization = "",
|
|
46195
|
+
search = "",
|
|
46196
|
+
page = 1,
|
|
46197
|
+
limit = 10,
|
|
46198
|
+
sort = {},
|
|
46199
|
+
type = "",
|
|
46200
|
+
status = "active"
|
|
46201
|
+
}) {
|
|
46202
|
+
page = page > 0 ? page - 1 : 0;
|
|
46203
|
+
const query = { status };
|
|
46204
|
+
const cacheOptions = { status };
|
|
46205
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
46206
|
+
cacheOptions.sort = JSON.stringify(sort);
|
|
46207
|
+
if (search) {
|
|
46208
|
+
query.$text = { $search: search };
|
|
46209
|
+
cacheOptions.search = search;
|
|
46210
|
+
}
|
|
46211
|
+
if (type) {
|
|
46212
|
+
query.type = type;
|
|
46213
|
+
cacheOptions.type = type;
|
|
46214
|
+
}
|
|
46215
|
+
if (organization) {
|
|
46216
|
+
try {
|
|
46217
|
+
query.defaultOrg = new ObjectId123(organization);
|
|
46218
|
+
cacheOptions.organization = organization.toString();
|
|
46219
|
+
} catch (error) {
|
|
46220
|
+
throw new BadRequestError198("Invalid organization ID format.");
|
|
46221
|
+
}
|
|
46222
|
+
}
|
|
46223
|
+
delNamespace().then(() => {
|
|
46224
|
+
logger178.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
46225
|
+
}).catch((err) => {
|
|
46226
|
+
logger178.error(
|
|
46227
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
46228
|
+
err
|
|
46229
|
+
);
|
|
46230
|
+
});
|
|
46231
|
+
const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
|
|
46232
|
+
const cachedData = await getCache(cacheKey);
|
|
46233
|
+
if (cachedData) {
|
|
46234
|
+
logger178.info(`Cache hit for key: ${cacheKey}`);
|
|
46235
|
+
return cachedData;
|
|
46236
|
+
}
|
|
46237
|
+
try {
|
|
46238
|
+
const items = await collection.aggregate([
|
|
46239
|
+
{ $match: query },
|
|
46240
|
+
{ $sort: sort },
|
|
46241
|
+
{ $skip: page * limit },
|
|
46242
|
+
{ $limit: limit },
|
|
46243
|
+
{
|
|
46244
|
+
$project: {
|
|
46245
|
+
_id: 1,
|
|
46246
|
+
name: 1,
|
|
46247
|
+
email: 1,
|
|
46248
|
+
type: 1,
|
|
46249
|
+
status: 1
|
|
46250
|
+
}
|
|
46251
|
+
}
|
|
46252
|
+
]).toArray();
|
|
46253
|
+
const length = await collection.countDocuments(query);
|
|
46254
|
+
const data = paginate58(items, page, limit, length);
|
|
46216
46255
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
46217
46256
|
logger178.info(`Cache set for key: ${cacheKey}`);
|
|
46218
46257
|
}).catch((err) => {
|
|
@@ -46220,12 +46259,197 @@ function useUserRepoV2() {
|
|
|
46220
46259
|
});
|
|
46221
46260
|
return data;
|
|
46222
46261
|
} catch (error) {
|
|
46223
|
-
|
|
46262
|
+
logger178.log({ level: "error", message: `${error}` });
|
|
46263
|
+
throw error;
|
|
46264
|
+
}
|
|
46265
|
+
}
|
|
46266
|
+
async function getUsers({
|
|
46267
|
+
search = "",
|
|
46268
|
+
page = 1,
|
|
46269
|
+
limit = 10,
|
|
46270
|
+
sort = {},
|
|
46271
|
+
type = "",
|
|
46272
|
+
status = "active"
|
|
46273
|
+
}) {
|
|
46274
|
+
page = page > 0 ? page - 1 : 0;
|
|
46275
|
+
const query = { status };
|
|
46276
|
+
const cacheOptions = { status };
|
|
46277
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
46278
|
+
cacheOptions.sort = JSON.stringify(sort);
|
|
46279
|
+
if (search) {
|
|
46280
|
+
query.$text = { $search: search };
|
|
46281
|
+
cacheOptions.search = search;
|
|
46282
|
+
}
|
|
46283
|
+
if (type) {
|
|
46284
|
+
query.type = type;
|
|
46285
|
+
cacheOptions.type = type;
|
|
46286
|
+
}
|
|
46287
|
+
delNamespace().then(
|
|
46288
|
+
() => logger178.info(`Cache cleared for namespace: ${namespace_collection}`)
|
|
46289
|
+
).catch(
|
|
46290
|
+
(err) => logger178.error(
|
|
46291
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
46292
|
+
err
|
|
46293
|
+
)
|
|
46294
|
+
);
|
|
46295
|
+
const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
|
|
46296
|
+
const cachedData = await getCache(cacheKey);
|
|
46297
|
+
if (cachedData) {
|
|
46298
|
+
logger178.info(`Cache hit for key: ${cacheKey}`);
|
|
46299
|
+
return cachedData;
|
|
46300
|
+
}
|
|
46301
|
+
try {
|
|
46302
|
+
const items = await collection.aggregate([
|
|
46303
|
+
{ $match: query },
|
|
46304
|
+
{ $sort: sort },
|
|
46305
|
+
{ $skip: page * limit },
|
|
46306
|
+
{ $limit: limit },
|
|
46307
|
+
{ $project: { _id: 1, name: 1, email: 1, type: 1, status: 1 } }
|
|
46308
|
+
]).toArray();
|
|
46309
|
+
const length = await collection.countDocuments(query);
|
|
46310
|
+
const data = paginate58(items, page, limit, length);
|
|
46311
|
+
setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
46312
|
+
(err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
46313
|
+
);
|
|
46314
|
+
return data;
|
|
46315
|
+
} catch (error) {
|
|
46316
|
+
logger178.log({ level: "error", message: `${error}` });
|
|
46317
|
+
throw error;
|
|
46318
|
+
}
|
|
46319
|
+
}
|
|
46320
|
+
async function updatePasswordById({ _id, password }, session) {
|
|
46321
|
+
const cacheKey = makeCacheKey65(namespace_collection, { _id });
|
|
46322
|
+
_id = toObjectId18(_id);
|
|
46323
|
+
try {
|
|
46324
|
+
const result = await collection.updateOne(
|
|
46325
|
+
{ _id },
|
|
46326
|
+
{ $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
|
|
46327
|
+
{ session }
|
|
46328
|
+
);
|
|
46329
|
+
delCache(cacheKey).then(() => {
|
|
46330
|
+
logger178.info(`Cache deleted for key: ${cacheKey}`);
|
|
46331
|
+
}).catch((err) => {
|
|
46332
|
+
logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
|
|
46333
|
+
});
|
|
46334
|
+
return result;
|
|
46335
|
+
} catch (error) {
|
|
46336
|
+
throw new InternalServerError70("Failed to update user password.");
|
|
46337
|
+
}
|
|
46338
|
+
}
|
|
46339
|
+
async function updateUserFieldById({ _id, field, value } = {}, session) {
|
|
46340
|
+
const allowedFields = [
|
|
46341
|
+
"name",
|
|
46342
|
+
"email",
|
|
46343
|
+
"contact",
|
|
46344
|
+
"nric",
|
|
46345
|
+
"dateOfBirth",
|
|
46346
|
+
"profile",
|
|
46347
|
+
"gender",
|
|
46348
|
+
"defaultOrg"
|
|
46349
|
+
];
|
|
46350
|
+
if (!allowedFields.includes(field)) {
|
|
46351
|
+
throw new BadRequestError198(
|
|
46352
|
+
`Field "${field}" is not allowed to be updated.`
|
|
46353
|
+
);
|
|
46354
|
+
}
|
|
46355
|
+
try {
|
|
46356
|
+
_id = new ObjectId123(_id);
|
|
46357
|
+
} catch (error) {
|
|
46358
|
+
throw new BadRequestError198("Invalid ID.");
|
|
46359
|
+
}
|
|
46360
|
+
if (field === "defaultOrg") {
|
|
46361
|
+
try {
|
|
46362
|
+
value = new ObjectId123(value);
|
|
46363
|
+
} catch (error) {
|
|
46364
|
+
throw new BadRequestError198("Invalid organization ID.");
|
|
46365
|
+
}
|
|
46366
|
+
}
|
|
46367
|
+
if (field === "name") {
|
|
46368
|
+
try {
|
|
46369
|
+
await Promise.all([
|
|
46370
|
+
updateFeedbackCreatedByName(_id, value, session),
|
|
46371
|
+
updateWorkOrderCreatedByName(_id, value, session),
|
|
46372
|
+
updateUserNameBySignatureId(_id, value, session)
|
|
46373
|
+
]);
|
|
46374
|
+
} catch (error) {
|
|
46224
46375
|
throw error;
|
|
46225
|
-
} else {
|
|
46226
|
-
throw new InternalServerError70("Failed to get user by email.");
|
|
46227
46376
|
}
|
|
46228
46377
|
}
|
|
46378
|
+
try {
|
|
46379
|
+
await collection.updateOne(
|
|
46380
|
+
{ _id },
|
|
46381
|
+
{ $set: { [field]: value, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
|
|
46382
|
+
// Dynamically set the field
|
|
46383
|
+
{ session }
|
|
46384
|
+
);
|
|
46385
|
+
const cacheKey = makeCacheKey65(namespace_collection, { _id });
|
|
46386
|
+
delCache(cacheKey).then(() => {
|
|
46387
|
+
logger178.info(`Cache deleted for key: ${cacheKey}`);
|
|
46388
|
+
}).catch((err) => {
|
|
46389
|
+
logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
|
|
46390
|
+
});
|
|
46391
|
+
return `Successfully updated user ${field}.`;
|
|
46392
|
+
} catch (error) {
|
|
46393
|
+
throw new InternalServerError70(`Failed to update user ${field}.`);
|
|
46394
|
+
}
|
|
46395
|
+
}
|
|
46396
|
+
async function updateBirthday({
|
|
46397
|
+
_id,
|
|
46398
|
+
month,
|
|
46399
|
+
day,
|
|
46400
|
+
year
|
|
46401
|
+
}, session) {
|
|
46402
|
+
try {
|
|
46403
|
+
_id = new ObjectId123(_id);
|
|
46404
|
+
} catch (error) {
|
|
46405
|
+
throw new BadRequestError198("Invalid user ID format.");
|
|
46406
|
+
}
|
|
46407
|
+
try {
|
|
46408
|
+
await collection.updateOne(
|
|
46409
|
+
{ _id },
|
|
46410
|
+
{
|
|
46411
|
+
$set: {
|
|
46412
|
+
birthMonth: month,
|
|
46413
|
+
birthDay: day,
|
|
46414
|
+
birthYear: year,
|
|
46415
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
46416
|
+
}
|
|
46417
|
+
},
|
|
46418
|
+
{ session }
|
|
46419
|
+
);
|
|
46420
|
+
const cacheKey = makeCacheKey65(namespace_collection, { _id });
|
|
46421
|
+
delCache(cacheKey).then(() => {
|
|
46422
|
+
logger178.info(`Cache deleted for key: ${cacheKey}`);
|
|
46423
|
+
}).catch((err) => {
|
|
46424
|
+
logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
|
|
46425
|
+
});
|
|
46426
|
+
return "Successfully updated user birthday.";
|
|
46427
|
+
} catch (error) {
|
|
46428
|
+
throw new InternalServerError70("Failed to update user birthday.");
|
|
46429
|
+
}
|
|
46430
|
+
}
|
|
46431
|
+
async function updatePassword({ _id, password }, session) {
|
|
46432
|
+
try {
|
|
46433
|
+
_id = new ObjectId123(_id);
|
|
46434
|
+
} catch (error) {
|
|
46435
|
+
throw new BadRequestError198("Invalid user ID format.");
|
|
46436
|
+
}
|
|
46437
|
+
try {
|
|
46438
|
+
const result = await collection.updateOne(
|
|
46439
|
+
{ _id },
|
|
46440
|
+
{ $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
|
|
46441
|
+
{ session }
|
|
46442
|
+
);
|
|
46443
|
+
const cacheKey = makeCacheKey65(namespace_collection, { _id });
|
|
46444
|
+
delCache(cacheKey).then(() => {
|
|
46445
|
+
logger178.info(`Cache deleted for key: ${cacheKey}`);
|
|
46446
|
+
}).catch((err) => {
|
|
46447
|
+
logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
|
|
46448
|
+
});
|
|
46449
|
+
return result;
|
|
46450
|
+
} catch (error) {
|
|
46451
|
+
throw new InternalServerError70("Failed to update user password.");
|
|
46452
|
+
}
|
|
46229
46453
|
}
|
|
46230
46454
|
return {
|
|
46231
46455
|
createIndex,
|
|
@@ -46234,7 +46458,13 @@ function useUserRepoV2() {
|
|
|
46234
46458
|
createUser,
|
|
46235
46459
|
getUserByEmail,
|
|
46236
46460
|
getUserByEmailStatus,
|
|
46237
|
-
getUserById
|
|
46461
|
+
getUserById,
|
|
46462
|
+
getUsers,
|
|
46463
|
+
getUsersByOrgId,
|
|
46464
|
+
updatePasswordById,
|
|
46465
|
+
updateUserFieldById,
|
|
46466
|
+
updateBirthday,
|
|
46467
|
+
updatePassword
|
|
46238
46468
|
};
|
|
46239
46469
|
}
|
|
46240
46470
|
|
|
@@ -46301,10 +46531,220 @@ function useAuthServiceV2() {
|
|
|
46301
46531
|
};
|
|
46302
46532
|
}
|
|
46303
46533
|
|
|
46534
|
+
// src/services/user-v2.service.ts
|
|
46535
|
+
import {
|
|
46536
|
+
BadRequestError as BadRequestError200,
|
|
46537
|
+
comparePassword as comparePassword4,
|
|
46538
|
+
hashPassword as hashPassword5,
|
|
46539
|
+
InternalServerError as InternalServerError72,
|
|
46540
|
+
NotFoundError as NotFoundError54,
|
|
46541
|
+
useAtlas as useAtlas114,
|
|
46542
|
+
useS3 as useS33
|
|
46543
|
+
} from "@7365admin1/node-server-utils";
|
|
46544
|
+
import "multer";
|
|
46545
|
+
function useUserServiceV2() {
|
|
46546
|
+
const {
|
|
46547
|
+
createUser: _createUser,
|
|
46548
|
+
getUserByEmail: _getUserByEmail,
|
|
46549
|
+
updatePasswordById: _updatePasswordById,
|
|
46550
|
+
updateUserFieldById: _updateUserFieldById,
|
|
46551
|
+
getUserById,
|
|
46552
|
+
updatePassword
|
|
46553
|
+
} = useUserRepoV2();
|
|
46554
|
+
const { getRoleByName, addRole } = useRoleRepo();
|
|
46555
|
+
const { add: addMember } = useMemberRepo();
|
|
46556
|
+
const { getById: getOrgById } = useOrgRepo();
|
|
46557
|
+
const { getSiteById } = useSiteRepo();
|
|
46558
|
+
const {
|
|
46559
|
+
getVerificationById: _getVerificationById,
|
|
46560
|
+
updateVerificationStatusById: _updateVerificationStatusById
|
|
46561
|
+
} = useVerificationRepoV2();
|
|
46562
|
+
const { verify: _verify } = useVerificationServiceV2();
|
|
46563
|
+
const { createFile, deleteFileById } = useFileRepo();
|
|
46564
|
+
async function createUserBySignUp({
|
|
46565
|
+
id = "",
|
|
46566
|
+
name = ""
|
|
46567
|
+
}) {
|
|
46568
|
+
const session = useAtlas114.getClient()?.startSession();
|
|
46569
|
+
session?.startTransaction();
|
|
46570
|
+
try {
|
|
46571
|
+
const signUp = await _getVerificationById(id);
|
|
46572
|
+
if (!signUp)
|
|
46573
|
+
throw new BadRequestError200("Invalid sign up link.");
|
|
46574
|
+
if (signUp.status === "complete" /* COMPLETE */)
|
|
46575
|
+
throw new BadRequestError200(
|
|
46576
|
+
"You have already an account created using this link."
|
|
46577
|
+
);
|
|
46578
|
+
const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
|
|
46579
|
+
if (signUp.status === "expired" || expired)
|
|
46580
|
+
throw new BadRequestError200("Sign up link expired.");
|
|
46581
|
+
const email = signUp.email;
|
|
46582
|
+
const _user = await _getUserByEmail(email);
|
|
46583
|
+
if (_user)
|
|
46584
|
+
throw new BadRequestError200(`User already exists: ${email}.`);
|
|
46585
|
+
let org = null;
|
|
46586
|
+
if (signUp.metadata?.org) {
|
|
46587
|
+
org = await getOrgById(signUp.metadata.org);
|
|
46588
|
+
if (!org)
|
|
46589
|
+
signUp.metadata.org = "";
|
|
46590
|
+
}
|
|
46591
|
+
if (signUp.metadata?.siteId)
|
|
46592
|
+
await getSiteById(signUp.metadata?.siteId);
|
|
46593
|
+
const user = {
|
|
46594
|
+
email,
|
|
46595
|
+
password: signUp.metadata?.password,
|
|
46596
|
+
name,
|
|
46597
|
+
defaultOrg: org?._id?.toString() || ""
|
|
46598
|
+
};
|
|
46599
|
+
const userId = await _createUser(user, session);
|
|
46600
|
+
if (org?._id) {
|
|
46601
|
+
await addMember(
|
|
46602
|
+
{
|
|
46603
|
+
org: org?._id?.toString() || "",
|
|
46604
|
+
orgName: org?.name || "",
|
|
46605
|
+
user: userId.toString(),
|
|
46606
|
+
name,
|
|
46607
|
+
role: signUp.metadata?.role?.toString() || "",
|
|
46608
|
+
type: signUp.metadata?.app ?? "organization",
|
|
46609
|
+
siteId: signUp.metadata?.siteId?.toString() || "",
|
|
46610
|
+
siteName: signUp.metadata?.siteName || ""
|
|
46611
|
+
},
|
|
46612
|
+
session
|
|
46613
|
+
);
|
|
46614
|
+
}
|
|
46615
|
+
await _updateVerificationStatusById(
|
|
46616
|
+
id,
|
|
46617
|
+
"complete" /* COMPLETE */,
|
|
46618
|
+
session
|
|
46619
|
+
);
|
|
46620
|
+
await session?.commitTransaction();
|
|
46621
|
+
return userId;
|
|
46622
|
+
} catch (error) {
|
|
46623
|
+
await session?.abortTransaction();
|
|
46624
|
+
throw error;
|
|
46625
|
+
} finally {
|
|
46626
|
+
session?.endSession();
|
|
46627
|
+
}
|
|
46628
|
+
}
|
|
46629
|
+
async function resetPassword(id, newPassword, passwordConfirmation) {
|
|
46630
|
+
if (newPassword !== passwordConfirmation) {
|
|
46631
|
+
throw new BadRequestError200("Passwords do not match.");
|
|
46632
|
+
}
|
|
46633
|
+
let hashedPassword;
|
|
46634
|
+
const session = useAtlas114.getClient()?.startSession();
|
|
46635
|
+
session?.startTransaction();
|
|
46636
|
+
try {
|
|
46637
|
+
hashedPassword = await hashPassword5(newPassword);
|
|
46638
|
+
} catch (error) {
|
|
46639
|
+
throw new InternalServerError72(`Error hashing password: ${error}`);
|
|
46640
|
+
}
|
|
46641
|
+
try {
|
|
46642
|
+
const otpDoc = await _getVerificationById(id);
|
|
46643
|
+
if (!otpDoc) {
|
|
46644
|
+
throw new NotFoundError54("You are using an invalid reset link.");
|
|
46645
|
+
}
|
|
46646
|
+
if (otpDoc.status === "complete" /* COMPLETE */) {
|
|
46647
|
+
throw new BadRequestError200("This link has already been invalidated.");
|
|
46648
|
+
}
|
|
46649
|
+
const user = await _getUserByEmail(otpDoc.email);
|
|
46650
|
+
if (!user) {
|
|
46651
|
+
throw new NotFoundError54("User not found.");
|
|
46652
|
+
}
|
|
46653
|
+
if (!user._id) {
|
|
46654
|
+
throw new InternalServerError72("Invalid user ID.");
|
|
46655
|
+
}
|
|
46656
|
+
await Promise.all([
|
|
46657
|
+
_updateVerificationStatusById(id, "complete" /* COMPLETE */, session),
|
|
46658
|
+
_updatePasswordById(
|
|
46659
|
+
{ _id: user._id.toString(), password: hashedPassword },
|
|
46660
|
+
session
|
|
46661
|
+
)
|
|
46662
|
+
]);
|
|
46663
|
+
await session?.commitTransaction();
|
|
46664
|
+
return "Successfully reset password.";
|
|
46665
|
+
} catch (error) {
|
|
46666
|
+
await session?.abortTransaction();
|
|
46667
|
+
throw error;
|
|
46668
|
+
} finally {
|
|
46669
|
+
session?.endSession();
|
|
46670
|
+
}
|
|
46671
|
+
}
|
|
46672
|
+
const s3 = new useS33({
|
|
46673
|
+
accessKeyId: SPACES_ACCESS_KEY,
|
|
46674
|
+
secretAccessKey: SPACES_SECRET_KEY,
|
|
46675
|
+
endpoint: SPACES_ENDPOINT,
|
|
46676
|
+
region: SPACES_REGION,
|
|
46677
|
+
bucket: SPACES_BUCKET,
|
|
46678
|
+
forcePathStyle: false
|
|
46679
|
+
});
|
|
46680
|
+
async function updateUserProfile({
|
|
46681
|
+
file,
|
|
46682
|
+
user,
|
|
46683
|
+
previousProfile
|
|
46684
|
+
}) {
|
|
46685
|
+
const session = useAtlas114.getClient()?.startSession();
|
|
46686
|
+
session?.startTransaction();
|
|
46687
|
+
const _file = {
|
|
46688
|
+
name: file.originalname,
|
|
46689
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
46690
|
+
};
|
|
46691
|
+
try {
|
|
46692
|
+
const id = await createFile(_file, session);
|
|
46693
|
+
await s3.uploadObject({
|
|
46694
|
+
key: id,
|
|
46695
|
+
body: file.buffer,
|
|
46696
|
+
contentType: file.mimetype
|
|
46697
|
+
});
|
|
46698
|
+
if (previousProfile) {
|
|
46699
|
+
await deleteFileById(previousProfile, session);
|
|
46700
|
+
await s3.deleteObject(previousProfile);
|
|
46701
|
+
}
|
|
46702
|
+
await _updateUserFieldById(
|
|
46703
|
+
{ _id: user, field: "profile", value: id },
|
|
46704
|
+
session
|
|
46705
|
+
);
|
|
46706
|
+
await session?.commitTransaction();
|
|
46707
|
+
return id;
|
|
46708
|
+
} catch (error) {
|
|
46709
|
+
await session?.abortTransaction();
|
|
46710
|
+
throw error;
|
|
46711
|
+
} finally {
|
|
46712
|
+
session?.endSession();
|
|
46713
|
+
}
|
|
46714
|
+
}
|
|
46715
|
+
async function updatePasswordById(id, currentPassword, newPassword, passwordConfirmation) {
|
|
46716
|
+
let hashedPassword;
|
|
46717
|
+
const user = await getUserById(id);
|
|
46718
|
+
const isPasswordValid = await comparePassword4(
|
|
46719
|
+
currentPassword,
|
|
46720
|
+
user.password
|
|
46721
|
+
);
|
|
46722
|
+
if (!isPasswordValid)
|
|
46723
|
+
throw new BadRequestError200("Invalid current password.");
|
|
46724
|
+
if (newPassword !== passwordConfirmation)
|
|
46725
|
+
throw new BadRequestError200("Passwords do not match.");
|
|
46726
|
+
try {
|
|
46727
|
+
hashedPassword = await hashPassword5(newPassword);
|
|
46728
|
+
if (!hashedPassword)
|
|
46729
|
+
throw new InternalServerError72("Error hashing password.");
|
|
46730
|
+
return await updatePassword({ _id: id, password: hashedPassword });
|
|
46731
|
+
} catch (error) {
|
|
46732
|
+
throw error;
|
|
46733
|
+
}
|
|
46734
|
+
}
|
|
46735
|
+
return {
|
|
46736
|
+
createUserBySignUp,
|
|
46737
|
+
resetPassword,
|
|
46738
|
+
updateUserProfile,
|
|
46739
|
+
updatePasswordById
|
|
46740
|
+
};
|
|
46741
|
+
}
|
|
46742
|
+
|
|
46304
46743
|
// src/controllers/auth-v2.controller.ts
|
|
46305
46744
|
function useAuthControllerV2() {
|
|
46306
46745
|
const { signUp: _signUp } = useVerificationServiceV2();
|
|
46307
46746
|
const { login: _login, logout: _logout } = useAuthServiceV2();
|
|
46747
|
+
const { resetPassword: _resetPassword } = useUserServiceV2();
|
|
46308
46748
|
async function signUp(req, res, next) {
|
|
46309
46749
|
try {
|
|
46310
46750
|
const validation = Joi127.object({
|
|
@@ -46318,8 +46758,8 @@ function useAuthControllerV2() {
|
|
|
46318
46758
|
});
|
|
46319
46759
|
if (error) {
|
|
46320
46760
|
const messages = error.details.map((d) => d.message);
|
|
46321
|
-
|
|
46322
|
-
next(new
|
|
46761
|
+
logger180.log({ level: "error", message: messages.join(", ") });
|
|
46762
|
+
next(new BadRequestError201(messages.join(", ")));
|
|
46323
46763
|
return;
|
|
46324
46764
|
}
|
|
46325
46765
|
const { email, password, country, orgName } = value;
|
|
@@ -46335,7 +46775,7 @@ function useAuthControllerV2() {
|
|
|
46335
46775
|
return;
|
|
46336
46776
|
} catch (error) {
|
|
46337
46777
|
console.log(error);
|
|
46338
|
-
|
|
46778
|
+
logger180.log({ level: "error", message: error.message });
|
|
46339
46779
|
next(error);
|
|
46340
46780
|
return;
|
|
46341
46781
|
}
|
|
@@ -46353,8 +46793,8 @@ function useAuthControllerV2() {
|
|
|
46353
46793
|
});
|
|
46354
46794
|
if (error) {
|
|
46355
46795
|
const messages = error.details.map((d) => d.message);
|
|
46356
|
-
|
|
46357
|
-
next(new
|
|
46796
|
+
logger180.log({ level: "error", message: messages.join(", ") });
|
|
46797
|
+
next(new BadRequestError201(messages.join(", ")));
|
|
46358
46798
|
return;
|
|
46359
46799
|
}
|
|
46360
46800
|
const session = await _login(value);
|
|
@@ -46366,7 +46806,7 @@ function useAuthControllerV2() {
|
|
|
46366
46806
|
res.cookie("sid", session.sid, cookieOptions).cookie("user", session.user, cookieOptions).json(session);
|
|
46367
46807
|
return;
|
|
46368
46808
|
} catch (error) {
|
|
46369
|
-
|
|
46809
|
+
logger180.log({ level: "error", message: error.message });
|
|
46370
46810
|
next(error);
|
|
46371
46811
|
return;
|
|
46372
46812
|
}
|
|
@@ -46374,7 +46814,7 @@ function useAuthControllerV2() {
|
|
|
46374
46814
|
async function logout(req, res, next) {
|
|
46375
46815
|
const sid = req.headers["authorization"] ?? "";
|
|
46376
46816
|
if (!sid) {
|
|
46377
|
-
next(new
|
|
46817
|
+
next(new BadRequestError201("Session ID is required"));
|
|
46378
46818
|
return;
|
|
46379
46819
|
}
|
|
46380
46820
|
try {
|
|
@@ -46382,130 +46822,170 @@ function useAuthControllerV2() {
|
|
|
46382
46822
|
res.json({ message: "Logged out successfully" });
|
|
46383
46823
|
return;
|
|
46384
46824
|
} catch (error) {
|
|
46385
|
-
|
|
46825
|
+
logger180.log({ level: "error", message: error.message });
|
|
46386
46826
|
next(error);
|
|
46387
46827
|
return;
|
|
46388
46828
|
}
|
|
46389
46829
|
}
|
|
46390
|
-
|
|
46391
|
-
|
|
46392
|
-
|
|
46393
|
-
|
|
46394
|
-
|
|
46395
|
-
}
|
|
46396
|
-
|
|
46397
|
-
|
|
46398
|
-
|
|
46399
|
-
|
|
46400
|
-
|
|
46401
|
-
|
|
46402
|
-
|
|
46403
|
-
|
|
46404
|
-
|
|
46405
|
-
|
|
46406
|
-
const { add: addMember } = useMemberRepo();
|
|
46407
|
-
const { getById: getOrgById } = useOrgRepo();
|
|
46408
|
-
const { getSiteById } = useSiteRepo();
|
|
46409
|
-
const {
|
|
46410
|
-
getVerificationById: _getVerificationById,
|
|
46411
|
-
updateVerificationStatusById: _updateVerificationStatusById
|
|
46412
|
-
} = useVerificationRepoV2();
|
|
46413
|
-
const { verify } = useVerificationService();
|
|
46414
|
-
const { createFile, deleteFileById } = useFileRepo();
|
|
46415
|
-
async function createUserBySignUp({
|
|
46416
|
-
id = "",
|
|
46417
|
-
name = ""
|
|
46418
|
-
}) {
|
|
46419
|
-
const session = useAtlas114.getClient()?.startSession();
|
|
46420
|
-
session?.startTransaction();
|
|
46830
|
+
async function resetPassword(req, res, next) {
|
|
46831
|
+
const validation = Joi127.object({
|
|
46832
|
+
otp: Joi127.string().hex().required(),
|
|
46833
|
+
newPassword: Joi127.string().required().min(8),
|
|
46834
|
+
passwordConfirmation: Joi127.string().required().min(8)
|
|
46835
|
+
});
|
|
46836
|
+
const { error, value } = validation.validate(req.body, {
|
|
46837
|
+
abortEarly: false
|
|
46838
|
+
});
|
|
46839
|
+
if (error) {
|
|
46840
|
+
const messages = error.details.map((d) => d.message);
|
|
46841
|
+
logger180.log({ level: "error", message: messages.join(", ") });
|
|
46842
|
+
next(new BadRequestError201(messages.join(", ")));
|
|
46843
|
+
return;
|
|
46844
|
+
}
|
|
46845
|
+
const { otp, newPassword, passwordConfirmation } = value;
|
|
46421
46846
|
try {
|
|
46422
|
-
const
|
|
46423
|
-
|
|
46424
|
-
|
|
46425
|
-
|
|
46426
|
-
throw new BadRequestError201(
|
|
46427
|
-
"You have already an account created using this link."
|
|
46428
|
-
);
|
|
46429
|
-
const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
|
|
46430
|
-
if (signUp.status === "expired" || expired)
|
|
46431
|
-
throw new BadRequestError201("Sign up link expired.");
|
|
46432
|
-
const email = signUp.email;
|
|
46433
|
-
const _user = await getUserByEmail(email);
|
|
46434
|
-
if (_user)
|
|
46435
|
-
throw new BadRequestError201(`User already exists: ${email}.`);
|
|
46436
|
-
let org = null;
|
|
46437
|
-
if (signUp.metadata?.org) {
|
|
46438
|
-
org = await getOrgById(signUp.metadata.org);
|
|
46439
|
-
if (!org)
|
|
46440
|
-
signUp.metadata.org = "";
|
|
46441
|
-
}
|
|
46442
|
-
if (signUp.metadata?.siteId)
|
|
46443
|
-
await getSiteById(signUp.metadata?.siteId);
|
|
46444
|
-
const user = {
|
|
46445
|
-
email,
|
|
46446
|
-
password: signUp.metadata?.password,
|
|
46447
|
-
name,
|
|
46448
|
-
defaultOrg: org?._id?.toString() || ""
|
|
46449
|
-
};
|
|
46450
|
-
const userId = await _createUser(user, session);
|
|
46451
|
-
if (org?._id) {
|
|
46452
|
-
await addMember(
|
|
46453
|
-
{
|
|
46454
|
-
org: org?._id?.toString() || "",
|
|
46455
|
-
orgName: org?.name || "",
|
|
46456
|
-
user: userId.toString(),
|
|
46457
|
-
name,
|
|
46458
|
-
role: signUp.metadata?.role?.toString() || "",
|
|
46459
|
-
type: signUp.metadata?.app ?? "organization",
|
|
46460
|
-
siteId: signUp.metadata?.siteId?.toString() || "",
|
|
46461
|
-
siteName: signUp.metadata?.siteName || ""
|
|
46462
|
-
},
|
|
46463
|
-
session
|
|
46464
|
-
);
|
|
46465
|
-
}
|
|
46466
|
-
await _updateVerificationStatusById(
|
|
46467
|
-
id,
|
|
46468
|
-
"complete" /* COMPLETE */,
|
|
46469
|
-
session
|
|
46847
|
+
const message = await _resetPassword(
|
|
46848
|
+
otp,
|
|
46849
|
+
newPassword,
|
|
46850
|
+
passwordConfirmation
|
|
46470
46851
|
);
|
|
46471
|
-
|
|
46472
|
-
return
|
|
46473
|
-
} catch (
|
|
46474
|
-
|
|
46475
|
-
|
|
46476
|
-
|
|
46477
|
-
session?.endSession();
|
|
46852
|
+
res.json({ message });
|
|
46853
|
+
return;
|
|
46854
|
+
} catch (error2) {
|
|
46855
|
+
logger180.log({ level: "error", message: error2.message });
|
|
46856
|
+
next(error2);
|
|
46857
|
+
return;
|
|
46478
46858
|
}
|
|
46479
46859
|
}
|
|
46480
46860
|
return {
|
|
46481
|
-
|
|
46861
|
+
signUp,
|
|
46862
|
+
login,
|
|
46863
|
+
logout,
|
|
46864
|
+
resetPassword
|
|
46482
46865
|
};
|
|
46483
46866
|
}
|
|
46484
46867
|
|
|
46485
46868
|
// src/controllers/user-v2.controller.ts
|
|
46486
46869
|
import Joi128 from "joi";
|
|
46870
|
+
import "multer";
|
|
46487
46871
|
import { BadRequestError as BadRequestError202, logger as logger181 } from "@7365admin1/node-server-utils";
|
|
46488
46872
|
function useUserControllerV2() {
|
|
46489
|
-
const {
|
|
46873
|
+
const {
|
|
46874
|
+
updateBirthday: _updateBirthday,
|
|
46875
|
+
getUserById: _getUserById,
|
|
46876
|
+
getUserByEmail: _getUserByEmail,
|
|
46877
|
+
getUserById: _getById,
|
|
46878
|
+
getUsers: _getUsers,
|
|
46879
|
+
getUsersByOrgId: _getUsersByOrgId,
|
|
46880
|
+
updateUserFieldById: _updateUserFieldById
|
|
46881
|
+
} = useUserRepoV2();
|
|
46882
|
+
const { createUserBySignUp, updateUserProfile: _updateUserProfile, updatePasswordById: _updatePasswordById } = useUserServiceV2();
|
|
46883
|
+
function rejectValidation(error, next) {
|
|
46884
|
+
const message = error.details.map((d) => d.message).join(", ");
|
|
46885
|
+
logger181.log({ level: "error", message });
|
|
46886
|
+
next(new BadRequestError202(message));
|
|
46887
|
+
}
|
|
46888
|
+
async function getById(req, res, next) {
|
|
46889
|
+
const validation = Joi128.string().hex().required();
|
|
46890
|
+
const _id = req.params.id;
|
|
46891
|
+
const { error, value } = validation.validate(_id);
|
|
46892
|
+
if (error) {
|
|
46893
|
+
logger181.log({ level: "error", message: `${error.message}` });
|
|
46894
|
+
next(new BadRequestError202(error.message));
|
|
46895
|
+
return;
|
|
46896
|
+
}
|
|
46897
|
+
try {
|
|
46898
|
+
const user = await _getById(value);
|
|
46899
|
+
res.json(user);
|
|
46900
|
+
return;
|
|
46901
|
+
} catch (error2) {
|
|
46902
|
+
logger181.log({ level: "error", message: `${error2.message}` });
|
|
46903
|
+
next(error2);
|
|
46904
|
+
return;
|
|
46905
|
+
}
|
|
46906
|
+
}
|
|
46907
|
+
async function getByEmail(req, res, next) {
|
|
46908
|
+
const { error, value } = Joi128.string().email().required().validate(req.params.email);
|
|
46909
|
+
if (error)
|
|
46910
|
+
return rejectValidation(error, next);
|
|
46911
|
+
try {
|
|
46912
|
+
const user = await _getUserByEmail(value);
|
|
46913
|
+
res.json(user);
|
|
46914
|
+
return;
|
|
46915
|
+
} catch (err) {
|
|
46916
|
+
logger181.log({ level: "error", message: `${err.message}` });
|
|
46917
|
+
next(err);
|
|
46918
|
+
return;
|
|
46919
|
+
}
|
|
46920
|
+
}
|
|
46921
|
+
async function getUsers(req, res, next) {
|
|
46922
|
+
const { search = "", page = 1, limit = 10, sort = {}, type = "", status = "active" } = req.query;
|
|
46923
|
+
const { error, value } = Joi128.object({
|
|
46924
|
+
search: Joi128.string().optional().allow("", null),
|
|
46925
|
+
page: Joi128.number().integer().min(1).allow("", null).default(1),
|
|
46926
|
+
limit: Joi128.number().integer().min(1).allow("", null).default(10),
|
|
46927
|
+
sort: Joi128.object().optional().allow("", null).default({}),
|
|
46928
|
+
type: Joi128.string().optional().allow("", null).default(""),
|
|
46929
|
+
status: Joi128.string().optional().allow("", null).default("active" /* ACTIVE */)
|
|
46930
|
+
}).validate({ search, page, limit, sort, type, status });
|
|
46931
|
+
if (error)
|
|
46932
|
+
return rejectValidation(error, next);
|
|
46933
|
+
try {
|
|
46934
|
+
const users = await _getUsers({
|
|
46935
|
+
search: value.search ?? "",
|
|
46936
|
+
page: value.page,
|
|
46937
|
+
limit: value.limit,
|
|
46938
|
+
sort: value.sort,
|
|
46939
|
+
type: value.type,
|
|
46940
|
+
status: value.status
|
|
46941
|
+
});
|
|
46942
|
+
res.json(users);
|
|
46943
|
+
return;
|
|
46944
|
+
} catch (err) {
|
|
46945
|
+
next(err);
|
|
46946
|
+
}
|
|
46947
|
+
}
|
|
46948
|
+
async function getUsersByOrgId(req, res, next) {
|
|
46949
|
+
const { search, page, status, organization } = req.query;
|
|
46950
|
+
const { error, value } = Joi128.object({
|
|
46951
|
+
search: Joi128.string().optional().allow("", null),
|
|
46952
|
+
page: Joi128.number().integer().min(1).allow("", null).default(1),
|
|
46953
|
+
status: Joi128.string().required(),
|
|
46954
|
+
organization: Joi128.string().required()
|
|
46955
|
+
}).validate({ search, page, status, organization });
|
|
46956
|
+
if (error)
|
|
46957
|
+
return rejectValidation(error, next);
|
|
46958
|
+
try {
|
|
46959
|
+
res.json(
|
|
46960
|
+
await _getUsersByOrgId({
|
|
46961
|
+
search: value.search ?? "",
|
|
46962
|
+
page: value.page,
|
|
46963
|
+
status: value.status,
|
|
46964
|
+
organization: value.organization
|
|
46965
|
+
})
|
|
46966
|
+
);
|
|
46967
|
+
} catch (err) {
|
|
46968
|
+
next(err);
|
|
46969
|
+
}
|
|
46970
|
+
}
|
|
46490
46971
|
async function createUserByVerification(req, res, next) {
|
|
46491
|
-
const
|
|
46492
|
-
|
|
46972
|
+
const allowedTypes = ["user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */];
|
|
46973
|
+
const validation = Joi128.object({
|
|
46974
|
+
id: Joi128.string().hex().required(),
|
|
46493
46975
|
name: Joi128.string().required(),
|
|
46494
|
-
|
|
46495
|
-
|
|
46496
|
-
const { error, value } = schema2.validate({
|
|
46497
|
-
id: req.params.id,
|
|
46498
|
-
...req.body
|
|
46976
|
+
password: Joi128.string().required(),
|
|
46977
|
+
type: Joi128.string().required().valid(...allowedTypes)
|
|
46499
46978
|
});
|
|
46979
|
+
const id = req.params.id;
|
|
46980
|
+
const payload = { ...req.body };
|
|
46981
|
+
const { error, value } = validation.validate({ id, ...payload });
|
|
46500
46982
|
if (error) {
|
|
46501
|
-
|
|
46502
|
-
|
|
46503
|
-
next(new BadRequestError202(messages));
|
|
46983
|
+
logger181.log({ level: "error", message: `${error.message}` });
|
|
46984
|
+
next(new BadRequestError202(error.message));
|
|
46504
46985
|
return;
|
|
46505
46986
|
}
|
|
46506
|
-
const { id, name } = value;
|
|
46507
46987
|
try {
|
|
46508
|
-
await
|
|
46988
|
+
await createUserBySignUp({ id: value.id, name: value.name });
|
|
46509
46989
|
res.status(201).json({ message: "Successfully created account." });
|
|
46510
46990
|
return;
|
|
46511
46991
|
} catch (error2) {
|
|
@@ -46514,8 +46994,148 @@ function useUserControllerV2() {
|
|
|
46514
46994
|
return;
|
|
46515
46995
|
}
|
|
46516
46996
|
}
|
|
46997
|
+
async function updateUserProfile(req, res, next) {
|
|
46998
|
+
if (!req.file) {
|
|
46999
|
+
next(new BadRequestError202("File is required!"));
|
|
47000
|
+
return;
|
|
47001
|
+
}
|
|
47002
|
+
const validation = Joi128.object({
|
|
47003
|
+
previousProfile: Joi128.string().hex().optional().allow("", null)
|
|
47004
|
+
});
|
|
47005
|
+
const payload = { ...req.body };
|
|
47006
|
+
const { error, value } = validation.validate(payload);
|
|
47007
|
+
if (error) {
|
|
47008
|
+
logger181.log({ level: "error", message: `${error.message}` });
|
|
47009
|
+
next(new BadRequestError202(error.message));
|
|
47010
|
+
return;
|
|
47011
|
+
}
|
|
47012
|
+
const user = req.headers.user ?? "";
|
|
47013
|
+
try {
|
|
47014
|
+
await _updateUserProfile({
|
|
47015
|
+
file: req.file,
|
|
47016
|
+
user,
|
|
47017
|
+
...value
|
|
47018
|
+
});
|
|
47019
|
+
res.json({ message: "Successfully updated profile picture." });
|
|
47020
|
+
return;
|
|
47021
|
+
} catch (error2) {
|
|
47022
|
+
logger181.log({ level: "error", message: `${error2.message}` });
|
|
47023
|
+
next(error2);
|
|
47024
|
+
return;
|
|
47025
|
+
}
|
|
47026
|
+
}
|
|
47027
|
+
async function updateBirthday(req, res, next) {
|
|
47028
|
+
const MONTHS = [
|
|
47029
|
+
"January",
|
|
47030
|
+
"February",
|
|
47031
|
+
"March",
|
|
47032
|
+
"April",
|
|
47033
|
+
"May",
|
|
47034
|
+
"June",
|
|
47035
|
+
"July",
|
|
47036
|
+
"August",
|
|
47037
|
+
"September",
|
|
47038
|
+
"October",
|
|
47039
|
+
"November",
|
|
47040
|
+
"December"
|
|
47041
|
+
];
|
|
47042
|
+
const validation = Joi128.object({
|
|
47043
|
+
_id: Joi128.string().hex().required(),
|
|
47044
|
+
month: Joi128.string().valid(...MONTHS).required(),
|
|
47045
|
+
day: Joi128.number().integer().min(1).max(31).required(),
|
|
47046
|
+
year: Joi128.number().integer().min(1900).max((/* @__PURE__ */ new Date()).getFullYear()).required()
|
|
47047
|
+
});
|
|
47048
|
+
const _id = req.params.id;
|
|
47049
|
+
const payload = { ...req.body };
|
|
47050
|
+
const { error } = validation.validate({ _id, ...payload });
|
|
47051
|
+
if (error) {
|
|
47052
|
+
logger181.log({ level: "error", message: `${error.message}` });
|
|
47053
|
+
next(new BadRequestError202(error.message));
|
|
47054
|
+
return;
|
|
47055
|
+
}
|
|
47056
|
+
try {
|
|
47057
|
+
const message = await _updateBirthday({ _id, ...payload });
|
|
47058
|
+
res.json({ message });
|
|
47059
|
+
return;
|
|
47060
|
+
} catch (error2) {
|
|
47061
|
+
logger181.log({ level: "error", message: `${error2.message}` });
|
|
47062
|
+
next(error2);
|
|
47063
|
+
return;
|
|
47064
|
+
}
|
|
47065
|
+
}
|
|
47066
|
+
async function updateUserFieldById(req, res, next) {
|
|
47067
|
+
const FIELDS = ["name", "email", "contact", "nric", "dateOfBirth", "profile", "gender", "defaultOrg"];
|
|
47068
|
+
const validation = Joi128.object({
|
|
47069
|
+
_id: Joi128.string().hex().required(),
|
|
47070
|
+
field: Joi128.string().valid(...FIELDS).required(),
|
|
47071
|
+
value: Joi128.when("field", {
|
|
47072
|
+
switch: [
|
|
47073
|
+
{ is: "email", then: Joi128.string().email().required() },
|
|
47074
|
+
{ is: "defaultOrg", then: Joi128.string().hex().required() }
|
|
47075
|
+
],
|
|
47076
|
+
otherwise: Joi128.string().required()
|
|
47077
|
+
})
|
|
47078
|
+
});
|
|
47079
|
+
const _id = req.params.id;
|
|
47080
|
+
const payload = { ...req.body };
|
|
47081
|
+
const { error } = validation.validate({ _id, ...payload });
|
|
47082
|
+
if (error) {
|
|
47083
|
+
logger181.log({ level: "error", message: `${error.message}` });
|
|
47084
|
+
next(new BadRequestError202(error.message));
|
|
47085
|
+
return;
|
|
47086
|
+
}
|
|
47087
|
+
try {
|
|
47088
|
+
const message = await _updateUserFieldById({ _id, ...payload });
|
|
47089
|
+
res.json({ message });
|
|
47090
|
+
return;
|
|
47091
|
+
} catch (error2) {
|
|
47092
|
+
logger181.log({ level: "error", message: `${error2.message}` });
|
|
47093
|
+
next(error2);
|
|
47094
|
+
return;
|
|
47095
|
+
}
|
|
47096
|
+
}
|
|
47097
|
+
async function updatePasswordById(req, res, next) {
|
|
47098
|
+
const validation = Joi128.object({
|
|
47099
|
+
_id: Joi128.string().hex().required(),
|
|
47100
|
+
currentPassword: Joi128.string().required().min(8),
|
|
47101
|
+
newPassword: Joi128.string().required().min(8),
|
|
47102
|
+
passwordConfirmation: Joi128.string().required().min(8)
|
|
47103
|
+
});
|
|
47104
|
+
const _id = req.params.id;
|
|
47105
|
+
const payload = { ...req.body };
|
|
47106
|
+
const { error } = validation.validate({
|
|
47107
|
+
_id,
|
|
47108
|
+
...payload
|
|
47109
|
+
});
|
|
47110
|
+
if (error) {
|
|
47111
|
+
next(new BadRequestError202(error.message));
|
|
47112
|
+
return;
|
|
47113
|
+
}
|
|
47114
|
+
const currentPassword = req.body.currentPassword ?? "";
|
|
47115
|
+
const newPassword = req.body.newPassword ?? "";
|
|
47116
|
+
const passwordConfirmation = req.body.passwordConfirmation ?? "";
|
|
47117
|
+
try {
|
|
47118
|
+
await _updatePasswordById(
|
|
47119
|
+
_id,
|
|
47120
|
+
currentPassword,
|
|
47121
|
+
newPassword,
|
|
47122
|
+
passwordConfirmation
|
|
47123
|
+
);
|
|
47124
|
+
res.json({ message: "Successfully updated password." });
|
|
47125
|
+
} catch (error2) {
|
|
47126
|
+
next(error2);
|
|
47127
|
+
}
|
|
47128
|
+
}
|
|
46517
47129
|
return {
|
|
46518
|
-
|
|
47130
|
+
getById,
|
|
47131
|
+
getByEmail,
|
|
47132
|
+
getUsersByOrgId,
|
|
47133
|
+
getUsers,
|
|
47134
|
+
createUserByVerification,
|
|
47135
|
+
updateUserProfile,
|
|
47136
|
+
updateBirthday,
|
|
47137
|
+
updateUserFieldById,
|
|
47138
|
+
updatePasswordById
|
|
46519
47139
|
};
|
|
46520
47140
|
}
|
|
46521
47141
|
export {
|
|
@@ -46657,6 +47277,7 @@ export {
|
|
|
46657
47277
|
occurrence_book_namespace_collection,
|
|
46658
47278
|
orgSchema,
|
|
46659
47279
|
overnight_parking_requests_namespace_collection,
|
|
47280
|
+
parseDahuaFind,
|
|
46660
47281
|
pestDashboardCollection,
|
|
46661
47282
|
poolDashboardCollection,
|
|
46662
47283
|
promoCodeSchema,
|