UNPKG

31.1 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.PolicyDocument = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const cdk = require("@aws-cdk/core");
8const cxapi = require("@aws-cdk/cx-api");
9const policy_statement_1 = require("./policy-statement");
10const merge_statements_1 = require("./private/merge-statements");
11const postprocess_policy_document_1 = require("./private/postprocess-policy-document");
12/**
13 * A PolicyDocument is a collection of statements
14 */
15class PolicyDocument {
16 constructor(props = {}) {
17 this.statements = new Array();
18 try {
19 jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyDocumentProps(props);
20 }
21 catch (error) {
22 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
23 Error.captureStackTrace(error, PolicyDocument);
24 }
25 throw error;
26 }
27 this.creationStack = cdk.captureStackTrace();
28 this.autoAssignSids = !!props.assignSids;
29 this.minimize = props.minimize;
30 this.addStatements(...props.statements || []);
31 }
32 /**
33 * Creates a new PolicyDocument based on the object provided.
34 * This will accept an object created from the `.toJSON()` call
35 * @param obj the PolicyDocument in object form.
36 */
37 static fromJson(obj) {
38 const newPolicyDocument = new PolicyDocument();
39 const statement = obj.Statement ?? [];
40 if (statement && !Array.isArray(statement)) {
41 throw new Error('Statement must be an array');
42 }
43 newPolicyDocument.addStatements(...obj.Statement.map((s) => policy_statement_1.PolicyStatement.fromJson(s)));
44 return newPolicyDocument;
45 }
46 resolve(context) {
47 this._maybeMergeStatements(context.scope);
48 // In the previous implementation of 'merge', sorting of actions/resources on
49 // a statement always happened, even on singular statements. In the new
50 // implementation of 'merge', sorting only happens when actually combining 2
51 // statements. This affects all test snapshots, so we need to put in mechanisms
52 // to avoid having to update all snapshots.
53 //
54 // To do sorting in a way compatible with the previous implementation of merging,
55 // (so we don't have to update snapshots) do it after rendering, but only when
56 // merging is enabled.
57 const sort = this.shouldMerge(context.scope);
58 context.registerPostProcessor(new postprocess_policy_document_1.PostProcessPolicyDocument(this.autoAssignSids, sort));
59 return this.render();
60 }
61 /**
62 * Whether the policy document contains any statements.
63 */
64 get isEmpty() {
65 return this.statements.length === 0;
66 }
67 /**
68 * The number of statements already added to this policy.
69 * Can be used, for example, to generate unique "sid"s within the policy.
70 */
71 get statementCount() {
72 return this.statements.length;
73 }
74 /**
75 * Adds a statement to the policy document.
76 *
77 * @param statement the statement to add.
78 */
79 addStatements(...statement) {
80 try {
81 jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyStatement(statement);
82 }
83 catch (error) {
84 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
85 Error.captureStackTrace(error, this.addStatements);
86 }
87 throw error;
88 }
89 this.statements.push(...statement);
90 }
91 /**
92 * Encode the policy document as a string
93 */
94 toString() {
95 return cdk.Token.asString(this, {
96 displayHint: 'PolicyDocument',
97 });
98 }
99 /**
100 * JSON-ify the document
101 *
102 * Used when JSON.stringify() is called
103 */
104 toJSON() {
105 return this.render();
106 }
107 /**
108 * Validate that all policy statements in the policy document satisfies the
109 * requirements for any policy.
110 *
111 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policies-json
112 *
113 * @returns An array of validation error messages, or an empty array if the document is valid.
114 */
115 validateForAnyPolicy() {
116 const errors = new Array();
117 for (const statement of this.statements) {
118 errors.push(...statement.validateForAnyPolicy());
119 }
120 return errors;
121 }
122 /**
123 * Validate that all policy statements in the policy document satisfies the
124 * requirements for a resource-based policy.
125 *
126 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policies-json
127 *
128 * @returns An array of validation error messages, or an empty array if the document is valid.
129 */
130 validateForResourcePolicy() {
131 const errors = new Array();
132 for (const statement of this.statements) {
133 errors.push(...statement.validateForResourcePolicy());
134 }
135 return errors;
136 }
137 /**
138 * Validate that all policy statements in the policy document satisfies the
139 * requirements for an identity-based policy.
140 *
141 * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policies-json
142 *
143 * @returns An array of validation error messages, or an empty array if the document is valid.
144 */
145 validateForIdentityPolicy() {
146 const errors = new Array();
147 for (const statement of this.statements) {
148 errors.push(...statement.validateForIdentityPolicy());
149 }
150 return errors;
151 }
152 /**
153 * Perform statement merging (if enabled and not done yet)
154 *
155 * @internal
156 */
157 _maybeMergeStatements(scope) {
158 if (this.shouldMerge(scope)) {
159 const result = merge_statements_1.mergeStatements(scope, this.statements, false);
160 this.statements.splice(0, this.statements.length, ...result.mergedStatements);
161 }
162 }
163 /**
164 * Split the statements of the PolicyDocument into multiple groups, limited by their size
165 *
166 * We do a round of size-limited merging first (making sure to not produce statements too
167 * large to fit into standalone policies), so that we can most accurately estimate total
168 * policy size. Another final round of minimization will be done just before rendering to
169 * end up with minimal policies that look nice to humans.
170 *
171 * Return a map of the final set of policy documents, mapped to the ORIGINAL (pre-merge)
172 * PolicyStatements that ended up in the given PolicyDocument.
173 *
174 * @internal
175 */
176 _splitDocument(scope, selfMaximumSize, splitMaximumSize) {
177 const self = this;
178 const newDocs = [];
179 // Maps final statements to original statements
180 let statementsToOriginals = new Map(this.statements.map(s => [s, [s]]));
181 if (this.shouldMerge(scope)) {
182 const result = merge_statements_1.mergeStatements(scope, this.statements, true);
183 this.statements.splice(0, this.statements.length, ...result.mergedStatements);
184 statementsToOriginals = result.originsMap;
185 }
186 const sizeOptions = policy_statement_1.deriveEstimateSizeOptions(scope);
187 // Cache statement sizes to avoid recomputing them based on the fields
188 const statementSizes = new Map(this.statements.map(s => [s, s._estimateSize(sizeOptions)]));
189 // Keep some size counters so we can avoid recomputing them based on the statements in each
190 let selfSize = 0;
191 const polSizes = new Map();
192 // Getter with a default to save some syntactic noise
193 const polSize = (x) => polSizes.get(x) ?? 0;
194 let i = 0;
195 while (i < this.statements.length) {
196 const statement = this.statements[i];
197 const statementSize = statementSizes.get(statement) ?? 0;
198 if (selfSize + statementSize < selfMaximumSize) {
199 // Fits in self
200 selfSize += statementSize;
201 i++;
202 continue;
203 }
204 // Split off to new PolicyDocument. Find the PolicyDocument we can add this to,
205 // or add a fresh one.
206 const addToDoc = findDocWithSpace(statementSize);
207 addToDoc.addStatements(statement);
208 polSizes.set(addToDoc, polSize(addToDoc) + statementSize);
209 this.statements.splice(i, 1);
210 }
211 // Return the set of all policy document and original statements
212 const ret = new Map();
213 ret.set(this, this.statements.flatMap(s => statementsToOriginals.get(s) ?? [s]));
214 for (const newDoc of newDocs) {
215 ret.set(newDoc, newDoc.statements.flatMap(s => statementsToOriginals.get(s) ?? [s]));
216 }
217 return ret;
218 function findDocWithSpace(size) {
219 let j = 0;
220 while (j < newDocs.length && polSize(newDocs[j]) + size > splitMaximumSize) {
221 j++;
222 }
223 if (j < newDocs.length) {
224 return newDocs[j];
225 }
226 const newDoc = new PolicyDocument({
227 assignSids: self.autoAssignSids,
228 minimize: self.minimize,
229 });
230 newDocs.push(newDoc);
231 return newDoc;
232 }
233 }
234 render() {
235 if (this.isEmpty) {
236 return undefined;
237 }
238 const doc = {
239 Statement: this.statements.map(s => s.toStatementJson()),
240 Version: '2012-10-17',
241 };
242 return doc;
243 }
244 shouldMerge(scope) {
245 return this.minimize ?? cdk.FeatureFlags.of(scope).isEnabled(cxapi.IAM_MINIMIZE_POLICIES) ?? false;
246 }
247}
248exports.PolicyDocument = PolicyDocument;
249_a = JSII_RTTI_SYMBOL_1;
250PolicyDocument[_a] = { fqn: "@aws-cdk/aws-iam.PolicyDocument", version: "1.161.0" };
251//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9saWN5LWRvY3VtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicG9saWN5LWRvY3VtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFDQUFxQztBQUVyQyx5Q0FBeUM7QUFDekMseURBQWdGO0FBQ2hGLGlFQUE2RDtBQUM3RCx1RkFBa0Y7QUF1Q2xGOztHQUVHO0FBQ0gsTUFBYSxjQUFjO0lBc0J6QixZQUFZLFFBQTZCLEVBQUU7UUFKMUIsZUFBVSxHQUFHLElBQUksS0FBSyxFQUFtQixDQUFDOzs7Ozs7K0NBbEJoRCxjQUFjOzs7O1FBdUJ2QixJQUFJLENBQUMsYUFBYSxHQUFHLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQzdDLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUM7UUFDekMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO1FBRS9CLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0tBQy9DO0lBMUJEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQVE7UUFDN0IsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDO1FBQ3RDLElBQUksU0FBUyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUMxQyxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7U0FDL0M7UUFDRCxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQU0sRUFBRSxFQUFFLENBQUMsa0NBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFD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LENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLElBQUksS0FBSyxDQUFDO0tBQ3BHOztBQXRQSCx3Q0F1UEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgeyBJQ29uc3RydWN0IH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgUG9saWN5U3RhdGVtZW50LCBkZXJpdmVFc3RpbWF0ZVNpemVPcHRpb25zIH0gZnJvbSAnLi9wb2xpY3ktc3RhdGVtZW50JztcbmltcG9ydCB7IG1lcmdlU3RhdGVtZW50cyB9IGZyb20gJy4vcHJpdmF0ZS9tZXJnZS1zdGF0ZW1lbnRzJztcbmltcG9ydCB7IFBvc3RQcm9jZXNzUG9saWN5RG9jdW1lbnQgfSBmcm9tICcuL3ByaXZhdGUvcG9zdHByb2Nlc3MtcG9saWN5LWRvY3VtZW50JztcblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIG5ldyBQb2xpY3lEb2N1bWVudFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvbGljeURvY3VtZW50UHJvcHMge1xuICAvKipcbiAgICogQXV0b21hdGljYWxseSBhc3NpZ24gU3RhdGVtZW50IElkcyB0byBhbGwgc3RhdGVtZW50c1xuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgYXNzaWduU2lkcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluaXRpYWwgc3RhdGVtZW50cyB0byBhZGQgdG8gdGhlIHBvbGljeSBkb2N1bWVudFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHN0YXRlbWVudHNcbiAgICovXG4gIHJlYWRvbmx5IHN0YXRlbWVudHM/OiBQb2xpY3lTdGF0ZW1lbnRbXTtcblxuICAvKipcbiAgICogVHJ5IHRvIG1pbmltaXplIHRoZSBwb2xpY3kgYnkgbWVyZ2luZyBzdGF0ZW1lbnRzXG4gICAqXG4gICAqIFRvIGF2b2lkIG92ZXJydW5uaW5nIHRoZSBtYXhpbXVtIHBvbGljeSBzaXplLCBjb21iaW5lIHN0YXRlbWVudHMgaWYgdGhleSBwcm9kdWNlXG4gICAqIHRoZSBzYW1lIHJlc3VsdC4gTWVyZ2luZyBoYXBwZW5zIGFjY29yZGluZyB0byB0aGUgZm9sbG93aW5nIHJ1bGVzOlxuICAgKlxuICAgKiAtIFRoZSBFZmZlY3Qgb2YgYm90aCBzdGF0ZW1lbnRzIGlzIHRoZSBzYW1lXG4gICAqIC0gTmVpdGhlciBvZiB0aGUgc3RhdGVtZW50cyBoYXZlIGEgJ1NpZCdcbiAgICogLSBDb21iaW5lIFByaW5jaXBhbHMgaWYgdGhlIHJlc3Qgb2YgdGhlIHN0YXRlbWVudCBpcyBleGFjdGx5IHRoZSBzYW1lLlxuICAgKiAtIENvbWJpbmUgUmVzb3VyY2VzIGlmIHRoZSByZXN0IG9mIHRoZSBzdGF0ZW1lbnQgaXMgZXhhY3RseSB0aGUgc2FtZS5cbiAgICogLSBDb21iaW5lIEFjdGlvbnMgaWYgdGhlIHJlc3Qgb2YgdGhlIHN0YXRlbWVudCBpcyBleGFjdGx5IHRoZSBzYW1lLlxuICAgKiAtIFdlIHdpbGwgbmV2ZXIgY29tYmluZSBOb3RQcmluY2lwYWxzLCBOb3RSZXNvdXJjZXMgb3IgTm90QWN0aW9ucywgYmVjYXVzZSBkb2luZ1xuICAgKiAgIHNvIHdvdWxkIGNoYW5nZSB0aGUgbWVhbmluZyBvZiB0aGUgcG9saWN5IGRvY3VtZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlLCB1bmxlc3MgdGhlIGZlYXR1cmUgZmxhZyBgQGF3cy1jZGsvYXdzLWlhbTptaW5pbWl6ZVBvbGljaWVzYCBpcyBzZXRcbiAgICovXG4gIHJlYWRvbmx5IG1pbmltaXplPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIFBvbGljeURvY3VtZW50IGlzIGEgY29sbGVjdGlvbiBvZiBzdGF0ZW1lbnRzXG4gKi9cbmV4cG9ydCBjbGFzcyBQb2xpY3lEb2N1bWVudCBpbXBsZW1lbnRzIGNkay5JUmVzb2x2YWJsZSB7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgUG9saWN5RG9jdW1lbnQgYmFzZWQgb24gdGhlIG9iamVjdCBwcm92aWRlZC5cbiAgICogVGhpcyB3aWxsIGFjY2VwdCBhbiBvYmplY3QgY3JlYXRlZCBmcm9tIHRoZSBgLnRvSlNPTigpYCBjYWxsXG4gICAqIEBwYXJhbSBvYmogdGhlIFBvbGljeURvY3VtZW50IGluIG9iamVjdCBmb3JtLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tSnNvbihvYmo6IGFueSk6IFBvbGljeURvY3VtZW50IHtcbiAgICBjb25zdCBuZXdQb2xpY3lEb2N1bWVudCA9IG5ldyBQb2xpY3lEb2N1bWVudCgpO1xuICAgIGNvbnN0IHN0YXRlbWVudCA9IG9iai5TdGF0ZW1lbnQgPz8gW107XG4gICAgaWYgKHN0YXRlbWVudCAmJiAhQXJyYXkuaXNBcnJheShzdGF0ZW1lbnQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1N0YXRlbWVudCBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgfVxuICAgIG5ld1BvbGljeURvY3VtZW50LmFkZFN0YXRlbWVudHMoLi4ub2JqLlN0YXRlbWVudC5tYXAoKHM6IGFueSkgPT4gUG9saWN5U3RhdGVtZW50LmZyb21Kc29uKHMpKSk7XG4gICAgcmV0dXJuIG5ld1BvbGljeURvY3VtZW50O1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGNyZWF0aW9uU3RhY2s6IHN0cmluZ1tdO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0YXRlbWVudHMgPSBuZXcgQXJyYXk8UG9saWN5U3RhdGVtZW50PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGF1dG9Bc3NpZ25TaWRzOiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IG1pbmltaXplPzogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogUG9saWN5RG9jdW1lbnRQcm9wcyA9IHt9KSB7XG4gICAgdGhpcy5jcmVhdGlvblN0YWNrID0gY2RrLmNhcHR1cmVTdGFja1RyYWNlKCk7XG4gICAgdGhpcy5hdXRvQXNzaWduU2lkcyA9ICEhcHJvcHMuYXNzaWduU2lkcztcbiAgICB0aGlzLm1pbmltaXplID0gcHJvcHMubWluaW1pemU7XG5cbiAgICB0aGlzLmFkZFN0YXRlbWVudHMoLi4ucHJvcHMuc3RhdGVtZW50cyB8fCBbXSk7XG4gIH1cblxuICBwdWJsaWMgcmVzb2x2ZShjb250ZXh0OiBjZGsuSVJlc29sdmVDb250ZXh0KTogYW55IHtcbiAgICB0aGlzLl9tYXliZU1lcmdlU3RhdGVtZW50cyhjb250ZXh0LnNjb3BlKTtcblxuICAgIC8vIEluIHRoZSBwcmV2aW91cyBpbXBsZW1lbnRhdGlvbiBvZiAnbWVyZ2UnLCBzb3J0aW5nIG9mIGFjdGlvbnMvcmVzb3VyY2VzIG9uXG4gICAgLy8gYSBzdGF0ZW1lbnQgYWx3YXlzIGhhcHBlbmVkLCBldmVuICBvbiBzaW5ndWxhciBzdGF0ZW1lbnRzLiBJbiB0aGUgbmV3XG4gICAgLy8gaW1wbGVtZW50YXRpb24gb2YgJ21lcmdlJywgc29ydGluZyBvbmx5IGhhcHBlbnMgd2hlbiBhY3R1YWxseSBjb21iaW5pbmcgMlxuICAgIC8vIHN0YXRlbWVudHMuIFRoaXMgYWZmZWN0cyBhbGwgdGVzdCBzbmFwc2hvdHMsIHNvIHdlIG5lZWQgdG8gcHV0IGluIG1lY2hhbmlzbXNcbiAgICAvLyB0byBhdm9pZCBoYXZpbmcgdG8gdXBkYXRlIGFsbCBzbmFwc2hvdHMuXG4gICAgLy9cbiAgICAvLyBUbyBkbyBzb3J0aW5nIGluIGEgd2F5IGNvbXBhdGlibGUgd2l0aCB0aGUgcHJldmlvdXMgaW1wbGVtZW50YXRpb24gb2YgbWVyZ2luZyxcbiAgICAvLyAoc28gd2UgZG9uJ3QgaGF2ZSB0byB1cGRhdGUgc25hcHNob3RzKSBkbyBpdCBhZnRlciByZW5kZXJpbmcsIGJ1dCBvbmx5IHdoZW5cbiAgICAvLyBtZXJnaW5nIGlzIGVuYWJsZWQuXG4gICAgY29uc3Qgc29ydCA9IHRoaXMuc2hvdWxkTWVyZ2UoY29udGV4dC5zY29wZSk7XG4gICAgY29udGV4dC5yZWdpc3RlclBvc3RQcm9jZXNzb3IobmV3IFBvc3RQcm9jZXNzUG9saWN5RG9jdW1lbnQodGhpcy5hdXRvQXNzaWduU2lkcywgc29ydCkpO1xuICAgIHJldHVybiB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHBvbGljeSBkb2N1bWVudCBjb250YWlucyBhbnkgc3RhdGVtZW50cy5cbiAgICovXG4gIHB1YmxpYyBnZXQgaXNFbXB0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZW1lbnRzLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIHN0YXRlbWVudHMgYWxyZWFkeSBhZGRlZCB0byB0aGlzIHBvbGljeS5cbiAgICogQ2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCB0byBnZW5lcmF0ZSB1bmlxdWUgXCJzaWRcInMgd2l0aGluIHRoZSBwb2xpY3kuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YXRlbWVudENvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVtZW50cy5sZW5ndGg7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHN0YXRlbWVudCB0byB0aGUgcG9saWN5IGRvY3VtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdGVtZW50IHRoZSBzdGF0ZW1lbnQgdG8gYWRkLlxuICAgKi9cbiAgcHVibGljIGFkZFN0YXRlbWVudHMoLi4uc3RhdGVtZW50OiBQb2xpY3lTdGF0ZW1lbnRbXSkge1xuICAgIHRoaXMuc3RhdGVtZW50cy5wdXNoKC4uLnN0YXRlbWVudCk7XG4gIH1cblxuICAvKipcbiAgICogRW5jb2RlIHRoZSBwb2xpY3kgZG9jdW1lbnQgYXMgYSBzdHJpbmdcbiAgICovXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gY2RrLlRva2VuLmFzU3RyaW5nKHRoaXMsIHtcbiAgICAgIGRpc3BsYXlIaW50OiAnUG9saWN5RG9jdW1lbnQnLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEpTT04taWZ5IHRoZSBkb2N1bWVudFxuICAgKlxuICAgKiBVc2VkIHdoZW4gSlNPTi5zdHJpbmdpZnkoKSBpcyBjYWxsZWRcbiAgICovXG4gIHB1YmxpYyB0b0pTT04oKSB7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCBhbGwgcG9saWN5IHN0YXRlbWVudHMgaW4gdGhlIHBvbGljeSBkb2N1bWVudCBzYXRpc2ZpZXMgdGhlXG4gICAqIHJlcXVpcmVtZW50cyBmb3IgYW55IHBvbGljeS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzLWpzb25cbiAgICpcbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlcywgb3IgYW4gZW1wdHkgYXJyYXkgaWYgdGhlIGRvY3VtZW50IGlzIHZhbGlkLlxuICAgKi9cbiAgcHVibGljIHZhbGlkYXRlRm9yQW55UG9saWN5KCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIHRoaXMuc3RhdGVtZW50cykge1xuICAgICAgZXJyb3JzLnB1c2goLi4uc3RhdGVtZW50LnZhbGlkYXRlRm9yQW55UG9saWN5KCkpO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3JzO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgYWxsIHBvbGljeSBzdGF0ZW1lbnRzIGluIHRoZSBwb2xpY3kgZG9jdW1lbnQgc2F0aXNmaWVzIHRoZVxuICAgKiByZXF1aXJlbWVudHMgZm9yIGEgcmVzb3VyY2UtYmFzZWQgcG9saWN5LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9hY2Nlc3NfcG9saWNpZXMuaHRtbCNhY2Nlc3NfcG9saWNpZXMtanNvblxuICAgKlxuICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiB2YWxpZGF0aW9uIGVycm9yIG1lc3NhZ2VzLCBvciBhbiBlbXB0eSBhcnJheSBpZiB0aGUgZG9jdW1lbnQgaXMgdmFsaWQuXG4gICAqL1xuICBwdWJsaWMgdmFsaWRhdGVGb3JSZXNvdXJjZVBvbGljeSgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiB0aGlzLnN0YXRlbWVudHMpIHtcbiAgICAgIGVycm9ycy5wdXNoKC4uLnN0YXRlbWVudC52YWxpZGF0ZUZvclJlc291cmNlUG9saWN5KCkpO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3JzO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgYWxsIHBvbGljeSBzdGF0ZW1lbnRzIGluIHRoZSBwb2xpY3kgZG9jdW1lbnQgc2F0aXNmaWVzIHRoZVxuICAgKiByZXF1aXJlbWVudHMgZm9yIGFuIGlkZW50aXR5LWJhc2VkIHBvbGljeS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvYWNjZXNzX3BvbGljaWVzLmh0bWwjYWNjZXNzX3BvbGljaWVzLWpzb25cbiAgICpcbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlcywgb3IgYW4gZW1wdHkgYXJyYXkgaWYgdGhlIGRvY3VtZW50IGlzIHZhbGlkLlxuICAgKi9cbiAgcHVibGljIHZhbGlkYXRlRm9ySWRlbnRpdHlQb2xpY3koKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGVycm9ycyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgdGhpcy5zdGF0ZW1lbnRzKSB7XG4gICAgICBlcnJvcnMucHVzaCguLi5zdGF0ZW1lbnQudmFsaWRhdGVGb3JJZGVudGl0eVBvbGljeSgpKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIHN0YXRlbWVudCBtZXJnaW5nIChpZiBlbmFibGVkIGFuZCBub3QgZG9uZSB5ZXQpXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9tYXliZU1lcmdlU3RhdGVtZW50cyhzY29wZTogY2RrLklDb25zdHJ1Y3QpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zaG91bGRNZXJnZShzY29wZSkpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IG1lcmdlU3RhdGVtZW50cyhzY29wZSwgdGhpcy5zdGF0ZW1lbnRzLCBmYWxzZSk7XG4gICAgICB0aGlzLnN0YXRlbWVudHMuc3BsaWNlKDAsIHRoaXMuc3RhdGVtZW50cy5sZW5ndGgsIC4uLnJlc3VsdC5tZXJnZWRTdGF0ZW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3BsaXQgdGhlIHN0YXRlbWVudHMgb2YgdGhlIFBvbGljeURvY3VtZW50IGludG8gbXVsdGlwbGUgZ3JvdXBzLCBsaW1pdGVkIGJ5IHRoZWlyIHNpemVcbiAgICpcbiAgICogV2UgZG8gYSByb3VuZCBvZiBzaXplLWxpbWl0ZWQgbWVyZ2luZyBmaXJzdCAobWFraW5nIHN1cmUgdG8gbm90IHByb2R1Y2Ugc3RhdGVtZW50cyB0b29cbiAgICogbGFyZ2UgdG8gZml0IGludG8gc3RhbmRhbG9uZSBwb2xpY2llcyksIHNvIHRoYXQgd2UgY2FuIG1vc3QgYWNjdXJhdGVseSBlc3RpbWF0ZSB0b3RhbFxuICAgKiBwb2xpY3kgc2l6ZS4gQW5vdGhlciBmaW5hbCByb3VuZCBvZiBtaW5pbWl6YXRpb24gd2lsbCBiZSBkb25lIGp1c3QgYmVmb3JlIHJlbmRlcmluZyB0b1xuICAgKiBlbmQgdXAgd2l0aCBtaW5pbWFsIHBvbGljaWVzIHRoYXQgbG9vayBuaWNlIHRvIGh1bWFucy5cbiAgICpcbiAgICogUmV0dXJuIGEgbWFwIG9mIHRoZSBmaW5hbCBzZXQgb2YgcG9saWN5IGRvY3VtZW50cywgbWFwcGVkIHRvIHRoZSBPUklHSU5BTCAocHJlLW1lcmdlKVxuICAgKiBQb2xpY3lTdGF0ZW1lbnRzIHRoYXQgZW5kZWQgdXAgaW4gdGhlIGdpdmVuIFBvbGljeURvY3VtZW50LlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfc3BsaXREb2N1bWVudChzY29wZTogSUNvbnN0cnVjdCwgc2VsZk1heGltdW1TaXplOiBudW1iZXIsIHNwbGl0TWF4aW11bVNpemU6IG51bWJlcik6IE1hcDxQb2xpY3lEb2N1bWVudCwgUG9saWN5U3RhdGVtZW50W10+IHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCBuZXdEb2NzOiBQb2xpY3lEb2N1bWVudFtdID0gW107XG5cbiAgICAvLyBNYXBzIGZpbmFsIHN0YXRlbWVudHMgdG8gb3JpZ2luYWwgc3RhdGVtZW50c1xuICAgIGxldCBzdGF0ZW1lbnRzVG9PcmlnaW5hbHMgPSBuZXcgTWFwKHRoaXMuc3RhdGVtZW50cy5tYXAocyA9PiBbcywgW3NdXSkpO1xuICAgIGlmICh0aGlzLnNob3VsZE1lcmdlKHNjb3BlKSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gbWVyZ2VTdGF0ZW1lbnRzKHNjb3BlLCB0aGlzLnN0YXRlbWVudHMsIHRydWUpO1xuICAgICAgdGhpcy5zdGF0ZW1lbnRzLnNwbGljZSgwLCB0aGlzLnN0YXRlbWVudHMubGVuZ3RoLCAuLi5yZXN1bHQubWVyZ2VkU3RhdGVtZW50cyk7XG4gICAgICBzdGF0ZW1lbnRzVG9PcmlnaW5hbHMgPSByZXN1bHQub3JpZ2luc01hcDtcbiAgICB9XG5cbiAgICBjb25zdCBzaXplT3B0aW9ucyA9IGRlcml2ZUVzdGltYXRlU2l6ZU9wdGlvbnMoc2NvcGUpO1xuXG4gICAgLy8gQ2FjaGUgc3RhdGVtZW50IHNpemVzIHRvIGF2b2lkIHJlY29tcHV0aW5nIHRoZW0gYmFzZWQgb24gdGhlIGZpZWxkc1xuICAgIGNvbnN0IHN0YXRlbWVudFNpemVzID0gbmV3IE1hcDxQb2xpY3lTdGF0ZW1lbnQsIG51bWJlcj4odGhpcy5zdGF0ZW1lbnRzLm1hcChzID0+IFtzLCBzLl9lc3RpbWF0ZVNpemUoc2l6ZU9wdGlvbnMpXSkpO1xuXG4gICAgLy8gS2VlcCBzb21lIHNpemUgY291bnRlcnMgc28gd2UgY2FuIGF2b2lkIHJlY29tcHV0aW5nIHRoZW0gYmFzZWQgb24gdGhlIHN0YXRlbWVudHMgaW4gZWFjaFxuICAgIGxldCBzZWxmU2l6ZSA9IDA7XG4gICAgY29uc3QgcG9sU2l6ZXMgPSBuZXcgTWFwPFBvbGljeURvY3VtZW50LCBudW1iZXI+KCk7XG4gICAgLy8gR2V0dGVyIHdpdGggYSBkZWZhdWx0IHRvIHNhdmUgc29tZSBzeW50YWN0aWMgbm9pc2VcbiAgICBjb25zdCBwb2xTaXplID0gKHg6IFBvbGljeURvY3VtZW50KSA9PiBwb2xTaXplcy5nZXQoeCkgPz8gMDtcblxuICAgIGxldCBpID0gMDtcbiAgICB3aGlsZSAoaSA8IHRoaXMuc3RhdGVtZW50cy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHN0YXRlbWVudCA9IHRoaXMuc3RhdGVtZW50c1tpXTtcblxuICAgICAgY29uc3Qgc3RhdGVtZW50U2l6ZSA9IHN0YXRlbWVudFNpemVzLmdldChzdGF0ZW1lbnQpID8/IDA7XG4gICAgICBpZiAoc2VsZlNpemUgKyBzdGF0ZW1lbnRTaXplIDwgc2VsZk1heGltdW1TaXplKSB7XG4gICAgICAgIC8vIEZpdHMgaW4gc2VsZlxuICAgICAgICBzZWxmU2l6ZSArPSBzdGF0ZW1lbnRTaXplO1xuICAgICAgICBpKys7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBTcGxpdCBvZmYgdG8gbmV3IFBvbGljeURvY3VtZW50LiBGaW5kIHRoZSBQb2xpY3lEb2N1bWVudCB3ZSBjYW4gYWRkIHRoaXMgdG8sXG4gICAgICAvLyBvciBhZGQgYSBmcmVzaCBvbmUuXG4gICAgICBjb25zdCBhZGRUb0RvYyA9IGZpbmREb2NXaXRoU3BhY2Uoc3RhdGVtZW50U2l6ZSk7XG4gICAgICBhZGRUb0RvYy5hZGRTdGF0ZW1lbnRzKHN0YXRlbWVudCk7XG4gICAgICBwb2xTaXplcy5zZXQoYWRkVG9Eb2MsIHBvbFNpemUoYWRkVG9Eb2MpICsgc3RhdGVtZW50U2l6ZSk7XG4gICAgICB0aGlzLnN0YXRlbWVudHMuc3BsaWNlKGksIDEpO1xuICAgIH1cblxuICAgIC8vIFJldHVybiB0aGUgc2V0IG9mIGFsbCBwb2xpY3kgZG9jdW1lbnQgYW5kIG9yaWdpbmFsIHN0YXRlbWVudHNcbiAgICBjb25zdCByZXQgPSBuZXcgTWFwPFBvbGljeURvY3VtZW50LCBQb2xpY3lTdGF0ZW1lbnRbXT4oKTtcbiAgICByZXQuc2V0KHRoaXMsIHRoaXMuc3RhdGVtZW50cy5mbGF0TWFwKHMgPT4gc3RhdGVtZW50c1RvT3JpZ2luYWxzLmdldChzKSA/PyBbc10pKTtcbiAgICBmb3IgKGNvbnN0IG5ld0RvYyBvZiBuZXdEb2NzKSB7XG4gICAgICByZXQuc2V0KG5ld0RvYywgbmV3RG9jLnN0YXRlbWVudHMuZmxhdE1hcChzID0+IHN0YXRlbWVudHNUb09yaWdpbmFscy5nZXQocykgPz8gW3NdKSk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG5cbiAgICBmdW5jdGlvbiBmaW5kRG9jV2l0aFNwYWNlKHNpemU6IG51bWJlcikge1xuICAgICAgbGV0IGogPSAwO1xuICAgICAgd2hpbGUgKGogPCBuZXdEb2NzLmxlbmd0aCAmJiBwb2xTaXplKG5ld0RvY3Nbal0pICsgc2l6ZSA+IHNwbGl0TWF4aW11bVNpemUpIHtcbiAgICAgICAgaisrO1xuICAgICAgfVxuICAgICAgaWYgKGogPCBuZXdEb2NzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gbmV3RG9jc1tqXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmV3RG9jID0gbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgYXNzaWduU2lkczogc2VsZi5hdXRvQXNzaWduU2lkcyxcbiAgICAgICAgbWluaW1pemU6IHNlbGYubWluaW1pemUsXG4gICAgICB9KTtcbiAgICAgIG5ld0RvY3MucHVzaChuZXdEb2MpO1xuICAgICAgcmV0dXJuIG5ld0RvYztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbmRlcigpOiBhbnkge1xuICAgIGlmICh0aGlzLmlzRW1wdHkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgZG9jID0ge1xuICAgICAgU3RhdGVtZW50OiB0aGlzLnN0YXRlbWVudHMubWFwKHMgPT4gcy50b1N0YXRlbWVudEpzb24oKSksXG4gICAgICBWZXJzaW9uOiAnMjAxMi0xMC0xNycsXG4gICAgfTtcblxuICAgIHJldHVybiBkb2M7XG4gIH1cblxuICBwcml2YXRlIHNob3VsZE1lcmdlKHNjb3BlOiBJQ29uc3RydWN0KSB7XG4gICAgcmV0dXJuIHRoaXMubWluaW1pemUgPz8gY2RrLkZlYXR1cmVGbGFncy5vZihzY29wZSkuaXNFbmFibGVkKGN4YXBpLklBTV9NSU5JTUlaRV9QT0xJQ0lFUykgPz8gZmFsc2U7XG4gIH1cbn1cbiJdfQ==
\No newline at end of file