@7365admin1/core 3.48.1-staging.173 → 3.48.1-staging.174
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 +30 -2
- package/dist/index.js +181 -108
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +181 -108
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/hid-authz.test.mjs +6 -4
- package/test/org-suspension.test.mjs +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -10913,6 +10913,7 @@ declare function useHidAmicoService(): {
|
|
|
10913
10913
|
includePassword?: boolean;
|
|
10914
10914
|
}) => Promise<THidAmicoReader>;
|
|
10915
10915
|
authorizeReaderUser: (readerId: string, hidUserIdValue: string | number, userId: string) => Promise<THidAmicoReader>;
|
|
10916
|
+
authorizeVisitorForMember: (readerId: string, visitorId: string, userId: string) => Promise<THidAmicoReader>;
|
|
10916
10917
|
authorizeSiteForCaller: (siteId: string, userId: string) => Promise<{
|
|
10917
10918
|
site: mongodb.WithId<bson.Document> | null;
|
|
10918
10919
|
siteObjectId: bson.ObjectId;
|
|
@@ -10936,6 +10937,23 @@ declare function useHidAmicoService(): {
|
|
|
10936
10937
|
pages: number;
|
|
10937
10938
|
pageRange: string;
|
|
10938
10939
|
}>;
|
|
10940
|
+
getMemberReaderInfo: (readerId: string, userId: string) => Promise<{
|
|
10941
|
+
_id: string;
|
|
10942
|
+
name: string;
|
|
10943
|
+
location: string | undefined;
|
|
10944
|
+
status: "deleted" | "active" | "inactive" | "offline" | undefined;
|
|
10945
|
+
portalId: number | undefined;
|
|
10946
|
+
portalName: string | undefined;
|
|
10947
|
+
readerModel: "unknown" | "VL35LF" | "VL70LF" | undefined;
|
|
10948
|
+
cardReadingMode: "unconfigured" | "pacs" | "csn" | "csn_for_mifare" | undefined;
|
|
10949
|
+
capabilities: {
|
|
10950
|
+
card: boolean;
|
|
10951
|
+
facial: boolean;
|
|
10952
|
+
qr: boolean;
|
|
10953
|
+
pin: boolean;
|
|
10954
|
+
intercom: boolean;
|
|
10955
|
+
};
|
|
10956
|
+
}>;
|
|
10939
10957
|
discoverReader: (value: Pick<THidAmicoReader, "baseUrl" | "username" | "password"> & Partial<Pick<THidAmicoReader, "readerModel">>) => Promise<{
|
|
10940
10958
|
deviceId: string;
|
|
10941
10959
|
serial: string;
|
|
@@ -11084,7 +11102,7 @@ declare function useHidAmicoService(): {
|
|
|
11084
11102
|
pages: number;
|
|
11085
11103
|
pageRange: string;
|
|
11086
11104
|
}>;
|
|
11087
|
-
listReaderUsers: (readerId: string, page?: number, limit?: number, search?: string, status?: "mapped" | "unmapped" | "", includeVisitors?: boolean) => Promise<{
|
|
11105
|
+
listReaderUsers: (readerId: string, page?: number, limit?: number, search?: string, status?: "mapped" | "unmapped" | "", includeVisitors?: boolean, userType?: "all" | "user" | "visitor") => Promise<{
|
|
11088
11106
|
items: {
|
|
11089
11107
|
reader: string;
|
|
11090
11108
|
hidUserId: string;
|
|
@@ -11096,7 +11114,6 @@ declare function useHidAmicoService(): {
|
|
|
11096
11114
|
facialEnrolled: boolean;
|
|
11097
11115
|
};
|
|
11098
11116
|
isAdministrator: boolean;
|
|
11099
|
-
_id?: bson.ObjectId | undefined;
|
|
11100
11117
|
}[];
|
|
11101
11118
|
page: number;
|
|
11102
11119
|
limit: number;
|
|
@@ -11153,6 +11170,15 @@ declare function useHidAmicoService(): {
|
|
|
11153
11170
|
validFrom: string;
|
|
11154
11171
|
expiresAt: string;
|
|
11155
11172
|
}>;
|
|
11173
|
+
getVisitorQrForMember: (readerId: string, visitorId: string, userId: string) => Promise<{
|
|
11174
|
+
readerId: string;
|
|
11175
|
+
visitorId: string;
|
|
11176
|
+
qrValue: string;
|
|
11177
|
+
expiresAt: string;
|
|
11178
|
+
portalId: number | undefined;
|
|
11179
|
+
portalName: string | undefined;
|
|
11180
|
+
readerName: string;
|
|
11181
|
+
} | null>;
|
|
11156
11182
|
revokeVisitorQr: (readerId: string, visitorId: string) => Promise<{
|
|
11157
11183
|
readerId: string;
|
|
11158
11184
|
visitorId: string;
|
|
@@ -11365,6 +11391,7 @@ declare function useHidAmicoController(): {
|
|
|
11365
11391
|
authorizeManage: (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
11366
11392
|
authorizeVisitor: (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
11367
11393
|
listReaders: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11394
|
+
getMemberReaderInfo: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11368
11395
|
discoverReader: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11369
11396
|
createReader: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11370
11397
|
updateReader: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -11400,6 +11427,7 @@ declare function useHidAmicoController(): {
|
|
|
11400
11427
|
setConfiguration: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11401
11428
|
runObjectOperation: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11402
11429
|
issueVisitorQr: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11430
|
+
getVisitorQr: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11403
11431
|
revokeVisitorQr: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11404
11432
|
getProfileFacial: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
11405
11433
|
setProfileFacial: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -43262,7 +43262,7 @@ var schemaHidAmicoIdentity = import_joi64.default.object({
|
|
|
43262
43262
|
var schemaCreateHidAmicoIdentity = import_joi64.default.object({
|
|
43263
43263
|
site: objectIdSchema2.optional(),
|
|
43264
43264
|
hidUserId: import_joi64.default.alternatives(import_joi64.default.string(), import_joi64.default.number()).optional().allow(null, ""),
|
|
43265
|
-
registration: import_joi64.default.string().trim().
|
|
43265
|
+
registration: import_joi64.default.string().trim().optional().allow(""),
|
|
43266
43266
|
cardNo: import_joi64.default.string().optional().allow(null, ""),
|
|
43267
43267
|
person: objectIdSchema2.optional().allow(null, ""),
|
|
43268
43268
|
user: objectIdSchema2.optional().allow(null, ""),
|
|
@@ -43409,7 +43409,8 @@ var schemaHidAmicoReaderUserQuery = import_joi64.default.object({
|
|
|
43409
43409
|
limit: import_joi64.default.number().integer().min(1).max(100).default(10),
|
|
43410
43410
|
search: import_joi64.default.string().trim().max(100).allow("").default(""),
|
|
43411
43411
|
status: import_joi64.default.string().valid("mapped", "unmapped").allow("").default(""),
|
|
43412
|
-
includeVisitors: import_joi64.default.boolean().default(false)
|
|
43412
|
+
includeVisitors: import_joi64.default.boolean().default(false),
|
|
43413
|
+
userType: import_joi64.default.string().valid("all", "user", "visitor").default("all")
|
|
43413
43414
|
});
|
|
43414
43415
|
var schemaHidAmicoAccessLogQuery = import_joi64.default.object({
|
|
43415
43416
|
page: import_joi64.default.number().integer().min(1).default(1),
|
|
@@ -44928,18 +44929,34 @@ function getSecretKey() {
|
|
|
44928
44929
|
return import_crypto2.default.createHash("sha256").update(secret).digest();
|
|
44929
44930
|
}
|
|
44930
44931
|
function getReaderCapabilities(readerModel, firmwareVersion) {
|
|
44932
|
+
const isAmicoBiometricReader2 = readerModel === "VL35LF" || readerModel === "VL70LF";
|
|
44931
44933
|
return {
|
|
44932
|
-
|
|
44934
|
+
// VL35LF/VL70LF expose the relevant credential functions even when the
|
|
44935
|
+
// installed product firmware reports a 2.x version rather than the legacy
|
|
44936
|
+
// API version scheme.
|
|
44937
|
+
card: isAmicoBiometricReader2 || hidFirmwareAtLeast(firmwareVersion, "6.5.1"),
|
|
44933
44938
|
// VL35LF and VL70LF are biometric readers. Some deployed readers report
|
|
44934
44939
|
// their device firmware as 2.x even though their face API is available.
|
|
44935
|
-
facial:
|
|
44936
|
-
qr: hidFirmwareAtLeast(firmwareVersion, "6.5.1"),
|
|
44937
|
-
pin: hidFirmwareAtLeast(firmwareVersion, "6.9.0"),
|
|
44940
|
+
facial: isAmicoBiometricReader2,
|
|
44941
|
+
qr: isAmicoBiometricReader2 || hidFirmwareAtLeast(firmwareVersion, "6.5.1"),
|
|
44942
|
+
pin: isAmicoBiometricReader2 || hidFirmwareAtLeast(firmwareVersion, "6.9.0"),
|
|
44938
44943
|
intercom: readerModel === "VL70LF"
|
|
44939
44944
|
};
|
|
44940
44945
|
}
|
|
44946
|
+
function isAmicoBiometricReader(reader) {
|
|
44947
|
+
return reader.readerModel === "VL35LF" || reader.readerModel === "VL70LF";
|
|
44948
|
+
}
|
|
44941
44949
|
function readerSupportsFacial(reader) {
|
|
44942
|
-
return reader.capabilities?.facial === true || reader
|
|
44950
|
+
return reader.capabilities?.facial === true || isAmicoBiometricReader(reader);
|
|
44951
|
+
}
|
|
44952
|
+
function readerSupportsCredential(reader, capability) {
|
|
44953
|
+
if (reader.capabilities?.[capability] === true)
|
|
44954
|
+
return true;
|
|
44955
|
+
if (capability === "facial")
|
|
44956
|
+
return readerSupportsFacial(reader);
|
|
44957
|
+
if (capability === "intercom")
|
|
44958
|
+
return reader.readerModel === "VL70LF";
|
|
44959
|
+
return isAmicoBiometricReader(reader);
|
|
44943
44960
|
}
|
|
44944
44961
|
function getMonitorConfiguration(callbackToken) {
|
|
44945
44962
|
const configured = String(process.env.HID_AMICO_MONITOR_URL || "").trim();
|
|
@@ -45095,14 +45112,25 @@ function createVisitorQrCredential(visitorId, readerId) {
|
|
|
45095
45112
|
}
|
|
45096
45113
|
async function configureVisitorQrReader(client) {
|
|
45097
45114
|
const requestedConfiguration = {
|
|
45115
|
+
general: ["online", "local_identification"],
|
|
45098
45116
|
face_id: ["qrcode_legacy_mode_enabled"],
|
|
45099
45117
|
identifier: ["qrcode_identification_enabled", "multi_factor_authentication"]
|
|
45100
45118
|
};
|
|
45101
45119
|
const currentConfiguration = await client.getConfiguration(requestedConfiguration);
|
|
45102
45120
|
const current = isUnknownRecord2(currentConfiguration) ? currentConfiguration : {};
|
|
45121
|
+
const currentGeneral = isUnknownRecord2(current.general) ? current.general : {};
|
|
45103
45122
|
const currentFaceId = isUnknownRecord2(current.face_id) ? current.face_id : {};
|
|
45104
45123
|
const currentIdentifier = isUnknownRecord2(current.identifier) ? current.identifier : {};
|
|
45105
45124
|
let changed = false;
|
|
45125
|
+
if (String(currentGeneral.online ?? "") !== "0" || String(currentGeneral.local_identification ?? "") !== "1") {
|
|
45126
|
+
await client.setConfiguration({
|
|
45127
|
+
general: {
|
|
45128
|
+
online: "0",
|
|
45129
|
+
local_identification: "1"
|
|
45130
|
+
}
|
|
45131
|
+
});
|
|
45132
|
+
changed = true;
|
|
45133
|
+
}
|
|
45106
45134
|
if (String(currentFaceId.qrcode_legacy_mode_enabled ?? "") !== VISITOR_QR_FORMAT) {
|
|
45107
45135
|
await client.setConfiguration({
|
|
45108
45136
|
face_id: { qrcode_legacy_mode_enabled: VISITOR_QR_FORMAT }
|
|
@@ -45122,9 +45150,10 @@ async function configureVisitorQrReader(client) {
|
|
|
45122
45150
|
}
|
|
45123
45151
|
const configuration = await client.getConfiguration(requestedConfiguration);
|
|
45124
45152
|
const savedConfiguration = isUnknownRecord2(configuration) ? configuration : {};
|
|
45153
|
+
const general = isUnknownRecord2(savedConfiguration.general) ? savedConfiguration.general : {};
|
|
45125
45154
|
const faceId = isUnknownRecord2(savedConfiguration.face_id) ? savedConfiguration.face_id : {};
|
|
45126
45155
|
const identifier = isUnknownRecord2(savedConfiguration.identifier) ? savedConfiguration.identifier : {};
|
|
45127
|
-
if (String(faceId.qrcode_legacy_mode_enabled ?? "") !== VISITOR_QR_FORMAT || String(identifier.qrcode_identification_enabled ?? "") !== "1" || String(identifier.multi_factor_authentication ?? "") !== "0") {
|
|
45156
|
+
if (String(general.online ?? "") !== "0" || String(general.local_identification ?? "") !== "1" || String(faceId.qrcode_legacy_mode_enabled ?? "") !== VISITOR_QR_FORMAT || String(identifier.qrcode_identification_enabled ?? "") !== "1" || String(identifier.multi_factor_authentication ?? "") !== "0") {
|
|
45128
45157
|
throw new import_node_server_utils132.BadRequestError(
|
|
45129
45158
|
"The HID reader did not retain alphanumeric QR configuration."
|
|
45130
45159
|
);
|
|
@@ -46357,6 +46386,17 @@ function useHidAmicoService() {
|
|
|
46357
46386
|
return reader;
|
|
46358
46387
|
return authorizeReader(readerId, userId);
|
|
46359
46388
|
}
|
|
46389
|
+
async function authorizeVisitorForMember(readerId, visitorId, userId) {
|
|
46390
|
+
const reader = await entitleReaderForSelf(readerId, userId);
|
|
46391
|
+
const visitor = await visitorRepo.getVisitorTransactionById(visitorId);
|
|
46392
|
+
const visitorSiteId = String(visitor?.site?._id || visitor?.site || "");
|
|
46393
|
+
if (!visitorSiteId || visitorSiteId !== String(reader.site || "")) {
|
|
46394
|
+
throw new import_node_server_utils132.BadRequestError("Visitor and HID reader must belong to the same site.");
|
|
46395
|
+
}
|
|
46396
|
+
if (String(visitor?.createdBy || "") === userId)
|
|
46397
|
+
return reader;
|
|
46398
|
+
return authorizeReader(readerId, userId);
|
|
46399
|
+
}
|
|
46360
46400
|
async function getActiveReader(id) {
|
|
46361
46401
|
const reader = await repo.getById(id, { includePassword: true });
|
|
46362
46402
|
if (reader.enabled === false || reader.status === "inactive" || reader.status === "deleted") {
|
|
@@ -46365,7 +46405,7 @@ function useHidAmicoService() {
|
|
|
46365
46405
|
return reader;
|
|
46366
46406
|
}
|
|
46367
46407
|
function assertReaderCapability(reader, capability) {
|
|
46368
|
-
if (reader
|
|
46408
|
+
if (readerSupportsCredential(reader, capability)) {
|
|
46369
46409
|
return;
|
|
46370
46410
|
}
|
|
46371
46411
|
const requirement = capability === "pin" ? "firmware 6.9.0 or newer" : capability === "intercom" ? "a VL70LF reader" : "firmware 6.5.1 or newer";
|
|
@@ -46809,6 +46849,26 @@ function useHidAmicoService() {
|
|
|
46809
46849
|
async function listReaders(value) {
|
|
46810
46850
|
return repo.list(value);
|
|
46811
46851
|
}
|
|
46852
|
+
async function getMemberReaderInfo(readerId, userId) {
|
|
46853
|
+
const reader = await entitleReaderForSelf(readerId, userId);
|
|
46854
|
+
return {
|
|
46855
|
+
_id: String(reader._id),
|
|
46856
|
+
name: reader.name,
|
|
46857
|
+
location: reader.location,
|
|
46858
|
+
status: reader.status,
|
|
46859
|
+
portalId: reader.portalId,
|
|
46860
|
+
portalName: reader.portalName,
|
|
46861
|
+
readerModel: reader.readerModel,
|
|
46862
|
+
cardReadingMode: reader.cardReadingMode,
|
|
46863
|
+
capabilities: {
|
|
46864
|
+
card: readerSupportsCredential(reader, "card"),
|
|
46865
|
+
facial: readerSupportsFacial(reader),
|
|
46866
|
+
qr: readerSupportsCredential(reader, "qr"),
|
|
46867
|
+
pin: readerSupportsCredential(reader, "pin"),
|
|
46868
|
+
intercom: readerSupportsCredential(reader, "intercom")
|
|
46869
|
+
}
|
|
46870
|
+
};
|
|
46871
|
+
}
|
|
46812
46872
|
async function deleteReader(id) {
|
|
46813
46873
|
return repo.markDeleted(id);
|
|
46814
46874
|
}
|
|
@@ -46983,7 +47043,7 @@ function useHidAmicoService() {
|
|
|
46983
47043
|
async function listIdentities(value) {
|
|
46984
47044
|
return repo.listIdentities(value);
|
|
46985
47045
|
}
|
|
46986
|
-
async function listReaderUsers(readerId, page = 1, limit = 10, search = "", status = "", includeVisitors = false) {
|
|
47046
|
+
async function listReaderUsers(readerId, page = 1, limit = 10, search = "", status = "", includeVisitors = false, userType = "all") {
|
|
46987
47047
|
const reader = await getActiveReader(readerId);
|
|
46988
47048
|
const offset = (page - 1) * limit;
|
|
46989
47049
|
const client = new HidAmicoClient(reader);
|
|
@@ -47000,54 +47060,22 @@ function useHidAmicoService() {
|
|
|
47000
47060
|
let rows = [];
|
|
47001
47061
|
let reportedTotal = null;
|
|
47002
47062
|
let hasMore = false;
|
|
47003
|
-
|
|
47004
|
-
|
|
47005
|
-
|
|
47006
|
-
|
|
47007
|
-
|
|
47008
|
-
|
|
47009
|
-
|
|
47010
|
-
|
|
47011
|
-
|
|
47012
|
-
|
|
47013
|
-
|
|
47014
|
-
|
|
47015
|
-
|
|
47016
|
-
|
|
47017
|
-
|
|
47018
|
-
|
|
47019
|
-
);
|
|
47020
|
-
const matchedRows = [];
|
|
47021
|
-
const targetCount = offset + limit + 1;
|
|
47022
|
-
let deviceOffset = 0;
|
|
47023
|
-
let exhausted = status === "mapped" && mappedUserIds.size === 0;
|
|
47024
|
-
const chunkSize = 100;
|
|
47025
|
-
while (!exhausted && matchedRows.length < targetCount) {
|
|
47026
|
-
const response = await client.loadObjects({
|
|
47027
|
-
object: "users",
|
|
47028
|
-
where: { users: userWhere },
|
|
47029
|
-
limit: chunkSize,
|
|
47030
|
-
offset: deviceOffset,
|
|
47031
|
-
order: ["id", "ascending"]
|
|
47032
|
-
});
|
|
47033
|
-
const batch = getHidObjectRows(response, "users");
|
|
47034
|
-
batch.forEach((row) => {
|
|
47035
|
-
if (!includeVisitors && Number(row.user_type_id) === 1)
|
|
47036
|
-
return;
|
|
47037
|
-
const mapped = mappedUserIds.has(String(row.id ?? ""));
|
|
47038
|
-
if (status === "mapped" && mapped || status === "unmapped" && !mapped) {
|
|
47039
|
-
matchedRows.push(row);
|
|
47040
|
-
}
|
|
47041
|
-
});
|
|
47042
|
-
deviceOffset += batch.length;
|
|
47043
|
-
exhausted = batch.length < chunkSize;
|
|
47044
|
-
}
|
|
47045
|
-
rows = matchedRows.slice(offset, offset + limit);
|
|
47046
|
-
hasMore = matchedRows.length > offset + limit || !exhausted;
|
|
47047
|
-
}
|
|
47048
|
-
const userIds = rows.map((row) => String(row.id ?? "")).filter(Boolean);
|
|
47049
|
-
const [identities, administratorFlags, facialUserIds] = await Promise.all([
|
|
47050
|
-
repo.findIdentitiesByHidUserIds(readerId, userIds),
|
|
47063
|
+
const response = await client.loadObjects({
|
|
47064
|
+
object: "users",
|
|
47065
|
+
where: { users: userWhere },
|
|
47066
|
+
limit: 500,
|
|
47067
|
+
offset: 0,
|
|
47068
|
+
order: ["id", "ascending"]
|
|
47069
|
+
});
|
|
47070
|
+
const deviceRows = getHidObjectRows(response, "users");
|
|
47071
|
+
const filteredRows = deviceRows.filter((row) => {
|
|
47072
|
+
const isVisitor = Number(row.user_type_id) === 1;
|
|
47073
|
+
return userType === "visitor" ? isVisitor : userType === "user" ? !isVisitor : true;
|
|
47074
|
+
});
|
|
47075
|
+
reportedTotal = filteredRows.length;
|
|
47076
|
+
rows = filteredRows.slice(offset, offset + limit);
|
|
47077
|
+
hasMore = offset + rows.length < filteredRows.length;
|
|
47078
|
+
const [administratorFlags, facialUserIds] = await Promise.all([
|
|
47051
47079
|
Promise.all(rows.map(async (row) => {
|
|
47052
47080
|
const userId = Number(row.id);
|
|
47053
47081
|
if (!Number.isSafeInteger(userId) || userId <= 0)
|
|
@@ -47062,24 +47090,17 @@ function useHidAmicoService() {
|
|
|
47062
47090
|
})),
|
|
47063
47091
|
readerSupportsFacial(reader) ? client.listUserImageIds().catch(() => []) : Promise.resolve([])
|
|
47064
47092
|
]);
|
|
47065
|
-
const identityMap = new Map(
|
|
47066
|
-
identities.map((identity) => [String(identity.hidUserId), identity])
|
|
47067
|
-
);
|
|
47068
47093
|
const facialUserIdSet = new Set(facialUserIds.map(String));
|
|
47069
47094
|
const items = rows.map((row, index) => {
|
|
47070
|
-
const
|
|
47071
|
-
const identityMetadata = identity && isUnknownRecord2(identity.metadata) ? identity.metadata : {};
|
|
47072
|
-
const facialEnrolled = facialUserIdSet.has(String(row.id ?? "")) || identityMetadata.facialEnrolled === true;
|
|
47095
|
+
const facialEnrolled = facialUserIdSet.has(String(row.id ?? ""));
|
|
47073
47096
|
return {
|
|
47074
47097
|
...row,
|
|
47075
|
-
...identity || {},
|
|
47076
47098
|
reader: readerId,
|
|
47077
|
-
hidUserId: String(row.id ??
|
|
47078
|
-
registration: String(row.registration ??
|
|
47099
|
+
hidUserId: String(row.id ?? ""),
|
|
47100
|
+
registration: String(row.registration ?? ""),
|
|
47079
47101
|
metadata: {
|
|
47080
|
-
|
|
47081
|
-
|
|
47082
|
-
hidUserTypeId: row.user_type_id ?? identityMetadata.hidUserTypeId,
|
|
47102
|
+
name: String(row.name ?? ""),
|
|
47103
|
+
hidUserTypeId: row.user_type_id,
|
|
47083
47104
|
facialEnrolled,
|
|
47084
47105
|
...facialEnrolled ? { facialData: String(row.id ?? "") } : {}
|
|
47085
47106
|
},
|
|
@@ -47404,6 +47425,7 @@ function useHidAmicoService() {
|
|
|
47404
47425
|
site: reader.site,
|
|
47405
47426
|
type: "visitor_qr_reader_configured",
|
|
47406
47427
|
payload: {
|
|
47428
|
+
operatingMode: "standalone",
|
|
47407
47429
|
qrFormat: VISITOR_QR_FORMAT,
|
|
47408
47430
|
qrcodeIdentificationEnabled: "1",
|
|
47409
47431
|
multiFactorAuthentication: "0"
|
|
@@ -47550,7 +47572,11 @@ function useHidAmicoService() {
|
|
|
47550
47572
|
site: reader.site
|
|
47551
47573
|
});
|
|
47552
47574
|
}
|
|
47553
|
-
await repo.updateById(readerId, {
|
|
47575
|
+
await repo.updateById(readerId, {
|
|
47576
|
+
status: "active",
|
|
47577
|
+
lastSeenAt: /* @__PURE__ */ new Date(),
|
|
47578
|
+
operatingMode: "standalone"
|
|
47579
|
+
});
|
|
47554
47580
|
await repo.addEvent({
|
|
47555
47581
|
reader: readerId,
|
|
47556
47582
|
site: reader.site,
|
|
@@ -47593,6 +47619,32 @@ function useHidAmicoService() {
|
|
|
47593
47619
|
await client.logout();
|
|
47594
47620
|
}
|
|
47595
47621
|
}
|
|
47622
|
+
async function getVisitorQrForMember(readerId, visitorId, userId) {
|
|
47623
|
+
const reader = await authorizeVisitorForMember(readerId, visitorId, userId);
|
|
47624
|
+
const result = await repo.listIdentities({
|
|
47625
|
+
reader: readerId,
|
|
47626
|
+
type: "visitor",
|
|
47627
|
+
status: "active",
|
|
47628
|
+
page: 1,
|
|
47629
|
+
limit: 500
|
|
47630
|
+
});
|
|
47631
|
+
const identities = Array.isArray(result.items) ? result.items : [];
|
|
47632
|
+
const identity = identities.find((item) => String(item.visitor || "") === visitorId);
|
|
47633
|
+
const metadata = identity && isUnknownRecord2(identity.metadata) ? identity.metadata : {};
|
|
47634
|
+
const qrValue = String(metadata.qrValue || identity?.cardNo || "").trim();
|
|
47635
|
+
const expiresAt = String(metadata.expiresAt || "").trim();
|
|
47636
|
+
if (!qrValue || !expiresAt)
|
|
47637
|
+
return null;
|
|
47638
|
+
return {
|
|
47639
|
+
readerId,
|
|
47640
|
+
visitorId,
|
|
47641
|
+
qrValue,
|
|
47642
|
+
expiresAt,
|
|
47643
|
+
portalId: reader.portalId,
|
|
47644
|
+
portalName: reader.portalName,
|
|
47645
|
+
readerName: reader.name
|
|
47646
|
+
};
|
|
47647
|
+
}
|
|
47596
47648
|
async function getProfileFacial(readerId, userId) {
|
|
47597
47649
|
const reader = await getActiveReader(readerId);
|
|
47598
47650
|
const context = await getProfileEnrollmentContext(readerId, reader, userId);
|
|
@@ -47759,47 +47811,25 @@ function useHidAmicoService() {
|
|
|
47759
47811
|
try {
|
|
47760
47812
|
await client.login();
|
|
47761
47813
|
const facialUserIds = await getReaderFacialUserIds(client);
|
|
47762
|
-
const
|
|
47763
|
-
const identitiesByUserId = new Map(
|
|
47764
|
-
activeIdentities.filter((identity) => identity._id && identity.hidUserId !== void 0).map((identity) => [String(identity.hidUserId), identity])
|
|
47765
|
-
);
|
|
47766
|
-
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
47767
|
-
let syncedCount = 0;
|
|
47768
|
-
let unmappedCount = 0;
|
|
47769
|
-
for (const hidUserId of facialUserIds) {
|
|
47770
|
-
const identity = identitiesByUserId.get(String(hidUserId));
|
|
47771
|
-
if (!identity?._id) {
|
|
47772
|
-
unmappedCount += 1;
|
|
47773
|
-
continue;
|
|
47774
|
-
}
|
|
47775
|
-
const metadata = isUnknownRecord2(identity.metadata) ? identity.metadata : {};
|
|
47776
|
-
await repo.updateIdentity(identity._id, {
|
|
47777
|
-
metadata: {
|
|
47778
|
-
...metadata,
|
|
47779
|
-
facialData: String(hidUserId),
|
|
47780
|
-
facialEnrolled: true,
|
|
47781
|
-
facialSyncedAt: syncedAt
|
|
47782
|
-
}
|
|
47783
|
-
});
|
|
47784
|
-
syncedCount += 1;
|
|
47785
|
-
}
|
|
47786
|
-
const message = [
|
|
47787
|
-
facialUserIds.length ? `Detected ${facialUserIds.length} facial enrollment(s) on the HID reader.` : "No facial enrollments found on the HID reader.",
|
|
47788
|
-
syncedCount ? `${syncedCount} mapped HID user(s) updated.` : "",
|
|
47789
|
-
unmappedCount ? `${unmappedCount} facial enrollment(s) still need HID User Mapping.` : ""
|
|
47790
|
-
].filter(Boolean).join(" ");
|
|
47814
|
+
const message = facialUserIds.length ? `Found ${facialUserIds.length} Amico user(s) with facial data. Facial status and images are read directly from the reader.` : "No facial enrollments found on the HID reader.";
|
|
47791
47815
|
await repo.updateById(readerId, { status: "active", lastSeenAt: /* @__PURE__ */ new Date() });
|
|
47792
47816
|
await repo.addEvent({
|
|
47793
47817
|
reader: readerId,
|
|
47794
47818
|
site: reader.site,
|
|
47795
47819
|
type: "facial_sync",
|
|
47796
|
-
payload: {
|
|
47820
|
+
payload: {
|
|
47821
|
+
facialDetected: facialUserIds.length,
|
|
47822
|
+
source: "amico",
|
|
47823
|
+
hidUserIds: facialUserIds
|
|
47824
|
+
}
|
|
47797
47825
|
});
|
|
47798
47826
|
return {
|
|
47799
47827
|
readerId,
|
|
47800
47828
|
facialDetected: facialUserIds.length,
|
|
47801
|
-
|
|
47802
|
-
|
|
47829
|
+
// Retain these response fields for existing clients. A direct refresh
|
|
47830
|
+
// has no unmapped records and does not write a second iService copy.
|
|
47831
|
+
syncedCount: facialUserIds.length,
|
|
47832
|
+
unmappedCount: 0,
|
|
47803
47833
|
message
|
|
47804
47834
|
};
|
|
47805
47835
|
} catch (error) {
|
|
@@ -47976,7 +48006,7 @@ function useHidAmicoService() {
|
|
|
47976
48006
|
async function listUserCards(readerId, hidUserIdValue) {
|
|
47977
48007
|
const reader = await getActiveReader(readerId);
|
|
47978
48008
|
assertReaderCapability(reader, "card");
|
|
47979
|
-
const cardType =
|
|
48009
|
+
const cardType = reader.cardReadingMode === "pacs" || reader.cardReadingMode === "csn" ? reader.cardReadingMode : "unknown";
|
|
47980
48010
|
const hidUserId = Number(hidUserIdValue);
|
|
47981
48011
|
const client = new HidAmicoClient(reader);
|
|
47982
48012
|
try {
|
|
@@ -48936,9 +48966,11 @@ function useHidAmicoService() {
|
|
|
48936
48966
|
return {
|
|
48937
48967
|
authorizeReader,
|
|
48938
48968
|
authorizeReaderUser,
|
|
48969
|
+
authorizeVisitorForMember,
|
|
48939
48970
|
authorizeSiteForCaller,
|
|
48940
48971
|
authorizeHidAccess,
|
|
48941
48972
|
listReaders,
|
|
48973
|
+
getMemberReaderInfo,
|
|
48942
48974
|
discoverReader,
|
|
48943
48975
|
createReader,
|
|
48944
48976
|
updateReader,
|
|
@@ -48958,6 +48990,7 @@ function useHidAmicoService() {
|
|
|
48958
48990
|
deleteIdentity,
|
|
48959
48991
|
runObjectOperation,
|
|
48960
48992
|
issueVisitorQr,
|
|
48993
|
+
getVisitorQrForMember,
|
|
48961
48994
|
revokeVisitorQr,
|
|
48962
48995
|
queueVisitorQrJob,
|
|
48963
48996
|
processVisitorQrGatewayJobs,
|
|
@@ -85966,6 +85999,20 @@ function useHidAmicoController() {
|
|
|
85966
85999
|
next(error2);
|
|
85967
86000
|
}
|
|
85968
86001
|
}
|
|
86002
|
+
async function getMemberReaderInfo(req, res, next) {
|
|
86003
|
+
const { error, value } = schemaHidAmicoReaderIdParams.validate(req.params);
|
|
86004
|
+
if (error) {
|
|
86005
|
+
next(new import_node_server_utils294.BadRequestError(error.message));
|
|
86006
|
+
return;
|
|
86007
|
+
}
|
|
86008
|
+
try {
|
|
86009
|
+
res.json({
|
|
86010
|
+
data: await service.getMemberReaderInfo(value.readerId, getAuthenticatedUserId(req))
|
|
86011
|
+
});
|
|
86012
|
+
} catch (requestError) {
|
|
86013
|
+
next(requestError);
|
|
86014
|
+
}
|
|
86015
|
+
}
|
|
85969
86016
|
async function createReader(req, res, next) {
|
|
85970
86017
|
const { error, value } = schemaHidAmicoReader.validate(req.body);
|
|
85971
86018
|
if (error) {
|
|
@@ -86153,7 +86200,8 @@ function useHidAmicoController() {
|
|
|
86153
86200
|
query2.value.limit,
|
|
86154
86201
|
query2.value.search,
|
|
86155
86202
|
query2.value.status,
|
|
86156
|
-
query2.value.includeVisitors
|
|
86203
|
+
query2.value.includeVisitors,
|
|
86204
|
+
query2.value.userType
|
|
86157
86205
|
));
|
|
86158
86206
|
} catch (error) {
|
|
86159
86207
|
next(error);
|
|
@@ -86359,6 +86407,11 @@ function useHidAmicoController() {
|
|
|
86359
86407
|
return;
|
|
86360
86408
|
}
|
|
86361
86409
|
try {
|
|
86410
|
+
await service.authorizeVisitorForMember(
|
|
86411
|
+
params.value.readerId,
|
|
86412
|
+
body.value.visitorId,
|
|
86413
|
+
getAuthenticatedUserId(req)
|
|
86414
|
+
);
|
|
86362
86415
|
res.status(201).json({
|
|
86363
86416
|
data: await service.issueVisitorQr(params.value.readerId, body.value)
|
|
86364
86417
|
});
|
|
@@ -86366,6 +86419,24 @@ function useHidAmicoController() {
|
|
|
86366
86419
|
next(error);
|
|
86367
86420
|
}
|
|
86368
86421
|
}
|
|
86422
|
+
async function getVisitorQr(req, res, next) {
|
|
86423
|
+
const { error, value } = schemaHidAmicoVisitorImageParams.validate(req.params);
|
|
86424
|
+
if (error) {
|
|
86425
|
+
next(new import_node_server_utils294.BadRequestError(error.message));
|
|
86426
|
+
return;
|
|
86427
|
+
}
|
|
86428
|
+
try {
|
|
86429
|
+
res.json({
|
|
86430
|
+
data: await service.getVisitorQrForMember(
|
|
86431
|
+
value.readerId,
|
|
86432
|
+
value.visitorId,
|
|
86433
|
+
getAuthenticatedUserId(req)
|
|
86434
|
+
)
|
|
86435
|
+
});
|
|
86436
|
+
} catch (requestError) {
|
|
86437
|
+
next(requestError);
|
|
86438
|
+
}
|
|
86439
|
+
}
|
|
86369
86440
|
async function discoverReader(req, res, next) {
|
|
86370
86441
|
const { error, value } = schemaDiscoverHidAmicoReader.validate(req.body);
|
|
86371
86442
|
if (error) {
|
|
@@ -86399,7 +86470,7 @@ function useHidAmicoController() {
|
|
|
86399
86470
|
return;
|
|
86400
86471
|
}
|
|
86401
86472
|
try {
|
|
86402
|
-
await
|
|
86473
|
+
await authorizeReaderUser(req, value.readerId, value.hidUserId);
|
|
86403
86474
|
res.json({ data: await service.listUserCards(value.readerId, value.hidUserId) });
|
|
86404
86475
|
} catch (requestError) {
|
|
86405
86476
|
next(requestError);
|
|
@@ -86433,7 +86504,7 @@ function useHidAmicoController() {
|
|
|
86433
86504
|
return;
|
|
86434
86505
|
}
|
|
86435
86506
|
try {
|
|
86436
|
-
await
|
|
86507
|
+
await authorizeReaderUser(req, params.value.readerId, params.value.hidUserId);
|
|
86437
86508
|
res.status(201).json({
|
|
86438
86509
|
data: await service.enrollUserCard(
|
|
86439
86510
|
params.value.readerId,
|
|
@@ -86466,7 +86537,7 @@ function useHidAmicoController() {
|
|
|
86466
86537
|
return;
|
|
86467
86538
|
}
|
|
86468
86539
|
try {
|
|
86469
|
-
await
|
|
86540
|
+
await authorizeReaderUser(req, value.readerId, value.hidUserId);
|
|
86470
86541
|
res.json({
|
|
86471
86542
|
data: await service.deleteUserCard(
|
|
86472
86543
|
value.readerId,
|
|
@@ -86725,6 +86796,7 @@ function useHidAmicoController() {
|
|
|
86725
86796
|
authorizeManage,
|
|
86726
86797
|
authorizeVisitor,
|
|
86727
86798
|
listReaders,
|
|
86799
|
+
getMemberReaderInfo,
|
|
86728
86800
|
discoverReader,
|
|
86729
86801
|
createReader,
|
|
86730
86802
|
updateReader,
|
|
@@ -86760,6 +86832,7 @@ function useHidAmicoController() {
|
|
|
86760
86832
|
setConfiguration,
|
|
86761
86833
|
runObjectOperation,
|
|
86762
86834
|
issueVisitorQr,
|
|
86835
|
+
getVisitorQr,
|
|
86763
86836
|
revokeVisitorQr,
|
|
86764
86837
|
getProfileFacial,
|
|
86765
86838
|
setProfileFacial,
|