PolyGerrit: Add Identities to settings screen
The identities section shows the user what is linked to your id -- external id (ldap, oauth and more), and linked emails. Bug: Issue 4315 Change-Id: Idd271609bc8ae02a935f60b398375afe9bfae613
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
const DETAIL_TYPES = {
|
const DETAIL_TYPES = {
|
||||||
BRANCHES: 'branches',
|
BRANCHES: 'branches',
|
||||||
|
ID: 'id',
|
||||||
TAGS: 'tags',
|
TAGS: 'tags',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,6 +57,8 @@
|
|||||||
return 'Branch';
|
return 'Branch';
|
||||||
} else if (detailType === DETAIL_TYPES.TAGS) {
|
} else if (detailType === DETAIL_TYPES.TAGS) {
|
||||||
return 'Tag';
|
return 'Tag';
|
||||||
|
} else if (detailType === DETAIL_TYPES.ID) {
|
||||||
|
return 'ID';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -0,0 +1,84 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2017 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../../styles/shared-styles.html">
|
||||||
|
<link rel="import" href="../../../styles/gr-form-styles.html">
|
||||||
|
<link rel="import" href="../../admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.html">
|
||||||
|
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||||
|
<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
|
||||||
|
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||||
|
|
||||||
|
<dom-module id="gr-identities">
|
||||||
|
<template>
|
||||||
|
<style include="shared-styles"></style>
|
||||||
|
<style include="gr-form-styles">
|
||||||
|
td {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
.deleteButton {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.deleteButton:not(.show) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.statusColumn {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="gr-form-styles">
|
||||||
|
<table id="identities">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="statusHeader">Status</th>
|
||||||
|
<th class="emailAddressHeader">Email Address</th>
|
||||||
|
<th class="identityHeader">Identity</th>
|
||||||
|
<th class="deleteHeader"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<template is="dom-repeat" items="[[_identities]]" filter="filterIdentities">
|
||||||
|
<tr>
|
||||||
|
<td class$="statusColumn">
|
||||||
|
[[_computeIsTrusted(item.trusted)]]
|
||||||
|
</td>
|
||||||
|
<td>[[item.email_address]]</td>
|
||||||
|
<td>[[_computeIdentity(item.identity)]]</td>
|
||||||
|
<td>
|
||||||
|
<gr-button
|
||||||
|
link
|
||||||
|
class$="deleteButton [[_computeHideDeleteClass(item.can_delete)]]"
|
||||||
|
on-tap="_handleDeleteItem">
|
||||||
|
Delete
|
||||||
|
</gr-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<gr-overlay id="overlay" with-backdrop>
|
||||||
|
<gr-confirm-delete-item-dialog
|
||||||
|
class="confirmDialog"
|
||||||
|
on-confirm="_handleDeleteItemConfirm"
|
||||||
|
on-cancel="_handleConfirmDialogCancel"
|
||||||
|
item="[[_idName]]"
|
||||||
|
item-type="id"></gr-confirm-delete-item-dialog>
|
||||||
|
</gr-overlay>
|
||||||
|
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||||
|
</template>
|
||||||
|
<script src="gr-identities.js"></script>
|
||||||
|
</dom-module>
|
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright (C) 2017 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'gr-identities',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
_identities: Object,
|
||||||
|
_idName: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
loadData() {
|
||||||
|
return this.$.restAPI.getExternalIds().then(id => {
|
||||||
|
this._identities = id;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeIdentity(id) {
|
||||||
|
return id && id.startsWith('mailto:') ? '' : id;
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeHideDeleteClass(canDelete) {
|
||||||
|
return canDelete ? 'show' : '';
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleDeleteItemConfirm() {
|
||||||
|
this.$.overlay.close();
|
||||||
|
return this.$.restAPI.deleteAccountIdentity([this._idName])
|
||||||
|
.then(() => { this.loadData(); });
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleConfirmDialogCancel() {
|
||||||
|
this.$.overlay.close();
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleDeleteItem(e) {
|
||||||
|
const name = e.model.get('item.identity');
|
||||||
|
if (!name) { return; }
|
||||||
|
this._idName = name;
|
||||||
|
this.$.overlay.open();
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeIsTrusted(item) {
|
||||||
|
return item ? '' : 'Untrusted';
|
||||||
|
},
|
||||||
|
|
||||||
|
filterIdentities(item) {
|
||||||
|
return !item.identity.startsWith('username:');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})();
|
@@ -0,0 +1,125 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2017 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||||
|
<title>gr-identities</title>
|
||||||
|
|
||||||
|
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||||
|
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||||
|
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||||
|
<link rel="import" href="gr-identities.html">
|
||||||
|
|
||||||
|
<script>void(0);</script>
|
||||||
|
|
||||||
|
<test-fixture id="basic">
|
||||||
|
<template>
|
||||||
|
<gr-identities></gr-identities>
|
||||||
|
</template>
|
||||||
|
</test-fixture>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
suite('gr-identities tests', () => {
|
||||||
|
let element;
|
||||||
|
let sandbox;
|
||||||
|
const ids = [
|
||||||
|
{
|
||||||
|
identity: 'username:john',
|
||||||
|
email_address: 'john.doe@example.com',
|
||||||
|
trusted: true,
|
||||||
|
}, {
|
||||||
|
identity: 'gerrit:gerrit',
|
||||||
|
email_address: 'gerrit@example.com',
|
||||||
|
}, {
|
||||||
|
identity: 'mailto:gerrit2@example.com',
|
||||||
|
email_address: 'gerrit2@example.com',
|
||||||
|
trusted: true,
|
||||||
|
can_delete: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
setup(done => {
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
|
stub('gr-rest-api-interface', {
|
||||||
|
getExternalIds() { return Promise.resolve(ids); },
|
||||||
|
});
|
||||||
|
|
||||||
|
element = fixture('basic');
|
||||||
|
|
||||||
|
element.loadData().then(() => { flush(done); });
|
||||||
|
});
|
||||||
|
|
||||||
|
teardown(() => {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('renders', () => {
|
||||||
|
const rows = Polymer.dom(element.root).querySelectorAll('tbody tr');
|
||||||
|
|
||||||
|
assert.equal(rows.length, 2);
|
||||||
|
|
||||||
|
const nameCells = rows.map(row =>
|
||||||
|
row.querySelectorAll('td')[2].textContent
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(nameCells[0], 'gerrit:gerrit');
|
||||||
|
assert.equal(nameCells[1], '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('renders email', () => {
|
||||||
|
const rows = Polymer.dom(element.root).querySelectorAll('tbody tr');
|
||||||
|
|
||||||
|
assert.equal(rows.length, 2);
|
||||||
|
|
||||||
|
const nameCells = rows.map(row =>
|
||||||
|
row.querySelectorAll('td')[1].textContent
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(nameCells[0], 'gerrit@example.com');
|
||||||
|
assert.equal(nameCells[1], 'gerrit2@example.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_computeIdentity', () => {
|
||||||
|
assert.equal(
|
||||||
|
element._computeIdentity(ids[0].identity), 'username:john');
|
||||||
|
assert.equal(element._computeIdentity(ids[2].identity), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('filterIdentities', () => {
|
||||||
|
assert.isFalse(element.filterIdentities(ids[0]));
|
||||||
|
|
||||||
|
assert.isTrue(element.filterIdentities(ids[1]));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('delete id', done => {
|
||||||
|
element._idName = 'mailto:gerrit2@example.com';
|
||||||
|
const loadDataStub = sandbox.stub(element, 'loadData');
|
||||||
|
element._handleDeleteItemConfirm().then(() => {
|
||||||
|
assert.isTrue(loadDataStub.called);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_handleDeleteItem opens modal', () => {
|
||||||
|
const deleteBtn =
|
||||||
|
Polymer.dom(element.root).querySelector('.deleteButton');
|
||||||
|
const deleteItem = sandbox.stub(element, '_handleDeleteItem');
|
||||||
|
MockInteractions.tap(deleteBtn);
|
||||||
|
assert.isTrue(deleteItem.called);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@@ -32,6 +32,7 @@ limitations under the License.
|
|||||||
<link rel="import" href="../gr-email-editor/gr-email-editor.html">
|
<link rel="import" href="../gr-email-editor/gr-email-editor.html">
|
||||||
<link rel="import" href="../gr-group-list/gr-group-list.html">
|
<link rel="import" href="../gr-group-list/gr-group-list.html">
|
||||||
<link rel="import" href="../gr-http-password/gr-http-password.html">
|
<link rel="import" href="../gr-http-password/gr-http-password.html">
|
||||||
|
<link rel="import" href="../gr-identities/gr-identities.html">
|
||||||
<link rel="import" href="../gr-menu-editor/gr-menu-editor.html">
|
<link rel="import" href="../gr-menu-editor/gr-menu-editor.html">
|
||||||
<link rel="import" href="../gr-ssh-editor/gr-ssh-editor.html">
|
<link rel="import" href="../gr-ssh-editor/gr-ssh-editor.html">
|
||||||
<link rel="import" href="../gr-watched-projects-editor/gr-watched-projects-editor.html">
|
<link rel="import" href="../gr-watched-projects-editor/gr-watched-projects-editor.html">
|
||||||
@@ -71,6 +72,7 @@ limitations under the License.
|
|||||||
SSH Keys
|
SSH Keys
|
||||||
</a></li>
|
</a></li>
|
||||||
<li><a href="#Groups">Groups</a></li>
|
<li><a href="#Groups">Groups</a></li>
|
||||||
|
<li><a href="#Identities">Identities</a></li>
|
||||||
<template is="dom-if" if="[[_serverConfig.auth.use_contributor_agreements]]">
|
<template is="dom-if" if="[[_serverConfig.auth.use_contributor_agreements]]">
|
||||||
<li>
|
<li>
|
||||||
<a href="#Agreements">Agreements</a>
|
<a href="#Agreements">Agreements</a>
|
||||||
@@ -399,6 +401,10 @@ limitations under the License.
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<gr-group-list id="groupList"></gr-group-list>
|
<gr-group-list id="groupList"></gr-group-list>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<h2 id="Identities">Identities</h2>
|
||||||
|
<fieldset>
|
||||||
|
<gr-identities id="identities"></gr-identities>
|
||||||
|
</fieldset>
|
||||||
<template is="dom-if" if="[[_serverConfig.auth.use_contributor_agreements]]">
|
<template is="dom-if" if="[[_serverConfig.auth.use_contributor_agreements]]">
|
||||||
<h2 id="Agreements">Agreements</h2>
|
<h2 id="Agreements">Agreements</h2>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@@ -145,6 +145,7 @@
|
|||||||
this.$.watchedProjectsEditor.loadData(),
|
this.$.watchedProjectsEditor.loadData(),
|
||||||
this.$.groupList.loadData(),
|
this.$.groupList.loadData(),
|
||||||
this.$.httpPass.loadData(),
|
this.$.httpPass.loadData(),
|
||||||
|
this.$.identities.loadData(),
|
||||||
];
|
];
|
||||||
|
|
||||||
promises.push(this.$.restAPI.getPreferences().then(prefs => {
|
promises.push(this.$.restAPI.getPreferences().then(prefs => {
|
||||||
|
@@ -486,6 +486,15 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getExternalIds() {
|
||||||
|
return this.fetchJSON('/accounts/self/external.ids');
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteAccountIdentity(id) {
|
||||||
|
return this.send('POST', '/accounts/self/external.ids:delete', id)
|
||||||
|
.then(response => this.getResponseObject(response));
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} userId the ID of the user usch as an email address.
|
* @param {string} userId the ID of the user usch as an email address.
|
||||||
* @return {!Promise<!Object>}
|
* @return {!Promise<!Object>}
|
||||||
|
@@ -120,6 +120,7 @@ limitations under the License.
|
|||||||
'settings/gr-email-editor/gr-email-editor_test.html',
|
'settings/gr-email-editor/gr-email-editor_test.html',
|
||||||
'settings/gr-group-list/gr-group-list_test.html',
|
'settings/gr-group-list/gr-group-list_test.html',
|
||||||
'settings/gr-http-password/gr-http-password_test.html',
|
'settings/gr-http-password/gr-http-password_test.html',
|
||||||
|
'settings/gr-identities/gr-identities_test.html',
|
||||||
'settings/gr-menu-editor/gr-menu-editor_test.html',
|
'settings/gr-menu-editor/gr-menu-editor_test.html',
|
||||||
'settings/gr-registration-dialog/gr-registration-dialog_test.html',
|
'settings/gr-registration-dialog/gr-registration-dialog_test.html',
|
||||||
'settings/gr-settings-view/gr-settings-view_test.html',
|
'settings/gr-settings-view/gr-settings-view_test.html',
|
||||||
|
Reference in New Issue
Block a user