@7365admin1/core 3.32.2-staging.78 → 3.32.2-staging.79
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/dist/index.d.ts +14 -9
- package/dist/index.js +190 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +190 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -9209,7 +9209,7 @@ type HidObjectBatch = {
|
|
|
9209
9209
|
};
|
|
9210
9210
|
type HidObjectQuery = {
|
|
9211
9211
|
object: string;
|
|
9212
|
-
where?:
|
|
9212
|
+
where?: UnknownRecord;
|
|
9213
9213
|
fields?: string[];
|
|
9214
9214
|
order?: string[];
|
|
9215
9215
|
limit?: number;
|
|
@@ -9241,14 +9241,19 @@ declare function useHidAmicoService(): {
|
|
|
9241
9241
|
message: string;
|
|
9242
9242
|
results: Record<string, any>[];
|
|
9243
9243
|
}>;
|
|
9244
|
-
receiveNotification: (readerId: string, type: string, payload:
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9244
|
+
receiveNotification: (readerId: string, type: string, payload: UnknownRecord) => Promise<{
|
|
9245
|
+
event: {
|
|
9246
|
+
_id: bson.ObjectId;
|
|
9247
|
+
reader: bson.ObjectId;
|
|
9248
|
+
site: bson.ObjectId | undefined;
|
|
9249
|
+
type: string;
|
|
9250
|
+
payload: Record<string, any>;
|
|
9251
|
+
status: "failed" | "received" | "processed";
|
|
9252
|
+
createdAt: string | Date;
|
|
9253
|
+
};
|
|
9254
|
+
response: {
|
|
9255
|
+
result: UnknownRecord;
|
|
9256
|
+
} | null;
|
|
9252
9257
|
}>;
|
|
9253
9258
|
listLogs: (value: {
|
|
9254
9259
|
reader: string;
|
package/dist/index.js
CHANGED
|
@@ -74438,6 +74438,8 @@ var schemaHidAmicoNotificationParams = import_joi153.default.object({
|
|
|
74438
74438
|
"secbox",
|
|
74439
74439
|
"access_photo",
|
|
74440
74440
|
"new_user_identified",
|
|
74441
|
+
"new_qrcode",
|
|
74442
|
+
"new_card",
|
|
74441
74443
|
"push_result"
|
|
74442
74444
|
).required()
|
|
74443
74445
|
});
|
|
@@ -75269,6 +75271,8 @@ async function configureVisitorQrReader(client, qrFormat) {
|
|
|
75269
75271
|
}
|
|
75270
75272
|
async function ensureVisitorAccessAuthorization(client, readerId, readerLocation, hidUserId) {
|
|
75271
75273
|
const accessRuleId = createStableHidId(`visitor-access-rule:${readerId}`);
|
|
75274
|
+
const timeZoneId = createStableHidId(`visitor-time-zone:${readerId}`);
|
|
75275
|
+
const timeSpanId = createStableHidId(`visitor-time-span:${readerId}`);
|
|
75272
75276
|
const existingRuleResponse = await client.loadObjects({
|
|
75273
75277
|
object: "access_rules",
|
|
75274
75278
|
where: { access_rules: { id: accessRuleId } },
|
|
@@ -75296,6 +75300,74 @@ async function ensureVisitorAccessAuthorization(client, readerId, readerLocation
|
|
|
75296
75300
|
}]
|
|
75297
75301
|
});
|
|
75298
75302
|
}
|
|
75303
|
+
const existingTimeZoneResponse = await client.loadObjects({
|
|
75304
|
+
object: "time_zones",
|
|
75305
|
+
where: { time_zones: { id: timeZoneId } },
|
|
75306
|
+
limit: 1,
|
|
75307
|
+
offset: 0
|
|
75308
|
+
});
|
|
75309
|
+
if (getHidObjectRows(existingTimeZoneResponse, "time_zones").length) {
|
|
75310
|
+
await client.modifyObjects({
|
|
75311
|
+
object: "time_zones",
|
|
75312
|
+
where: { time_zones: { id: timeZoneId } },
|
|
75313
|
+
values: { name: "iService365 Visitor Schedule" }
|
|
75314
|
+
});
|
|
75315
|
+
} else {
|
|
75316
|
+
await client.createObjects({
|
|
75317
|
+
object: "time_zones",
|
|
75318
|
+
values: [{ id: timeZoneId, name: "iService365 Visitor Schedule" }]
|
|
75319
|
+
});
|
|
75320
|
+
}
|
|
75321
|
+
const visitorTimeSpan = {
|
|
75322
|
+
time_zone_id: timeZoneId,
|
|
75323
|
+
start: 0,
|
|
75324
|
+
end: 86399,
|
|
75325
|
+
sun: 1,
|
|
75326
|
+
mon: 1,
|
|
75327
|
+
tue: 1,
|
|
75328
|
+
wed: 1,
|
|
75329
|
+
thu: 1,
|
|
75330
|
+
fri: 1,
|
|
75331
|
+
sat: 1,
|
|
75332
|
+
hol1: 1,
|
|
75333
|
+
hol2: 1,
|
|
75334
|
+
hol3: 1
|
|
75335
|
+
};
|
|
75336
|
+
const existingTimeSpanResponse = await client.loadObjects({
|
|
75337
|
+
object: "time_spans",
|
|
75338
|
+
where: { time_spans: { id: timeSpanId } },
|
|
75339
|
+
limit: 1,
|
|
75340
|
+
offset: 0
|
|
75341
|
+
});
|
|
75342
|
+
if (getHidObjectRows(existingTimeSpanResponse, "time_spans").length) {
|
|
75343
|
+
await client.modifyObjects({
|
|
75344
|
+
object: "time_spans",
|
|
75345
|
+
where: { time_spans: { id: timeSpanId } },
|
|
75346
|
+
values: visitorTimeSpan
|
|
75347
|
+
});
|
|
75348
|
+
} else {
|
|
75349
|
+
await client.createObjects({
|
|
75350
|
+
object: "time_spans",
|
|
75351
|
+
values: [{ id: timeSpanId, ...visitorTimeSpan }]
|
|
75352
|
+
});
|
|
75353
|
+
}
|
|
75354
|
+
const accessRuleTimeZoneResponse = await client.loadObjects({
|
|
75355
|
+
object: "access_rule_time_zones",
|
|
75356
|
+
where: {
|
|
75357
|
+
access_rule_time_zones: {
|
|
75358
|
+
access_rule_id: accessRuleId,
|
|
75359
|
+
time_zone_id: timeZoneId
|
|
75360
|
+
}
|
|
75361
|
+
},
|
|
75362
|
+
limit: 1,
|
|
75363
|
+
offset: 0
|
|
75364
|
+
});
|
|
75365
|
+
if (!getHidObjectRows(accessRuleTimeZoneResponse, "access_rule_time_zones").length) {
|
|
75366
|
+
await client.createObjects({
|
|
75367
|
+
object: "access_rule_time_zones",
|
|
75368
|
+
values: [{ access_rule_id: accessRuleId, time_zone_id: timeZoneId }]
|
|
75369
|
+
});
|
|
75370
|
+
}
|
|
75299
75371
|
const portalsResponse = await client.loadObjects({
|
|
75300
75372
|
object: "portals",
|
|
75301
75373
|
limit: 100,
|
|
@@ -75350,7 +75422,7 @@ async function ensureVisitorAccessAuthorization(client, readerId, readerLocation
|
|
|
75350
75422
|
values: missingPortalLinks
|
|
75351
75423
|
});
|
|
75352
75424
|
}
|
|
75353
|
-
return { accessRuleId, portalIds };
|
|
75425
|
+
return { accessRuleId, portalIds, timeZoneId };
|
|
75354
75426
|
}
|
|
75355
75427
|
function getRelayAuth() {
|
|
75356
75428
|
const username = process.env.HID_AMICO_RELAY_USERNAME;
|
|
@@ -75688,19 +75760,95 @@ function normalizeBatches(payload) {
|
|
|
75688
75760
|
function firstValue(payload, keys) {
|
|
75689
75761
|
for (const key of keys) {
|
|
75690
75762
|
const value = payload?.[key];
|
|
75691
|
-
if (value
|
|
75763
|
+
if ((typeof value === "string" || typeof value === "number") && value !== "") {
|
|
75692
75764
|
return value;
|
|
75693
75765
|
}
|
|
75694
75766
|
}
|
|
75695
75767
|
return void 0;
|
|
75696
75768
|
}
|
|
75697
75769
|
function extractIdentityKeys(payload) {
|
|
75698
|
-
const
|
|
75770
|
+
const nestedCandidate = payload.user || payload.person || payload.data;
|
|
75771
|
+
const nested = isUnknownRecord(nestedCandidate) ? nestedCandidate : {};
|
|
75699
75772
|
const merged = { ...payload, ...nested };
|
|
75773
|
+
const hidUserId = firstValue(merged, ["hidUserId", "hid_user_id", "user_id", "userId", "id", "user"]);
|
|
75774
|
+
const registration = firstValue(merged, ["registration", "register", "employeeNo", "staffNo", "memberNo"]);
|
|
75775
|
+
const cardNo = firstValue(merged, [
|
|
75776
|
+
"qrcode_value",
|
|
75777
|
+
"qrCodeValue",
|
|
75778
|
+
"qr_code_value",
|
|
75779
|
+
"card_value",
|
|
75780
|
+
"cardNo",
|
|
75781
|
+
"card_no",
|
|
75782
|
+
"card",
|
|
75783
|
+
"cardNumber",
|
|
75784
|
+
"value"
|
|
75785
|
+
]);
|
|
75786
|
+
return {
|
|
75787
|
+
hidUserId,
|
|
75788
|
+
registration: registration === void 0 ? void 0 : String(registration),
|
|
75789
|
+
cardNo: cardNo === void 0 ? void 0 : String(cardNo)
|
|
75790
|
+
};
|
|
75791
|
+
}
|
|
75792
|
+
function toPositiveInteger(value) {
|
|
75793
|
+
const parsed = Number(value);
|
|
75794
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
|
75795
|
+
}
|
|
75796
|
+
function toDateTimestamp(value) {
|
|
75797
|
+
if (value instanceof Date)
|
|
75798
|
+
return value.getTime();
|
|
75799
|
+
if (typeof value !== "string" && typeof value !== "number")
|
|
75800
|
+
return null;
|
|
75801
|
+
const parsed = new Date(value).getTime();
|
|
75802
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
75803
|
+
}
|
|
75804
|
+
function buildOnlineIdentificationResponse(identity, payload) {
|
|
75805
|
+
const metadata = identity && isUnknownRecord(identity.metadata) ? identity.metadata : {};
|
|
75806
|
+
const requestedPortalId = toPositiveInteger(payload.portal_id ?? payload.portalId);
|
|
75807
|
+
const configuredPortalIds = Array.isArray(metadata.portalIds) ? metadata.portalIds.map(toPositiveInteger).filter((value) => value !== null) : [];
|
|
75808
|
+
const portalId = requestedPortalId ?? (configuredPortalIds.length === 1 ? configuredPortalIds[0] : null);
|
|
75809
|
+
const now = Date.now();
|
|
75810
|
+
const issuedAt = toDateTimestamp(metadata.issuedAt);
|
|
75811
|
+
const expiresAt = toDateTimestamp(metadata.expiresAt);
|
|
75812
|
+
let deniedReason = "User is not registered for this reader.";
|
|
75813
|
+
if (identity) {
|
|
75814
|
+
deniedReason = "Access denied.";
|
|
75815
|
+
if (identity.type === "visitor" && issuedAt !== null && now < issuedAt) {
|
|
75816
|
+
deniedReason = "Visitor pass is not active yet.";
|
|
75817
|
+
} else if (identity.type === "visitor" && expiresAt !== null && now > expiresAt) {
|
|
75818
|
+
deniedReason = "Visitor pass has expired.";
|
|
75819
|
+
} else if (identity.type === "visitor" && configuredPortalIds.length > 0 && requestedPortalId !== null && !configuredPortalIds.includes(requestedPortalId)) {
|
|
75820
|
+
deniedReason = "Visitor is not permitted to use this portal.";
|
|
75821
|
+
} else {
|
|
75822
|
+
const userId = toPositiveInteger(identity.hidUserId ?? payload.user_id);
|
|
75823
|
+
const userName = String(metadata.name ?? payload.user_name ?? "").trim();
|
|
75824
|
+
const result = {
|
|
75825
|
+
event: 7,
|
|
75826
|
+
user_id: userId ?? 0,
|
|
75827
|
+
user_name: userName,
|
|
75828
|
+
user_image: Boolean(metadata.facialEnrolled),
|
|
75829
|
+
portal_id: portalId === null ? "" : String(portalId),
|
|
75830
|
+
message: "Access granted"
|
|
75831
|
+
};
|
|
75832
|
+
if (portalId !== null) {
|
|
75833
|
+
result.actions = [{ action: "door", parameters: `door=${portalId}` }];
|
|
75834
|
+
}
|
|
75835
|
+
return { granted: true, reason: "Access granted", response: { result } };
|
|
75836
|
+
}
|
|
75837
|
+
}
|
|
75700
75838
|
return {
|
|
75701
|
-
|
|
75702
|
-
|
|
75703
|
-
|
|
75839
|
+
granted: false,
|
|
75840
|
+
reason: deniedReason,
|
|
75841
|
+
response: {
|
|
75842
|
+
result: {
|
|
75843
|
+
event: 6,
|
|
75844
|
+
user_id: toPositiveInteger(identity?.hidUserId ?? payload.user_id) ?? 0,
|
|
75845
|
+
user_name: String(metadata.name ?? payload.user_name ?? "").trim(),
|
|
75846
|
+
user_image: Boolean(metadata.facialEnrolled),
|
|
75847
|
+
portal_id: portalId === null ? "" : String(portalId),
|
|
75848
|
+
actions: [],
|
|
75849
|
+
message: deniedReason
|
|
75850
|
+
}
|
|
75851
|
+
}
|
|
75704
75852
|
};
|
|
75705
75853
|
}
|
|
75706
75854
|
function useHidAmicoService() {
|
|
@@ -75854,6 +76002,7 @@ function useHidAmicoService() {
|
|
|
75854
76002
|
reader: readerId,
|
|
75855
76003
|
...identityKeys
|
|
75856
76004
|
});
|
|
76005
|
+
const authorization = ["new_user_identified", "new_qrcode", "new_card"].includes(type) ? buildOnlineIdentificationResponse(identity, payload) : null;
|
|
75857
76006
|
const enrichedPayload = identity ? {
|
|
75858
76007
|
...payload,
|
|
75859
76008
|
identity: {
|
|
@@ -75866,20 +76015,33 @@ function useHidAmicoService() {
|
|
|
75866
76015
|
user: identity.user,
|
|
75867
76016
|
member: identity.member,
|
|
75868
76017
|
visitor: identity.visitor
|
|
75869
|
-
}
|
|
76018
|
+
},
|
|
76019
|
+
...authorization ? {
|
|
76020
|
+
authorization: {
|
|
76021
|
+
granted: authorization.granted,
|
|
76022
|
+
reason: authorization.reason
|
|
76023
|
+
}
|
|
76024
|
+
} : {}
|
|
75870
76025
|
} : {
|
|
75871
76026
|
...payload,
|
|
75872
76027
|
identity: null,
|
|
75873
|
-
identityLookup: identityKeys
|
|
76028
|
+
identityLookup: identityKeys,
|
|
76029
|
+
...authorization ? {
|
|
76030
|
+
authorization: {
|
|
76031
|
+
granted: authorization.granted,
|
|
76032
|
+
reason: authorization.reason
|
|
76033
|
+
}
|
|
76034
|
+
} : {}
|
|
75874
76035
|
};
|
|
75875
76036
|
await repo.updateById(readerId, { lastSeenAt: /* @__PURE__ */ new Date() });
|
|
75876
|
-
|
|
76037
|
+
const event = await repo.addEvent({
|
|
75877
76038
|
reader: readerId,
|
|
75878
76039
|
site: reader.site,
|
|
75879
76040
|
type,
|
|
75880
76041
|
payload: enrichedPayload,
|
|
75881
|
-
status: identity ? "processed" : "received"
|
|
76042
|
+
status: authorization ? authorization.granted ? "processed" : "failed" : identity ? "processed" : "received"
|
|
75882
76043
|
});
|
|
76044
|
+
return { event, response: authorization?.response ?? null };
|
|
75883
76045
|
}
|
|
75884
76046
|
async function listLogs(value) {
|
|
75885
76047
|
return repo.listEvents(value);
|
|
@@ -76021,6 +76183,7 @@ function useHidAmicoService() {
|
|
|
76021
76183
|
const identityPayload = {
|
|
76022
76184
|
hidUserId: String(hidUserId),
|
|
76023
76185
|
registration,
|
|
76186
|
+
cardNo: credential.qrValue,
|
|
76024
76187
|
visitor: value.visitorId,
|
|
76025
76188
|
type: "visitor",
|
|
76026
76189
|
status: "active",
|
|
@@ -76030,8 +76193,10 @@ function useHidAmicoService() {
|
|
|
76030
76193
|
qrFormat: value.qrFormat,
|
|
76031
76194
|
credentialObject: credential.object,
|
|
76032
76195
|
credentialId: credential.credentialId,
|
|
76196
|
+
qrValue: credential.qrValue,
|
|
76033
76197
|
accessRuleId: authorization.accessRuleId,
|
|
76034
76198
|
portalIds: authorization.portalIds,
|
|
76199
|
+
timeZoneId: authorization.timeZoneId,
|
|
76035
76200
|
issuedAt: issuedAt.toISOString(),
|
|
76036
76201
|
expiresAt: expiresAt.toISOString()
|
|
76037
76202
|
}
|
|
@@ -76057,6 +76222,7 @@ function useHidAmicoService() {
|
|
|
76057
76222
|
credentialObject: credential.object,
|
|
76058
76223
|
accessRuleId: authorization.accessRuleId,
|
|
76059
76224
|
portalIds: authorization.portalIds,
|
|
76225
|
+
timeZoneId: authorization.timeZoneId,
|
|
76060
76226
|
issuedAt: issuedAt.toISOString(),
|
|
76061
76227
|
expiresAt: expiresAt.toISOString()
|
|
76062
76228
|
}
|
|
@@ -76828,18 +76994,28 @@ function useHidAmicoController() {
|
|
|
76828
76994
|
}
|
|
76829
76995
|
}
|
|
76830
76996
|
async function receiveNotification(req, res, next) {
|
|
76831
|
-
const
|
|
76997
|
+
const type = String(req.params.type ?? "").replace(/\.fcgi$/i, "");
|
|
76998
|
+
const validation = schemaHidAmicoNotificationParams.validate({
|
|
76999
|
+
...req.params,
|
|
77000
|
+
type
|
|
77001
|
+
});
|
|
76832
77002
|
if (validation.error) {
|
|
76833
77003
|
next(new import_node_server_utils267.BadRequestError(validation.error.message));
|
|
76834
77004
|
return;
|
|
76835
77005
|
}
|
|
76836
77006
|
try {
|
|
76837
|
-
const
|
|
77007
|
+
const queryPayload = req.query && typeof req.query === "object" ? req.query : {};
|
|
77008
|
+
const bodyPayload = req.body && typeof req.body === "object" ? req.body : {};
|
|
77009
|
+
const notification = await service.receiveNotification(
|
|
76838
77010
|
validation.value.readerId,
|
|
76839
77011
|
validation.value.type,
|
|
76840
|
-
|
|
77012
|
+
{ ...queryPayload, ...bodyPayload }
|
|
76841
77013
|
);
|
|
76842
|
-
|
|
77014
|
+
if (notification.response) {
|
|
77015
|
+
res.status(200).json(notification.response);
|
|
77016
|
+
return;
|
|
77017
|
+
}
|
|
77018
|
+
res.status(202).json({ data: notification.event });
|
|
76843
77019
|
} catch (error) {
|
|
76844
77020
|
next(error);
|
|
76845
77021
|
}
|