root.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.Root = void 0;
  7. const util_1 = __importDefault(require("util"));
  8. const base_1 = require("./base");
  9. const error_1 = require("./error");
  10. const key_1 = require("./key");
  11. const role_1 = require("./role");
  12. const 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. */
  19. class 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. }
  84. exports.Root = Root;
  85. function keysToJSON(keys) {
  86. return Object.entries(keys).reduce((acc, [keyID, key]) => ({ ...acc, [keyID]: key.toJSON() }), {});
  87. }
  88. function rolesToJSON(roles) {
  89. return Object.entries(roles).reduce((acc, [roleName, role]) => ({ ...acc, [roleName]: role.toJSON() }), {});
  90. }
  91. function 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. }
  104. function 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. }