blob: 39dadcc5b80f70c292d42f9d23502a298fa04c22 [file] [log] [blame]
// Copyright (C) 2011 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.
package com.google.gerrit.client.admin;
import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.groups.GroupMap;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupInfo;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.ProjectAccess;
import com.google.gerrit.common.data.RefConfigSection;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorDelegate;
import com.google.gwt.editor.client.ValueAwareEditor;
import com.google.gwt.editor.client.adapters.EditorSource;
import com.google.gwt.editor.client.adapters.ListEditor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.ValueLabel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class PermissionEditor extends Composite
implements Editor<Permission>, ValueAwareEditor<Permission> {
interface Binder extends UiBinder<HTMLPanel, PermissionEditor> {}
private static final Binder uiBinder = GWT.create(Binder.class);
@UiField(provided = true)
@Path("name")
ValueLabel<String> normalName;
@UiField(provided = true)
@Path("name")
ValueLabel<String> deletedName;
@UiField CheckBox exclusiveGroup;
@UiField FlowPanel ruleContainer;
ListEditor<PermissionRule, PermissionRuleEditor> rules;
@UiField DivElement addContainer;
@UiField DivElement addStage1;
@UiField DivElement addStage2;
@UiField Anchor beginAddRule;
@UiField @Editor.Ignore GroupReferenceBox groupToAdd;
@UiField Button addRule;
@UiField Anchor deletePermission;
@UiField DivElement normal;
@UiField DivElement deleted;
private final Project.NameKey projectName;
private final Map<AccountGroup.UUID, GroupInfo> groupInfo;
private final boolean readOnly;
private final AccessSection section;
private final LabelTypes labelTypes;
private Permission value;
private PermissionRange.WithDefaults validRange;
private boolean isDeleted;
public PermissionEditor(
ProjectAccess projectAccess, boolean readOnly, AccessSection section, LabelTypes labelTypes) {
this.readOnly = readOnly;
this.section = section;
this.projectName = projectAccess.getProjectName();
this.groupInfo = projectAccess.getGroupInfo();
this.labelTypes = labelTypes;
PermissionNameRenderer nameRenderer =
new PermissionNameRenderer(projectAccess.getCapabilities());
normalName = new ValueLabel<>(nameRenderer);
deletedName = new ValueLabel<>(nameRenderer);
initWidget(uiBinder.createAndBindUi(this));
groupToAdd.setProject(projectName);
rules = ListEditor.of(new RuleEditorSource());
exclusiveGroup.setEnabled(!readOnly);
exclusiveGroup.setVisible(RefConfigSection.isValid(section.getName()));
if (readOnly) {
addContainer.removeFromParent();
addContainer = null;
deletePermission.removeFromParent();
deletePermission = null;
}
}
@UiHandler("deletePermission")
void onDeleteHover(@SuppressWarnings("unused") MouseOverEvent event) {
addStyleName(AdminResources.I.css().deleteSectionHover());
}
@UiHandler("deletePermission")
void onDeleteNonHover(@SuppressWarnings("unused") MouseOutEvent event) {
removeStyleName(AdminResources.I.css().deleteSectionHover());
}
@UiHandler("deletePermission")
void onDeletePermission(@SuppressWarnings("unused") ClickEvent event) {
isDeleted = true;
normal.getStyle().setDisplay(Display.NONE);
deleted.getStyle().setDisplay(Display.BLOCK);
}
@UiHandler("undoDelete")
void onUndoDelete(@SuppressWarnings("unused") ClickEvent event) {
isDeleted = false;
deleted.getStyle().setDisplay(Display.NONE);
normal.getStyle().setDisplay(Display.BLOCK);
}
@UiHandler("beginAddRule")
void onBeginAddRule(@SuppressWarnings("unused") ClickEvent event) {
beginAddRule();
}
void beginAddRule() {
addStage1.getStyle().setDisplay(Display.NONE);
addStage2.getStyle().setDisplay(Display.BLOCK);
Scheduler.get()
.scheduleDeferred(
new ScheduledCommand() {
@Override
public void execute() {
groupToAdd.setFocus(true);
}
});
}
@UiHandler("addRule")
void onAddGroupByClick(@SuppressWarnings("unused") ClickEvent event) {
GroupReference ref = groupToAdd.getValue();
if (ref != null) {
addGroup(ref);
} else {
groupToAdd.setFocus(true);
}
}
@UiHandler("groupToAdd")
void onAddGroupByEnter(SelectionEvent<GroupReference> event) {
GroupReference ref = event.getSelectedItem();
if (ref != null) {
addGroup(ref);
}
}
@UiHandler("groupToAdd")
void onAbortAddGroup(@SuppressWarnings("unused") CloseEvent<GroupReferenceBox> event) {
hideAddGroup();
}
@UiHandler("hideAddGroup")
void hideAddGroup(@SuppressWarnings("unused") ClickEvent event) {
hideAddGroup();
}
private void hideAddGroup() {
addStage1.getStyle().setDisplay(Display.BLOCK);
addStage2.getStyle().setDisplay(Display.NONE);
}
private void addGroup(GroupReference ref) {
if (ref.getUUID() != null) {
if (value.getRule(ref) == null) {
PermissionRule newRule = value.getRule(ref, true);
if (validRange != null) {
int min = validRange.getDefaultMin();
int max = validRange.getDefaultMax();
newRule.setRange(min, max);
} else if (GlobalCapability.PRIORITY.equals(value.getName())) {
newRule.setAction(PermissionRule.Action.BATCH);
}
rules.getList().add(newRule);
}
groupToAdd.setValue(null);
groupToAdd.setFocus(true);
} else {
// If the oracle didn't get to complete a UUID, resolve it now.
//
addRule.setEnabled(false);
GroupMap.suggestAccountGroupForProject(
projectName.get(),
ref.getName(),
1,
new GerritCallback<GroupMap>() {
@Override
public void onSuccess(GroupMap result) {
addRule.setEnabled(true);
if (result.values().length() == 1) {
addGroup(
new GroupReference(
result.values().get(0).getGroupUUID(), result.values().get(0).name()));
} else {
groupToAdd.setFocus(true);
new ErrorDialog(Gerrit.M.noSuchGroupMessage(ref.getName())).center();
}
}
@Override
public void onFailure(Throwable caught) {
addRule.setEnabled(true);
super.onFailure(caught);
}
});
}
}
boolean isDeleted() {
return isDeleted;
}
@Override
public void setValue(Permission value) {
this.value = value;
if (Permission.hasRange(value.getName())) {
LabelType lt = labelTypes.byLabel(value.getLabel());
if (lt != null) {
validRange =
new PermissionRange.WithDefaults(
value.getName(),
lt.getMin().getValue(),
lt.getMax().getValue(),
lt.getMin().getValue(),
lt.getMax().getValue());
}
} else if (GlobalCapability.isGlobalCapability(value.getName())) {
validRange = GlobalCapability.getRange(value.getName());
} else {
validRange = null;
}
if (Permission.OWNER.equals(value.getName())) {
exclusiveGroup.setEnabled(false);
} else {
exclusiveGroup.setEnabled(!readOnly);
}
}
@Override
public void flush() {
List<PermissionRule> src = rules.getList();
List<PermissionRule> keep = new ArrayList<>(src.size());
for (int i = 0; i < src.size(); i++) {
PermissionRuleEditor e = (PermissionRuleEditor) ruleContainer.getWidget(i);
if (!e.isDeleted()) {
keep.add(src.get(i));
}
}
value.setRules(keep);
}
@Override
public void onPropertyChange(String... paths) {}
@Override
public void setDelegate(EditorDelegate<Permission> delegate) {}
private class RuleEditorSource extends EditorSource<PermissionRuleEditor> {
@Override
public PermissionRuleEditor create(int index) {
PermissionRuleEditor subEditor =
new PermissionRuleEditor(readOnly, groupInfo, section, value, validRange);
ruleContainer.insert(subEditor, index);
return subEditor;
}
@Override
public void dispose(PermissionRuleEditor subEditor) {
subEditor.removeFromParent();
}
@Override
public void setIndex(PermissionRuleEditor subEditor, int index) {
ruleContainer.insert(subEditor, index);
}
}
}