Allow username editing if permitted by project cfg
Change-Id: I57986af606833c20535c719a1f7540d22d4602bb
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html
index 494b9e8..5dbd466 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html
@@ -44,17 +44,28 @@
date-str="[[_account.registered_on]]"></gr-date-formatter>
</span>
</section>
- <section>
+ <section id="usernameSection">
<span class="title">Username</span>
- <span class="value">[[_account.username]]</span>
+ <span
+ hidden$="[[usernameMutable]]"
+ class="value">[[_account.username]]</span>
+ <span
+ hidden$="[[!usernameMutable]]"
+ class="value">
+ <input
+ is="iron-input"
+ id="usernameInput"
+ disabled="[[_saving]]"
+ on-keydown="_handleKeydown"
+ bind-value="{{_account.username}}">
</section>
<section id="nameSection">
<span class="title">Full name</span>
<span
- hidden$="[[mutable]]"
+ hidden$="[[nameMutable]]"
class="value">[[_account.name]]</span>
<span
- hidden$="[[!mutable]]"
+ hidden$="[[!nameMutable]]"
class="value">
<input
is="iron-input"
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
index 5d7f8a6..03795f6 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
@@ -24,21 +24,31 @@
*/
properties: {
- mutable: {
+ usernameMutable: {
type: Boolean,
notify: true,
- computed: '_computeMutable(_serverConfig)',
+ computed: '_computeUsernameMutable(_serverConfig)',
+ },
+ nameMutable: {
+ type: Boolean,
+ notify: true,
+ computed: '_computeNameMutable(_serverConfig)',
},
hasUnsavedChanges: {
type: Boolean,
notify: true,
- computed: '_computeHasUnsavedChanges(_hasNameChange, _hasStatusChange)',
+ computed: '_computeHasUnsavedChanges(_hasNameChange, ' +
+ '_hasUsernameChange, _hasStatusChange)',
},
_hasNameChange: {
type: Boolean,
value: false,
},
+ _hasUsernameChange: {
+ type: Boolean,
+ value: false,
+ },
_hasStatusChange: {
type: Boolean,
value: false,
@@ -58,6 +68,7 @@
observers: [
'_nameChanged(_account.name)',
+ '_usernameChanged(_account.username)',
'_statusChanged(_account.status)',
],
@@ -88,6 +99,7 @@
// Set only the fields that have changed.
// Must be done in sequence to avoid race conditions (@see Issue 5721)
return this._maybeSetName()
+ .then(this._maybeSetUsername.bind(this))
.then(this._maybeSetStatus.bind(this))
.then(() => {
this._hasNameChange = false;
@@ -98,9 +110,15 @@
},
_maybeSetName() {
- return this._hasNameChange && this.mutable ?
- this.$.restAPI.setAccountName(this._account.name) :
- Promise.resolve();
+ return this._hasNameChange && this.nameMutable ?
+ this.$.restAPI.setAccountName(this._account.name) :
+ Promise.resolve();
+ },
+
+ _maybeSetUsername() {
+ return this._hasUsernameChange && this.usernameMutable ?
+ this.$.restAPI.setAccountUsername(this._account.username) :
+ Promise.resolve();
},
_maybeSetStatus() {
@@ -109,11 +127,15 @@
Promise.resolve();
},
- _computeHasUnsavedChanges(name, status) {
- return name || status;
+ _computeHasUnsavedChanges(nameChanged, usernameChanged, statusChanged) {
+ return nameChanged || usernameChanged || statusChanged;
},
- _computeMutable(config) {
+ _computeUsernameMutable(config) {
+ return config.auth.editable_account_fields.includes('USER_NAME');
+ },
+
+ _computeNameMutable(config) {
return config.auth.editable_account_fields.includes('FULL_NAME');
},
@@ -122,6 +144,11 @@
this._hasStatusChange = true;
},
+ _usernameChanged() {
+ if (this._loading) { return; }
+ this._hasUsernameChange = true;
+ },
+
_nameChanged() {
if (this._loading) { return; }
this._hasNameChange = true;
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
index 84fbc09..e46be5b 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
@@ -84,18 +84,18 @@
assert.equal(valueOf('Username').textContent, account.username);
});
- test('user name render (immutable)', () => {
+ test('full name render (immutable)', () => {
const section = element.$.nameSection;
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
- assert.isFalse(element.mutable);
+ assert.isFalse(element.nameMutable);
assert.isFalse(displaySpan.hasAttribute('hidden'));
assert.equal(displaySpan.textContent, account.name);
assert.isTrue(inputSpan.hasAttribute('hidden'));
});
- test('user name render (mutable)', () => {
+ test('full name render (mutable)', () => {
element.set('_serverConfig',
{auth: {editable_account_fields: ['FULL_NAME']}});
@@ -103,32 +103,62 @@
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
- assert.isTrue(element.mutable);
+ assert.isTrue(element.nameMutable);
assert.isTrue(displaySpan.hasAttribute('hidden'));
assert.equal(element.$.nameInput.bindValue, account.name);
assert.isFalse(inputSpan.hasAttribute('hidden'));
});
+ test('username render (immutable)', () => {
+ const section = element.$.usernameSection;
+ const displaySpan = section.querySelectorAll('.value')[0];
+ const inputSpan = section.querySelectorAll('.value')[1];
+
+ assert.isFalse(element.usernameMutable);
+ assert.isFalse(displaySpan.hasAttribute('hidden'));
+ assert.equal(displaySpan.textContent, account.username);
+ assert.isTrue(inputSpan.hasAttribute('hidden'));
+ });
+
+ test('username render (mutable)', () => {
+ element.set('_serverConfig',
+ {auth: {editable_account_fields: ['USER_NAME']}});
+
+ const section = element.$.usernameSection;
+ const displaySpan = section.querySelectorAll('.value')[0];
+ const inputSpan = section.querySelectorAll('.value')[1];
+
+ assert.isTrue(element.usernameMutable);
+ assert.isTrue(displaySpan.hasAttribute('hidden'));
+ assert.equal(element.$.usernameInput.bindValue, account.username);
+ assert.isFalse(inputSpan.hasAttribute('hidden'));
+ });
+
suite('account info edit', () => {
let nameChangedSpy;
+ let usernameChangedSpy;
let statusChangedSpy;
let nameStub;
+ let usernameStub;
let statusStub;
setup(() => {
nameChangedSpy = sandbox.spy(element, '_nameChanged');
+ usernameChangedSpy = sandbox.spy(element, '_usernameChanged');
statusChangedSpy = sandbox.spy(element, '_statusChanged');
element.set('_serverConfig',
- {auth: {editable_account_fields: ['FULL_NAME']}});
+ {auth: {editable_account_fields: ['FULL_NAME', 'USER_NAME']}});
- nameStub = sandbox.stub(element.$.restAPI, 'setAccountName', name =>
- Promise.resolve());
+ nameStub = sandbox.stub(element.$.restAPI, 'setAccountName',
+ name => Promise.resolve());
+ usernameStub = sandbox.stub(element.$.restAPI, 'setAccountUsername',
+ username => Promise.resolve());
statusStub = sandbox.stub(element.$.restAPI, 'setAccountStatus',
status => Promise.resolve());
});
test('name', done => {
- assert.isTrue(element.mutable);
+ assert.isTrue(element.nameMutable);
assert.isFalse(element.hasUnsavedChanges);
element.set('_account.name', 'new name');
@@ -137,18 +167,39 @@
assert.isFalse(statusChangedSpy.called);
assert.isTrue(element.hasUnsavedChanges);
- MockInteractions.pressAndReleaseKeyOn(element.$.nameInput, 13);
+ element.save().then(() => {
+ assert.isFalse(usernameStub.called);
+ assert.isTrue(nameStub.called);
+ assert.isFalse(statusStub.called);
+ nameStub.lastCall.returnValue.then(() => {
+ assert.equal(nameStub.lastCall.args[0], 'new name');
+ done();
+ });
+ });
+ });
- assert.isTrue(nameStub.called);
- assert.isFalse(statusStub.called);
- nameStub.lastCall.returnValue.then(() => {
- assert.equal(nameStub.lastCall.args[0], 'new name');
- done();
+ test('username', done => {
+ assert.isTrue(element.usernameMutable);
+ assert.isFalse(element.hasUnsavedChanges);
+
+ element.set('_account.username', 'new username');
+
+ assert.isTrue(usernameChangedSpy.called);
+ assert.isFalse(statusChangedSpy.called);
+ assert.isTrue(element.hasUnsavedChanges);
+
+ element.save().then(() => {
+ assert.isTrue(usernameStub.called);
+ assert.isFalse(nameStub.called);
+ assert.isFalse(statusStub.called);
+ usernameStub.lastCall.returnValue.then(() => {
+ assert.equal(usernameStub.lastCall.args[0], 'new username');
+ done();
+ });
});
});
test('status', done => {
- assert.isTrue(element.mutable);
assert.isFalse(element.hasUnsavedChanges);
element.set('_account.status', 'new status');
@@ -158,6 +209,7 @@
assert.isTrue(element.hasUnsavedChanges);
element.save().then(() => {
+ assert.isFalse(usernameStub.called);
assert.isTrue(statusStub.called);
assert.isFalse(nameStub.called);
statusStub.lastCall.returnValue.then(() => {
@@ -178,16 +230,18 @@
nameChangedSpy = sandbox.spy(element, '_nameChanged');
statusChangedSpy = sandbox.spy(element, '_statusChanged');
element.set('_serverConfig',
- {auth: {editable_account_fields: ['FULL_NAME']}});
+ {auth: {editable_account_fields: ['FULL_NAME']}});
- nameStub = sandbox.stub(element.$.restAPI, 'setAccountName', name =>
- Promise.resolve());
+ nameStub = sandbox.stub(element.$.restAPI, 'setAccountName',
+ name => Promise.resolve());
statusStub = sandbox.stub(element.$.restAPI, 'setAccountStatus',
status => Promise.resolve());
+ sandbox.stub(element.$.restAPI, 'setAccountUsername',
+ username => Promise.resolve());
});
test('set name and status', done => {
- assert.isTrue(element.mutable);
+ assert.isTrue(element.nameMutable);
assert.isFalse(element.hasUnsavedChanges);
element.set('_account.name', 'new name');
@@ -231,7 +285,7 @@
const displaySpan = section.querySelectorAll('.value')[0];
const inputSpan = section.querySelectorAll('.value')[1];
- assert.isFalse(element.mutable);
+ assert.isFalse(element.nameMutable);
assert.isFalse(element.hasUnsavedChanges);