
* stable-3.0: Update git submodules Update git submodules Update git submodules Fix documentation of UI selection Set version to 2.16.12-SNAPSHOT Set version to 2.16.11 Update git submodules Revert "GerritServer: Silence non-critical logs from JGit's FileSnapshot" Revert "GerritServer: Silence non-critical logs from JGit's FS" Revert "Upgrade JGit to 5.1.10.201908230655-r" Revert "Stop using deprecated DirCacheEntry#setLastModified(long)" Update git submodules Update git submodules Update git submodules Update git submodules Update git submodules Update git submodules Set version to 2.15.17-SNAPSHOT Update git submodules Update git submodules Revert "Upgrade JGit to 5.3.4.201908231101-r" Set version to 2.15.16 Revert "CreateAccount: Fail early when invalid SSH key is given" Update git submodules tools/eclipse/project.py: Fix typo of bazelisk Set XSRF on '/' under PolyGerrit Migrate from old-style legacy .java provider to the new JavaInfo. Remove deleted rules for the new added section Support bazelisk or bazel in tools/eclipse/project.py Rework imports in project.py Update project.py to use argparse AccountIT: Test that account is not created with invalid email CreateAccount: Fail early when invalid SSH key is given Update git submodules GerritServer: Silence non-critical logs from JGit's FS GerritServer: Silence non-critical logs from JGit's FileSnapshot Stop using deprecated DirCacheEntry#setLastModified(long) ProjectState: Fix 'invalid type qualification' javadoc warning Upgrade JGit to 5.3.4.201908231101-r Documentation: refresh IntelliJ IDEA developer documentation Documentation: update external links to Bazel Use base url for commentlink Update git submodules Update git submodules Don't store LabelTypes in ProjectState Upgrade highlight.js to latest master revision Update git submodules Update git submodules Update git submodules StarredChangesUtil: Stop using deprecated RefDatabase.getRef Suppress warnings about deprecated BaseReceivePack DeleteRef: Stop using deprecated RefDatabase.getRef Upgrade elasticsearch-rest-client to 7.3.1 Add .gitreview file Remove vestigal GWT plugin loading hooks Upgrade JGit to 5.1.10.201908230655-r DeleteDraftComments: Don't update change modified timestamp ChangeIT: set submittableAfterLosingPermissions private Rebase: Don't swallow caught exception Output NoteDb migration progress to Flogger Update git submodules Remove AccountPatchReview data when change gets auto-abandoned DefaultChangeReportFormatter: Make constructor and urlFormatter visible StarredChangesUtil: Fix NPE when ref to be deleted doesn't exist StarredChangesUtil: Throw LockFailureException on LOCK_FAILURE Add test for creating a change on a non-existing base change Rebase: Do not fail with 500 ISE if non-existing change is given as base Fix detecting changes of parent trees when computing change kind for merge commit Remove duplicate descriptions of fields in Requirement JSON entity Allow to set content type in the plugin REST API interface InternalAccountQuery: Add back the oneByExternalId method Set version to 2.16.11-SNAPSHOT Revert "Migrate from old-style legacy .java provider to the new JavaInfo." Catch all exceptions for reporting on Schema_130 migration Update git submodules Migrate from old-style legacy .java provider to the new JavaInfo. Update git submodules Update git submodules AuthRequest: Fix Javadoc for return values ChangeApi: Add methods to get change comments/drafts as list Update git submodules ListChangeComments: Extend ListChangeDrafts Upgrade Go Bazel rules to the latest version detach -> detached Fix anchor tag for settings page Add support for Elasticsearch version 7.3.* PrologEnvironment: Reduce "setting reductionLimit" log spam ElasticContainer: Upgrade to 6.8.2 image for V6_8 tests Fix typo: program Fix email token routing Clarify usage of 'parent' option in list files API Remove unused Skylark patch file Files: Use Gerrit API to get revision parents Fix broken link for rest-api-projects.html#commentlink-info Add support for Elasticsearch version 6.8.x Upgrade elasticsearch-rest-client to 7.2.1 Add support for "Link Another Identity" in gr-identities Update git submodules CommitApi: Add method to get commit info Consolidate all CommitApi tests into a single class Files: Validate parent option to prevent internal server error RevisionIT: Assert that files(base) only works for patch set revisions Fix and expand documentation of REST API to get revision files RevisionIT#files: Simplify assertion Update git submodules Update git submodules Update git submodules Update git submodules Remove default bug tracker from _feedbackUrl PG: Add shortcuts for dashboard and watched changes PG: Allow empty label values Remove token param from getCapabilities Add an extension point to show a small banner next to the search bar Fix gr-group-audit-log to use tbody Change-Id: Iaf877b737f115d4fe95af74f8284eec19112a21d
295 lines
8.4 KiB
JavaScript
295 lines
8.4 KiB
JavaScript
/**
|
|
* @license
|
|
* 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 MAX_AUTOCOMPLETE_RESULTS = 20;
|
|
|
|
const RANGE_NAMES = [
|
|
'QUERY LIMIT',
|
|
'BATCH CHANGES LIMIT',
|
|
];
|
|
|
|
/**
|
|
* Fired when the permission has been modified or removed.
|
|
*
|
|
* @event access-modified
|
|
*/
|
|
|
|
/**
|
|
* Fired when a permission that was previously added was removed.
|
|
* @event added-permission-removed
|
|
*/
|
|
|
|
Polymer({
|
|
is: 'gr-permission',
|
|
|
|
properties: {
|
|
labels: Object,
|
|
name: String,
|
|
/** @type {?} */
|
|
permission: {
|
|
type: Object,
|
|
observer: '_sortPermission',
|
|
notify: true,
|
|
},
|
|
groups: Object,
|
|
section: String,
|
|
editing: {
|
|
type: Boolean,
|
|
value: false,
|
|
observer: '_handleEditingChanged',
|
|
},
|
|
_label: {
|
|
type: Object,
|
|
computed: '_computeLabel(permission, labels)',
|
|
},
|
|
_groupFilter: String,
|
|
_query: {
|
|
type: Function,
|
|
value() {
|
|
return this._getGroupSuggestions.bind(this);
|
|
},
|
|
},
|
|
_rules: Array,
|
|
_groupsWithRules: Object,
|
|
_deleted: {
|
|
type: Boolean,
|
|
value: false,
|
|
},
|
|
_originalExclusiveValue: Boolean,
|
|
},
|
|
|
|
behaviors: [
|
|
Gerrit.AccessBehavior,
|
|
/**
|
|
* Unused in this element, but called by other elements in tests
|
|
* e.g gr-access-section_test.
|
|
*/
|
|
Gerrit.FireBehavior,
|
|
],
|
|
|
|
observers: [
|
|
'_handleRulesChanged(_rules.splices)',
|
|
],
|
|
|
|
listeners: {
|
|
'access-saved': '_handleAccessSaved',
|
|
},
|
|
|
|
ready() {
|
|
this._setupValues();
|
|
},
|
|
|
|
_setupValues() {
|
|
if (!this.permission) { return; }
|
|
this._originalExclusiveValue = !!this.permission.value.exclusive;
|
|
Polymer.dom.flush();
|
|
},
|
|
|
|
_handleAccessSaved() {
|
|
// Set a new 'original' value to keep track of after the value has been
|
|
// saved.
|
|
this._setupValues();
|
|
},
|
|
|
|
_permissionIsOwnerOrGlobal(permissionId, section) {
|
|
return permissionId === 'owner' || section === 'GLOBAL_CAPABILITIES';
|
|
},
|
|
|
|
_handleEditingChanged(editing, editingOld) {
|
|
// Ignore when editing gets set initially.
|
|
if (!editingOld) { return; }
|
|
// Restore original values if no longer editing.
|
|
if (!editing) {
|
|
this._deleted = false;
|
|
delete this.permission.value.deleted;
|
|
this._groupFilter = '';
|
|
this._rules = this._rules.filter(rule => !rule.value.added);
|
|
for (const key of Object.keys(this.permission.value.rules)) {
|
|
if (this.permission.value.rules[key].added) {
|
|
delete this.permission.value.rules[key];
|
|
}
|
|
}
|
|
|
|
// Restore exclusive bit to original.
|
|
this.set(['permission', 'value', 'exclusive'],
|
|
this._originalExclusiveValue);
|
|
}
|
|
},
|
|
|
|
_handleAddedRuleRemoved(e) {
|
|
const index = e.model.index;
|
|
this._rules = this._rules.slice(0, index)
|
|
.concat(this._rules.slice(index + 1, this._rules.length));
|
|
},
|
|
|
|
_handleValueChange() {
|
|
this.permission.value.modified = true;
|
|
// Allows overall access page to know a change has been made.
|
|
this.dispatchEvent(
|
|
new CustomEvent('access-modified', {bubbles: true, composed: true}));
|
|
},
|
|
|
|
_handleRemovePermission() {
|
|
if (this.permission.value.added) {
|
|
this.dispatchEvent(new CustomEvent(
|
|
'added-permission-removed', {bubbles: true, composed: true}));
|
|
}
|
|
this._deleted = true;
|
|
this.permission.value.deleted = true;
|
|
this.dispatchEvent(
|
|
new CustomEvent('access-modified', {bubbles: true, composed: true}));
|
|
},
|
|
|
|
_handleRulesChanged(changeRecord) {
|
|
// Update the groups to exclude in the autocomplete.
|
|
this._groupsWithRules = this._computeGroupsWithRules(this._rules);
|
|
},
|
|
|
|
_sortPermission(permission) {
|
|
this._rules = this.toSortedArray(permission.value.rules);
|
|
},
|
|
|
|
_computeSectionClass(editing, deleted) {
|
|
const classList = [];
|
|
if (editing) {
|
|
classList.push('editing');
|
|
}
|
|
if (deleted) {
|
|
classList.push('deleted');
|
|
}
|
|
return classList.join(' ');
|
|
},
|
|
|
|
_handleUndoRemove() {
|
|
this._deleted = false;
|
|
delete this.permission.value.deleted;
|
|
},
|
|
|
|
_computeLabel(permission, labels) {
|
|
if (!labels || !permission ||
|
|
!permission.value || !permission.value.label) { return; }
|
|
|
|
const labelName = permission.value.label;
|
|
|
|
// It is possible to have a label name that is not included in the
|
|
// 'labels' object. In this case, treat it like anything else.
|
|
if (!labels[labelName]) { return; }
|
|
const label = {
|
|
name: labelName,
|
|
values: this._computeLabelValues(labels[labelName].values),
|
|
};
|
|
return label;
|
|
},
|
|
|
|
_computeLabelValues(values) {
|
|
const valuesArr = [];
|
|
const keys = Object.keys(values).sort((a, b) => {
|
|
return parseInt(a, 10) - parseInt(b, 10);
|
|
});
|
|
|
|
for (const key of keys) {
|
|
let text = values[key];
|
|
if (!text) { text = ''; }
|
|
// The value from the server being used to choose which item is
|
|
// selected is in integer form, so this must be converted.
|
|
valuesArr.push({value: parseInt(key, 10), text});
|
|
}
|
|
return valuesArr;
|
|
},
|
|
|
|
/**
|
|
* @param {!Array} rules
|
|
* @return {!Object} Object with groups with rues as keys, and true as
|
|
* value.
|
|
*/
|
|
_computeGroupsWithRules(rules) {
|
|
const groups = {};
|
|
for (const rule of rules) {
|
|
groups[rule.id] = true;
|
|
}
|
|
return groups;
|
|
},
|
|
|
|
_computeGroupName(groups, groupId) {
|
|
return groups && groups[groupId] && groups[groupId].name ?
|
|
groups[groupId].name : groupId;
|
|
},
|
|
|
|
_getGroupSuggestions() {
|
|
return this.$.restAPI.getSuggestedGroups(
|
|
this._groupFilter,
|
|
MAX_AUTOCOMPLETE_RESULTS)
|
|
.then(response => {
|
|
const groups = [];
|
|
for (const key in response) {
|
|
if (!response.hasOwnProperty(key)) { continue; }
|
|
groups.push({
|
|
name: key,
|
|
value: response[key],
|
|
});
|
|
}
|
|
// Does not return groups in which we already have rules for.
|
|
return groups.filter(group => {
|
|
return !this._groupsWithRules[group.value.id];
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Handles adding a skeleton item to the dom-repeat.
|
|
* gr-rule-editor handles setting the default values.
|
|
*/
|
|
_handleAddRuleItem(e) {
|
|
// The group id is encoded, but have to decode in order for the access
|
|
// API to work as expected.
|
|
const groupId = decodeURIComponent(e.detail.value.id).replace(/\+/g, ' ');
|
|
this.set(['permission', 'value', 'rules', groupId], {});
|
|
|
|
// Purposely don't recompute sorted array so that the newly added rule
|
|
// is the last item of the array.
|
|
this.push('_rules', {
|
|
id: groupId,
|
|
});
|
|
|
|
// Add the new group name to the groups object so the name renders
|
|
// correctly.
|
|
if (this.groups && !this.groups[groupId]) {
|
|
this.groups[groupId] = {name: this.$.groupAutocomplete.text};
|
|
}
|
|
|
|
// Wait for new rule to get value populated via gr-rule-editor, and then
|
|
// add to permission values as well, so that the change gets propogated
|
|
// back to the section. Since the rule is inside a dom-repeat, a flush
|
|
// is needed.
|
|
Polymer.dom.flush();
|
|
const value = this._rules[this._rules.length - 1].value;
|
|
value.added = true;
|
|
this.set(['permission', 'value', 'rules', groupId], value);
|
|
this.dispatchEvent(
|
|
new CustomEvent('access-modified', {bubbles: true, composed: true}));
|
|
},
|
|
|
|
_computeHasRange(name) {
|
|
if (!name) { return false; }
|
|
|
|
return RANGE_NAMES.includes(name.toUpperCase());
|
|
},
|
|
});
|
|
})();
|