1"use strict"; 2var __importDefault = (this && this.__importDefault) || function (mod) { 3 return (mod && mod.__esModule) ? mod : { "default": mod }; 4}; 5Object.defineProperty(exports, "__esModule", { value: true }); 6exports.Root = void 0; 7const util_1 = __importDefault(require("util")); 8const base_1 = require("./base"); 9const error_1 = require("./error"); 10const key_1 = require("./key"); 11const role_1 = require("./role"); 12const utils_1 = require("./utils"); 13/** 14 * A container for the signed part of root metadata. 15 * 16 * The top-level role and metadata file signed by the root keys. 17 * This role specifies trusted keys for all other top-level roles, which may further delegate trust. 18 */ 19class Root extends base_1.Signed { 20 constructor(options) { 21 super(options); 22 this.type = base_1.MetadataKind.Root; 23 this.keys = options.keys || {}; 24 this.consistentSnapshot = options.consistentSnapshot ?? true; 25 if (!options.roles) { 26 this.roles = role_1.TOP_LEVEL_ROLE_NAMES.reduce((acc, role) => ({ 27 ...acc, 28 [role]: new role_1.Role({ keyIDs: [], threshold: 1 }), 29 }), {}); 30 } 31 else { 32 const roleNames = new Set(Object.keys(options.roles)); 33 if (!role_1.TOP_LEVEL_ROLE_NAMES.every((role) => roleNames.has(role))) { 34 throw new error_1.ValueError('missing top-level role'); 35 } 36 this.roles = options.roles; 37 } 38 } 39 addKey(key, role) { 40 if (!this.roles[role]) { 41 throw new error_1.ValueError(`role ${role} does not exist`); 42 } 43 if (!this.roles[role].keyIDs.includes(key.keyID)) { 44 this.roles[role].keyIDs.push(key.keyID); 45 } 46 this.keys[key.keyID] = key; 47 } 48 equals(other) { 49 if (!(other instanceof Root)) { 50 return false; 51 } 52 return (super.equals(other) && 53 this.consistentSnapshot === other.consistentSnapshot && 54 util_1.default.isDeepStrictEqual(this.keys, other.keys) && 55 util_1.default.isDeepStrictEqual(this.roles, other.roles)); 56 } 57 toJSON() { 58 return { 59 _type: this.type, 60 spec_version: this.specVersion, 61 version: this.version, 62 expires: this.expires, 63 keys: keysToJSON(this.keys), 64 roles: rolesToJSON(this.roles), 65 consistent_snapshot: this.consistentSnapshot, 66 ...this.unrecognizedFields, 67 }; 68 } 69 static fromJSON(data) { 70 const { unrecognizedFields, ...commonFields } = base_1.Signed.commonFieldsFromJSON(data); 71 const { keys, roles, consistent_snapshot, ...rest } = unrecognizedFields; 72 if (typeof consistent_snapshot !== 'boolean') { 73 throw new TypeError('consistent_snapshot must be a boolean'); 74 } 75 return new Root({ 76 ...commonFields, 77 keys: keysFromJSON(keys), 78 roles: rolesFromJSON(roles), 79 consistentSnapshot: consistent_snapshot, 80 unrecognizedFields: rest, 81 }); 82 } 83} 84exports.Root = Root; 85function keysToJSON(keys) { 86 return Object.entries(keys).reduce((acc, [keyID, key]) => ({ ...acc, [keyID]: key.toJSON() }), {}); 87} 88function rolesToJSON(roles) { 89 return Object.entries(roles).reduce((acc, [roleName, role]) => ({ ...acc, [roleName]: role.toJSON() }), {}); 90} 91function keysFromJSON(data) { 92 let keys; 93 if (utils_1.guard.isDefined(data)) { 94 if (!utils_1.guard.isObjectRecord(data)) { 95 throw new TypeError('keys must be an object'); 96 } 97 keys = Object.entries(data).reduce((acc, [keyID, keyData]) => ({ 98 ...acc, 99 [keyID]: key_1.Key.fromJSON(keyID, keyData), 100 }), {}); 101 } 102 return keys; 103} 104function rolesFromJSON(data) { 105 let roles; 106 if (utils_1.guard.isDefined(data)) { 107 if (!utils_1.guard.isObjectRecord(data)) { 108 throw new TypeError('roles must be an object'); 109 } 110 roles = Object.entries(data).reduce((acc, [roleName, roleData]) => ({ 111 ...acc, 112 [roleName]: role_1.Role.fromJSON(roleData), 113 }), {}); 114 } 115 return roles; 116} 117