98 lines
2.7 KiB
JavaScript
98 lines
2.7 KiB
JavaScript
import {
|
|
normalizeNdcCredentialReference,
|
|
} from "./credential-reference.mjs";
|
|
|
|
export const DEVICE_SENSITIVE_REFERENCE_COMMAND_KINDS = Object.freeze([
|
|
"device_credential_binding.upsert",
|
|
"device_credential_binding.revoke",
|
|
]);
|
|
|
|
const commandKindSet = new Set(DEVICE_SENSITIVE_REFERENCE_COMMAND_KINDS);
|
|
const purposePattern = /^[a-z][a-z0-9._-]{1,63}$/;
|
|
const resolutionPattern = /^[a-z][a-z0-9._-]{1,63}$/;
|
|
|
|
export function isSensitiveReferenceManagementCommand(kind) {
|
|
return commandKindSet.has(kind);
|
|
}
|
|
|
|
export function normalizeSensitiveReferenceManagementCommand(kind, input) {
|
|
if (!commandKindSet.has(kind)) {
|
|
throw new TypeError("device_sensitive_reference_command_kind_invalid");
|
|
}
|
|
assertPlainObject(input);
|
|
|
|
if (kind === "device_credential_binding.upsert") {
|
|
assertAllowedKeys(input, [
|
|
"projectRef",
|
|
"deviceRef",
|
|
"purpose",
|
|
"credentialRef",
|
|
]);
|
|
return Object.freeze({
|
|
projectId: normalizeEntityRef(input.projectRef, "project"),
|
|
deviceId: normalizeEntityRef(input.deviceRef, "device"),
|
|
purpose: normalizePattern(
|
|
input.purpose,
|
|
purposePattern,
|
|
"device_credential_purpose_invalid",
|
|
),
|
|
credentialRef: normalizeNdcCredentialReference(input.credentialRef),
|
|
});
|
|
}
|
|
|
|
assertAllowedKeys(input, [
|
|
"projectRef",
|
|
"deviceRef",
|
|
"purpose",
|
|
"resolutionCode",
|
|
]);
|
|
return Object.freeze({
|
|
projectId: normalizeEntityRef(input.projectRef, "project"),
|
|
deviceId: normalizeEntityRef(input.deviceRef, "device"),
|
|
purpose: normalizePattern(
|
|
input.purpose,
|
|
purposePattern,
|
|
"device_credential_purpose_invalid",
|
|
),
|
|
resolutionCode: normalizePattern(
|
|
input.resolutionCode,
|
|
resolutionPattern,
|
|
"device_credential_resolution_code_invalid",
|
|
),
|
|
});
|
|
}
|
|
|
|
function normalizeEntityRef(value, prefix) {
|
|
if (typeof value !== "string") {
|
|
throw new TypeError(`device_${prefix}_ref_invalid`);
|
|
}
|
|
const match = value.match(new RegExp(
|
|
`^${prefix}:([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$`,
|
|
"i",
|
|
));
|
|
if (!match) throw new TypeError(`device_${prefix}_ref_invalid`);
|
|
return match[1].toLowerCase();
|
|
}
|
|
|
|
function normalizePattern(value, pattern, code) {
|
|
if (typeof value !== "string" || !pattern.test(value)) {
|
|
throw new TypeError(code);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function assertPlainObject(value) {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
throw new TypeError("device_sensitive_reference_command_invalid");
|
|
}
|
|
}
|
|
|
|
function assertAllowedKeys(input, allowed) {
|
|
const allowedSet = new Set(allowed);
|
|
for (const key of Object.keys(input)) {
|
|
if (!allowedSet.has(key)) {
|
|
throw new TypeError(`device_management_command_field_unexpected:${key}`);
|
|
}
|
|
}
|
|
}
|