Add ability to remove and add back permission in repo access
Bug: Issue 8033 Change-Id: Ib6290c8b50a7c085d0c37a0b268d2a043ecc2ade
This commit is contained in:
@@ -37,10 +37,6 @@ limitations under the License.
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: .3em .7em;
|
margin: .3em .7em;
|
||||||
}
|
}
|
||||||
#deletedContainer {
|
|
||||||
border: 1px solid #d1d2d3;
|
|
||||||
padding: .7em;
|
|
||||||
}
|
|
||||||
.rules {
|
.rules {
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
border: 1px solid #d1d2d3;
|
border: 1px solid #d1d2d3;
|
||||||
@@ -57,11 +53,11 @@ limitations under the License.
|
|||||||
#removeBtn {
|
#removeBtn {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* TODO @beckysiegel add back */
|
.editing #removeBtn {
|
||||||
/* .editing #removeBtn {
|
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.editing #addRule {
|
/* TODO @beckysiegel add back */
|
||||||
|
/* .editing #addRule {
|
||||||
display: block;
|
display: block;
|
||||||
padding: .7em;
|
padding: .7em;
|
||||||
} */
|
} */
|
||||||
@@ -69,7 +65,13 @@ limitations under the License.
|
|||||||
.deleted #mainContainer {
|
.deleted #mainContainer {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.deleted #deletedContainer,
|
.deleted #deletedContainer {
|
||||||
|
align-items: baseline;
|
||||||
|
border: 1px solid #d1d2d3;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: .7em;
|
||||||
|
}
|
||||||
#mainContainer {
|
#mainContainer {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@@ -83,6 +85,7 @@ limitations under the License.
|
|||||||
<div class="header">
|
<div class="header">
|
||||||
<span class="title">[[name]]</span>
|
<span class="title">[[name]]</span>
|
||||||
<gr-button
|
<gr-button
|
||||||
|
link
|
||||||
id="removeBtn"
|
id="removeBtn"
|
||||||
on-tap="_handleRemovePermission">Remove</gr-button>
|
on-tap="_handleRemovePermission">Remove</gr-button>
|
||||||
</div><!-- end header -->
|
</div><!-- end header -->
|
||||||
@@ -112,8 +115,9 @@ limitations under the License.
|
|||||||
</div> <!-- end rules -->
|
</div> <!-- end rules -->
|
||||||
</div><!-- end mainContainer -->
|
</div><!-- end mainContainer -->
|
||||||
<div id="deletedContainer">
|
<div id="deletedContainer">
|
||||||
[[name]] was deleted
|
<span>[[name]] was deleted</span>
|
||||||
<gr-button
|
<gr-button
|
||||||
|
link
|
||||||
id="undoRemoveBtn"
|
id="undoRemoveBtn"
|
||||||
on-tap="_handleUndoRemove">Undo</gr-button>
|
on-tap="_handleUndoRemove">Undo</gr-button>
|
||||||
</div><!-- end deletedContainer -->
|
</div><!-- end deletedContainer -->
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
|
|
||||||
const MAX_AUTOCOMPLETE_RESULTS = 20;
|
const MAX_AUTOCOMPLETE_RESULTS = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when the permission has been modified or removed.
|
||||||
|
*
|
||||||
|
* @event access-modified
|
||||||
|
*/
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'gr-permission',
|
is: 'gr-permission',
|
||||||
|
|
||||||
@@ -33,6 +39,7 @@
|
|||||||
editing: {
|
editing: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
|
observer: '_handleEditingChanged',
|
||||||
},
|
},
|
||||||
_label: {
|
_label: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -61,6 +68,21 @@
|
|||||||
'_handleRulesChanged(_rules.splices)',
|
'_handleRulesChanged(_rules.splices)',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
_handleEditingChanged(editing, editingOld) {
|
||||||
|
// Ignore when editing gets set initially.
|
||||||
|
if (!editingOld) { return; }
|
||||||
|
// Restore original values if no longer editing.
|
||||||
|
if (!editing) {
|
||||||
|
this._deleted = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleRemovePermission() {
|
||||||
|
this._deleted = true;
|
||||||
|
this.permission.value.deleted = true;
|
||||||
|
this.dispatchEvent(new CustomEvent('access-modified', {bubbles: true}));
|
||||||
|
},
|
||||||
|
|
||||||
_handleRulesChanged(changeRecord) {
|
_handleRulesChanged(changeRecord) {
|
||||||
// Update the groups to exclude in the autocomplete.
|
// Update the groups to exclude in the autocomplete.
|
||||||
this._groupsWithRules = this._computeGroupsWithRules(this._rules);
|
this._groupsWithRules = this._computeGroupsWithRules(this._rules);
|
||||||
@@ -70,11 +92,6 @@
|
|||||||
this._rules = this.toSortedArray(permission.value.rules);
|
this._rules = this.toSortedArray(permission.value.rules);
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleRemovePermission() {
|
|
||||||
this._deleted = true;
|
|
||||||
this.set('permission.value.deleted', true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_computeSectionClass(editing, deleted) {
|
_computeSectionClass(editing, deleted) {
|
||||||
const classList = [];
|
const classList = [];
|
||||||
if (editing) {
|
if (editing) {
|
||||||
|
|||||||
@@ -50,8 +50,9 @@ limitations under the License.
|
|||||||
</style>
|
</style>
|
||||||
<style include="gr-menu-page-styles"></style>
|
<style include="gr-menu-page-styles"></style>
|
||||||
<main class$="[[_computeAdminClass(_isAdmin)]]">
|
<main class$="[[_computeAdminClass(_isAdmin)]]">
|
||||||
<div class="gwtLink">This is currently in read only mode. To modify content, go to the
|
<div class="gwtLink">Editing access in the new UI is a work in progress. Visit the
|
||||||
<a href$="[[computeGwtUrl(path)]]" rel="external">Old UI</a>
|
<a href$="[[computeGwtUrl(path)]]" rel="external">Old UI</a>
|
||||||
|
if you need a feature that is not yet supported.
|
||||||
</div>
|
</div>
|
||||||
<template is="dom-if" if="[[_inheritsFrom]]">
|
<template is="dom-if" if="[[_inheritsFrom]]">
|
||||||
<h3 id="inheritsFrom">Rights Inherit From
|
<h3 id="inheritsFrom">Rights Inherit From
|
||||||
|
|||||||
@@ -156,7 +156,14 @@
|
|||||||
for (const item of path) {
|
for (const item of path) {
|
||||||
if (!curPos[item]) {
|
if (!curPos[item]) {
|
||||||
if (item === path[path.length - 1] && type === 'remove') {
|
if (item === path[path.length - 1] && type === 'remove') {
|
||||||
|
// TODO(beckysiegel) This if statement should be removed when
|
||||||
|
// https://gerrit-review.googlesource.com/c/gerrit/+/150851
|
||||||
|
// is live.
|
||||||
|
if (path[path.length - 2] === 'permissions') {
|
||||||
|
curPos[item] = {rules: {}};
|
||||||
|
} else {
|
||||||
curPos[item] = null;
|
curPos[item] = null;
|
||||||
|
}
|
||||||
} else if (item === path[path.length - 1] && type === 'add') {
|
} else if (item === path[path.length - 1] && type === 'add') {
|
||||||
curPos[item] = opt_value;
|
curPos[item] = opt_value;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -100,22 +100,6 @@ limitations under the License.
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const repoAccessInputRemoved = {
|
|
||||||
add: {},
|
|
||||||
remove: {
|
|
||||||
'refs/*': {
|
|
||||||
permissions: {
|
|
||||||
owner: {
|
|
||||||
rules: {
|
|
||||||
123: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
setup(() => {
|
setup(() => {
|
||||||
sandbox = sinon.sandbox.create();
|
sandbox = sinon.sandbox.create();
|
||||||
element = fixture('basic');
|
element = fixture('basic');
|
||||||
@@ -280,17 +264,112 @@ limitations under the License.
|
|||||||
assert.isTrue(element._handleAccessModified.called);
|
assert.isTrue(element._handleAccessModified.called);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_computeAddAndRemove', () => {
|
test('_computeAddAndRemove rules', () => {
|
||||||
// With nothing modified
|
element._local = JSON.parse(JSON.stringify(accessRes.local));
|
||||||
element._local = accessRes.local;
|
|
||||||
assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}});
|
assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}});
|
||||||
element._local['refs/*'].permissions.owner.rules[123].deleted = true;
|
element._local['refs/*'].permissions.owner.rules[123].deleted = true;
|
||||||
assert.deepEqual(element._computeAddAndRemove(), repoAccessInputRemoved);
|
const expectedInput = {
|
||||||
|
add: {},
|
||||||
|
remove: {
|
||||||
|
'refs/*': {
|
||||||
|
permissions: {
|
||||||
|
owner: {
|
||||||
|
rules: {
|
||||||
|
123: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
||||||
delete element._local['refs/*'].permissions.owner.rules[123].deleted;
|
delete element._local['refs/*'].permissions.owner.rules[123].deleted;
|
||||||
element._local['refs/*'].permissions.owner.rules[123].modified = true;
|
element._local['refs/*'].permissions.owner.rules[123].modified = true;
|
||||||
assert.deepEqual(element._computeAddAndRemove(), repoAccessInput);
|
assert.deepEqual(element._computeAddAndRemove(), repoAccessInput);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('_computeAddAndRemove permissions', () => {
|
||||||
|
element._local = JSON.parse(JSON.stringify(accessRes.local));
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}});
|
||||||
|
element._local['refs/*'].permissions.owner.deleted = true;
|
||||||
|
const expectedInput = {
|
||||||
|
add: {},
|
||||||
|
remove: {
|
||||||
|
'refs/*': {
|
||||||
|
permissions: {
|
||||||
|
owner: {rules: {}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_computeAddAndRemove permissions', () => {
|
||||||
|
element._local = JSON.parse(JSON.stringify(accessRes.local));
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}});
|
||||||
|
element._local['refs/*'].permissions.owner.deleted = true;
|
||||||
|
const expectedInput = {
|
||||||
|
add: {},
|
||||||
|
remove: {
|
||||||
|
'refs/*': {
|
||||||
|
permissions: {
|
||||||
|
owner: {rules: {}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_computeAddAndRemove combinations', () => {
|
||||||
|
// Modify rule and delete permission that it is inside of.
|
||||||
|
element._local = JSON.parse(JSON.stringify(accessRes.local));
|
||||||
|
element._local['refs/*'].permissions.owner.rules[123].modified = true;
|
||||||
|
element._local['refs/*'].permissions.owner.deleted = true;
|
||||||
|
let expectedInput = {
|
||||||
|
add: {},
|
||||||
|
remove: {
|
||||||
|
'refs/*': {
|
||||||
|
permissions: {
|
||||||
|
owner: {rules: {}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
||||||
|
// Delete rule and delete permission that it is inside of.
|
||||||
|
element._local['refs/*'].permissions.owner.rules[123].modified = false;
|
||||||
|
element._local['refs/*'].permissions.owner.rules[123].deleted = true;
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
||||||
|
|
||||||
|
// Also modify a different rule inside of another permission.
|
||||||
|
element._local['refs/*'].permissions.read.modified = true;
|
||||||
|
expectedInput = {
|
||||||
|
add: {
|
||||||
|
'refs/*': {
|
||||||
|
permissions: {
|
||||||
|
read: {
|
||||||
|
modified: true,
|
||||||
|
rules: {
|
||||||
|
234: {action: 'ALLOW'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
'refs/*': {
|
||||||
|
permissions: {
|
||||||
|
owner: {rules: {}},
|
||||||
|
read: {rules: {}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
||||||
|
});
|
||||||
|
|
||||||
test('_handleSaveForReview', done => {
|
test('_handleSaveForReview', done => {
|
||||||
sandbox.stub(element.$.restAPI, 'getRepoAccessRights')
|
sandbox.stub(element.$.restAPI, 'getRepoAccessRights')
|
||||||
.returns(Promise.resolve(accessRes));
|
.returns(Promise.resolve(accessRes));
|
||||||
|
|||||||
Reference in New Issue
Block a user