Files
gerrit/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.js
Paladox none 2bd5c217d0 Rename projects admin interface to repo
This also includes backwards compatibility with the old /projects/ url.

This only renames it for the admin interface. It does not rename it for
changes or anything else.

Bug: Issue 7754
Change-Id: Ia31d3f26871556729fb3c5b5b28ceca12da1ec7c
2017-12-27 21:40:31 +00:00

304 lines
8.1 KiB
JavaScript

// 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';
const Defs = {};
/**
* @typedef {{
* value: !Object,
* }}
*/
Defs.rule;
/**
* @typedef {{
* rules: !Object<string, Defs.rule>
* }}
*/
Defs.permission;
/**
* Can be an empty object or consist of permissions.
*
* @typedef {{
* permissions: !Object<string, Defs.permission>
* }}
*/
Defs.permissions;
/**
* Can be an empty object or consist of permissions.
*
* @typedef {Object<string, Defs.permissions>}
*/
Defs.sections;
/**
* @typedef {{
* remove: Defs.sections,
* add: Defs.sections,
* }}
*/
Defs.projectAccessInput;
Polymer({
is: 'gr-repo-access',
properties: {
repo: {
type: String,
observer: '_repoChanged',
},
// The current path
path: String,
_isAdmin: {
type: Boolean,
value: false,
},
_capabilities: Object,
_groups: Object,
/** @type {?} */
_inheritsFrom: Object,
_labels: Object,
_local: Object,
_editing: {
type: Boolean,
value: false,
},
_modified: {
type: Boolean,
value: false,
},
_sections: Array,
},
behaviors: [
Gerrit.AccessBehavior,
Gerrit.BaseUrlBehavior,
Gerrit.URLEncodingBehavior,
],
listeners: {
'access-modified': '_handleAccessModified',
},
/**
* Gets an array of gr-acces-section Polymer elements.
*
* @return {!Array}
*/
_getSections() {
return Polymer.dom(this.root).querySelectorAll('gr-access-section');
},
/**
* Gets an array of the gr-permission polymer elements for a particular
* access section.
*
* @param {!Object} section
* @return {!Array}
*/
_getPermissionsForSection(section) {
return Polymer.dom(section.root).querySelectorAll('gr-permission');
},
/**
* Gets an array of the gr-rule-editor polymer elements for a particular
* permission (within a section).
*
* @param {!Object} permission
* @return {!Array}
*/
_getRulesForPermission(permission) {
return Polymer.dom(permission.root).querySelectorAll('gr-rule-editor');
},
/**
* Gets an array of all rules for the entire project access.
*
* @return {!Array}
*/
_getAllRules() {
let rules = [];
for (const section of this._getSections()) {
for (const permission of this._getPermissionsForSection(section)) {
rules = rules.concat(this._getRulesForPermission(permission));
}
}
return rules;
},
_handleAccessModified() {
this._modified = true;
},
/**
* @param {string} repo
* @return {!Promise}
*/
_repoChanged(repo) {
if (!repo) { return Promise.resolve(); }
const promises = [];
// Always reset sections when a project changes.
this._sections = [];
promises.push(this.$.restAPI.getRepoAccessRights(repo).then(res => {
this._inheritsFrom = res.inherits_from;
this._local = res.local;
this._groups = res.groups;
return this.toSortedArray(this._local);
}));
promises.push(this.$.restAPI.getCapabilities().then(res => {
return res;
}));
promises.push(this.$.restAPI.getRepo(repo).then(res => {
return res.labels;
}));
promises.push(this.$.restAPI.getIsAdmin().then(isAdmin => {
this._isAdmin = isAdmin;
}));
return Promise.all(promises).then(([sections, capabilities, labels]) => {
this._capabilities = capabilities;
this._labels = labels;
this._sections = sections;
});
},
_handleEdit() {
this._editing = !this._editing;
},
_editOrCancel(editing) {
return editing ? 'Cancel' : 'Edit';
},
/**
* Returns whether or not a given permission exists in the remove object
*
* @param {!Object} remove
* @param {string} sectionId
* @param {string} permissionId
* @return {boolean}
*/
_permissionInRemove(remove, sectionId, permissionId) {
return !!(remove[sectionId] &&
remove[sectionId].permissions[permissionId]);
},
/**
* Returns a projectAccessInput object that contains new permission Objects
* for a given permission in a section.
*
* @param {!Defs.projectAccessInput} addRemoveObj
* @param {string} sectionId
* @param {string} permissionId
*
* @return {!Defs.projectAccessInput}
*/
_generatePermissionObject(addRemoveObj, sectionId, permissionId) {
const permissionObjAdd = {};
const permissionObjRemove = {};
permissionObjAdd[permissionId] = {rules: {}};
permissionObjRemove[permissionId] = {rules: {}};
addRemoveObj.add[sectionId] = {permissions: permissionObjAdd};
addRemoveObj.remove[sectionId] = {permissions: permissionObjRemove};
return addRemoveObj;
},
/**
* Returns an object formatted for saving or submitting access changes for
* review
*
* @return {!Defs.projectAccessInput}
*/
_computeAddAndRemove() {
let addRemoveObj = {
add: {},
remove: {},
};
const sections = this._getSections();
for (const section of sections) {
const sectionId = section.section.id;
const permissions = this._getPermissionsForSection(section);
for (const permission of permissions) {
const permissionId = permission.permission.id;
const rules = this._getRulesForPermission(permission);
for (const rule of rules) {
// Find all rules that are changed. In the event that it has been
// modified.
if (!rule._modified) { continue; }
const ruleId = rule.rule.id;
const ruleValue = rule.rule.value;
// If the rule's parent permission has already been added to the
// remove object (don't need to check add, as they are always
// done to both at the same time). If it doesn't exist yet, it needs
// to be created.
if (!this._permissionInRemove(addRemoveObj.remove, sectionId,
permissionId)) {
addRemoveObj = this._generatePermissionObject(addRemoveObj,
sectionId, permissionId);
}
// Remove the rule with a value of null
addRemoveObj.remove[sectionId].permissions[permissionId]
.rules[ruleId] = null;
// Add the rule with a value of the updated rule value.
addRemoveObj.add[sectionId].permissions[permissionId]
.rules[ruleId] = ruleValue;
}
}
}
return addRemoveObj;
},
_handleSaveForReview() {
// Use saving rather than editing here because rules have to handle
// save prior to toggling editing.
const addRemoveObj = this._computeAddAndRemove();
return this.$.restAPI.setProjectAccessRightsForReview(this.project, {
add: addRemoveObj.add,
remove: addRemoveObj.remove,
}).then(change => {
Gerrit.Nav.navigateToChange(change);
});
},
_computeShowEditClass(sections) {
if (!sections.length) { return ''; }
return 'visible';
},
_computeShowSaveClass(editing) {
if (!editing) { return ''; }
return 'visible';
},
_computeAdminClass(isAdmin) {
return isAdmin ? 'admin' : '';
},
_computeParentHref(repoName) {
return this.getBaseUrl() +
`/admin/repos/${this.encodeURL(repoName, true)},access`;
},
});
})();