Merge "Show signed push verification result"
This commit is contained in:
@@ -27,6 +27,7 @@ limitations under the License.
|
|||||||
<link rel="import" href="../../shared/gr-account-link/gr-account-link.html">
|
<link rel="import" href="../../shared/gr-account-link/gr-account-link.html">
|
||||||
<link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
|
<link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
|
||||||
<link rel="import" href="../../shared/gr-editable-label/gr-editable-label.html">
|
<link rel="import" href="../../shared/gr-editable-label/gr-editable-label.html">
|
||||||
|
<link rel="import" href="../../shared/gr-icons/gr-icons.html">
|
||||||
<link rel="import" href="../../shared/gr-limited-text/gr-limited-text.html">
|
<link rel="import" href="../../shared/gr-limited-text/gr-limited-text.html">
|
||||||
<link rel="import" href="../../shared/gr-linked-chip/gr-linked-chip.html">
|
<link rel="import" href="../../shared/gr-linked-chip/gr-linked-chip.html">
|
||||||
<link rel="import" href="../../shared/gr-tooltip-content/gr-tooltip-content.html">
|
<link rel="import" href="../../shared/gr-tooltip-content/gr-tooltip-content.html">
|
||||||
@@ -114,6 +115,19 @@ limitations under the License.
|
|||||||
#parentNotCurrentMessage {
|
#parentNotCurrentMessage {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.icon {
|
||||||
|
margin: -.25em 0;
|
||||||
|
}
|
||||||
|
.icon.help,
|
||||||
|
.icon.notTrusted {
|
||||||
|
color: #FFA62F;
|
||||||
|
}
|
||||||
|
.icon.invalid {
|
||||||
|
color: var(--vote-text-color-disliked);
|
||||||
|
}
|
||||||
|
.icon.trusted {
|
||||||
|
color: var(--vote-text-color-recommended);
|
||||||
|
}
|
||||||
.parentList.notCurrent.nonMerge #parentNotCurrentMessage {
|
.parentList.notCurrent.nonMerge #parentNotCurrentMessage {
|
||||||
--arrow-color: #ffa62f;
|
--arrow-color: #ffa62f;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -137,6 +151,16 @@ limitations under the License.
|
|||||||
<span class="title">Owner</span>
|
<span class="title">Owner</span>
|
||||||
<span class="value">
|
<span class="value">
|
||||||
<gr-account-link account="[[change.owner]]"></gr-account-link>
|
<gr-account-link account="[[change.owner]]"></gr-account-link>
|
||||||
|
<template is="dom-if" if="[[_pushCertificateValidation]]">
|
||||||
|
<gr-tooltip-content
|
||||||
|
has-tooltip
|
||||||
|
title$="[[_pushCertificateValidation.message]]">
|
||||||
|
<iron-icon
|
||||||
|
class$="icon [[_pushCertificateValidation.class]]"
|
||||||
|
icon="[[_pushCertificateValidation.icon]]">
|
||||||
|
</iron-icon>
|
||||||
|
</gr-tooltip-content>
|
||||||
|
</template>
|
||||||
</span>
|
</span>
|
||||||
</section>
|
</section>
|
||||||
<section class$="[[_computeShowRoleClass(change, _CHANGE_ROLE.UPLOADER)]]">
|
<section class$="[[_computeShowRoleClass(change, _CHANGE_ROLE.UPLOADER)]]">
|
||||||
|
|||||||
@@ -17,6 +17,17 @@
|
|||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const Defs = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* message: string,
|
||||||
|
* icon: string,
|
||||||
|
* class: string,
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
Defs.PushCertificateValidation;
|
||||||
|
|
||||||
const HASHTAG_ADD_MESSAGE = 'Add Hashtag';
|
const HASHTAG_ADD_MESSAGE = 'Add Hashtag';
|
||||||
|
|
||||||
const SubmitTypeLabel = {
|
const SubmitTypeLabel = {
|
||||||
@@ -30,6 +41,24 @@
|
|||||||
|
|
||||||
const NOT_CURRENT_MESSAGE = 'Not current - rebase possible';
|
const NOT_CURRENT_MESSAGE = 'Not current - rebase possible';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
const CertificateStatus = {
|
||||||
|
/**
|
||||||
|
* This certificate status is bad.
|
||||||
|
*/
|
||||||
|
BAD: 'BAD',
|
||||||
|
/**
|
||||||
|
* This certificate status is OK.
|
||||||
|
*/
|
||||||
|
OK: 'OK',
|
||||||
|
/**
|
||||||
|
* This certificate status is TRUSTED.
|
||||||
|
*/
|
||||||
|
TRUSTED: 'TRUSTED',
|
||||||
|
};
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'gr-change-metadata',
|
is: 'gr-change-metadata',
|
||||||
|
|
||||||
@@ -76,6 +105,13 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: '_computeShowReviewersByState(serverConfig)',
|
computed: '_computeShowReviewersByState(serverConfig)',
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* @type {Defs.PushCertificateValidation}
|
||||||
|
*/
|
||||||
|
_pushCertificateValidation: {
|
||||||
|
type: Object,
|
||||||
|
computed: '_computePushCertificateValidation(serverConfig, change)',
|
||||||
|
},
|
||||||
_showRequirements: {
|
_showRequirements: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: '_computeShowRequirements(change)',
|
computed: '_computeShowRequirements(change)',
|
||||||
@@ -260,6 +296,59 @@
|
|||||||
return hasRequirements || hasLabels || !!change.work_in_progress;
|
return hasRequirements || hasLabels || !!change.work_in_progress;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {?Defs.PushCertificateValidation} object representing data for
|
||||||
|
* the push validation.
|
||||||
|
*/
|
||||||
|
_computePushCertificateValidation(serverConfig, change) {
|
||||||
|
if (!serverConfig || !serverConfig.receive ||
|
||||||
|
!serverConfig.receive.enable_signed_push) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const rev = change.revisions[change.current_revision];
|
||||||
|
if (!rev.push_certificate || !rev.push_certificate.key) {
|
||||||
|
return {
|
||||||
|
class: 'help',
|
||||||
|
icon: 'gr-icons:help',
|
||||||
|
message: 'This patch set was created without a push certificate',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = rev.push_certificate.key;
|
||||||
|
switch (key.status) {
|
||||||
|
case CertificateStatus.BAD:
|
||||||
|
return {
|
||||||
|
class: 'invalid',
|
||||||
|
icon: 'gr-icons:close',
|
||||||
|
message: this._problems('Push certificate is invalid', key),
|
||||||
|
};
|
||||||
|
case CertificateStatus.OK:
|
||||||
|
return {
|
||||||
|
class: 'notTrusted',
|
||||||
|
icon: 'gr-icons:info',
|
||||||
|
message: this._problems(
|
||||||
|
'Push certificate is valid, but key is not trusted', key),
|
||||||
|
};
|
||||||
|
case CertificateStatus.TRUSTED:
|
||||||
|
return {
|
||||||
|
class: 'trusted',
|
||||||
|
icon: 'gr-icons:check',
|
||||||
|
message: this._problems(
|
||||||
|
'Push certificate is valid and key is trusted', key),
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
throw new Error(`unknown certificate status: ${key.status}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_problems(msg, key) {
|
||||||
|
if (!key || !key.problems || key.problems.length === 0) {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [msg + ':'].concat(key.problems).join('\n');
|
||||||
|
},
|
||||||
|
|
||||||
_computeProjectURL(project) {
|
_computeProjectURL(project) {
|
||||||
return Gerrit.Nav.getUrlForProjectChanges(project);
|
return Gerrit.Nav.getUrlForProjectChanges(project);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -311,6 +311,107 @@ limitations under the License.
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Push Certificate Validation test BAD', () => {
|
||||||
|
const serverConfig = {
|
||||||
|
receive: {
|
||||||
|
enable_signed_push: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const change = {
|
||||||
|
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||||
|
owner: {
|
||||||
|
_account_id: 1019328,
|
||||||
|
},
|
||||||
|
revisions: {
|
||||||
|
rev1: {
|
||||||
|
_number: 1,
|
||||||
|
push_certificate: {
|
||||||
|
key: {
|
||||||
|
status: 'BAD',
|
||||||
|
problems: [
|
||||||
|
'No public keys found for key ID E5E20E52',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
current_revision: 'rev1',
|
||||||
|
status: 'NEW',
|
||||||
|
labels: {},
|
||||||
|
mergeable: true,
|
||||||
|
};
|
||||||
|
const result =
|
||||||
|
element._computePushCertificateValidation(serverConfig, change);
|
||||||
|
assert.equal(result.message,
|
||||||
|
'Push certificate is invalid:\n' +
|
||||||
|
'No public keys found for key ID E5E20E52');
|
||||||
|
assert.equal(result.icon, 'gr-icons:close');
|
||||||
|
assert.equal(result.class, 'invalid');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Push Certificate Validation test TRUSTED', () => {
|
||||||
|
const serverConfig = {
|
||||||
|
receive: {
|
||||||
|
enable_signed_push: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const change = {
|
||||||
|
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||||
|
owner: {
|
||||||
|
_account_id: 1019328,
|
||||||
|
},
|
||||||
|
revisions: {
|
||||||
|
rev1: {
|
||||||
|
_number: 1,
|
||||||
|
push_certificate: {
|
||||||
|
key: {
|
||||||
|
status: 'TRUSTED',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
current_revision: 'rev1',
|
||||||
|
status: 'NEW',
|
||||||
|
labels: {},
|
||||||
|
mergeable: true,
|
||||||
|
};
|
||||||
|
const result =
|
||||||
|
element._computePushCertificateValidation(serverConfig, change);
|
||||||
|
assert.equal(result.message,
|
||||||
|
'Push certificate is valid and key is trusted');
|
||||||
|
assert.equal(result.icon, 'gr-icons:check');
|
||||||
|
assert.equal(result.class, 'trusted');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Push Certificate Validation is missing test', () => {
|
||||||
|
const serverConfig = {
|
||||||
|
receive: {
|
||||||
|
enable_signed_push: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const change = {
|
||||||
|
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||||
|
owner: {
|
||||||
|
_account_id: 1019328,
|
||||||
|
},
|
||||||
|
revisions: {
|
||||||
|
rev1: {
|
||||||
|
_number: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
current_revision: 'rev1',
|
||||||
|
status: 'NEW',
|
||||||
|
labels: {},
|
||||||
|
mergeable: true,
|
||||||
|
};
|
||||||
|
const result =
|
||||||
|
element._computePushCertificateValidation(serverConfig, change);
|
||||||
|
assert.equal(result.message,
|
||||||
|
'This patch set was created without a push certificate');
|
||||||
|
assert.equal(result.icon, 'gr-icons:help');
|
||||||
|
assert.equal(result.class, 'help');
|
||||||
|
});
|
||||||
|
|
||||||
test('_computeParents', () => {
|
test('_computeParents', () => {
|
||||||
const parents = [{commit: '123', subject: 'abc'}];
|
const parents = [{commit: '123', subject: 'abc'}];
|
||||||
assert.isUndefined(element._computeParents(
|
assert.isUndefined(element._computeParents(
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ limitations under the License.
|
|||||||
<g id="publishEdit"><path d="M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"/></g>
|
<g id="publishEdit"><path d="M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"/></g>
|
||||||
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/editor-icons.html -->
|
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/editor-icons.html -->
|
||||||
<g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></g>
|
<g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></g>
|
||||||
|
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
|
||||||
|
<g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"></path></g>
|
||||||
|
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
|
||||||
|
<g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"></path></g>
|
||||||
<!-- This SVG is a copy from material.io https://material.io/icons/#ic_hourglass_full-->
|
<!-- This SVG is a copy from material.io https://material.io/icons/#ic_hourglass_full-->
|
||||||
<g id="hourglass"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6z"/><path d="M0 0h24v24H0V0z" fill="none"/></g>
|
<g id="hourglass"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6z"/><path d="M0 0h24v24H0V0z" fill="none"/></g>
|
||||||
<!-- This is a custom PolyGerrit SVG -->
|
<!-- This is a custom PolyGerrit SVG -->
|
||||||
|
|||||||
Reference in New Issue
Block a user