Support creation of groups via REST

A new group can now be created by POST on '/groups/'. The WebUI was
adapted to create groups via REST.

Change-Id: Ib11150cc4aa7944c5e79fff194fe97797cb77de2
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2013-01-25 16:32:07 +01:00
parent b33d0985ef
commit 58ccec09df
8 changed files with 141 additions and 11 deletions

View File

@@ -20,12 +20,13 @@ import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.NotFoundScreen;
import com.google.gerrit.client.account.AccountCapabilities;
import com.google.gerrit.client.groups.GroupApi;
import com.google.gerrit.client.groups.GroupInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
@@ -106,9 +107,10 @@ public class CreateGroupScreen extends Screen {
}
addNew.setEnabled(false);
Util.GROUP_SVC.createGroup(newName, new GerritCallback<AccountGroup.Id>() {
public void onSuccess(final AccountGroup.Id result) {
History.newItem(Dispatcher.toGroup(result, AccountGroupScreen.MEMBERS));
GroupApi.createGroup(newName, new GerritCallback<GroupInfo>() {
public void onSuccess(final GroupInfo result) {
History.newItem(Dispatcher.toGroup(result.getGroupId(),
AccountGroupScreen.MEMBERS));
}
@Override

View File

@@ -31,6 +31,13 @@ import java.util.Set;
*/
public class GroupApi {
/** Create a new group */
public static void createGroup(String groupName, AsyncCallback<GroupInfo> cb) {
GroupInput in = GroupInput.create();
in.name(groupName);
new RestApi("/groups/").data(in).post(cb);
}
/** Add member to a group. */
public static void addMember(AccountGroup.UUID groupUUID,
String member, AsyncCallback<MemberInfo> cb) {
@@ -101,4 +108,15 @@ public class GroupApi {
protected MemberInput() {
}
}
private static class GroupInput extends JavaScriptObject {
final native void name(String n) /*-{ if(n)this.name=n; }-*/;
static GroupInput create() {
return (GroupInput) createObject();
}
protected GroupInput() {
}
}
}

View File

@@ -56,6 +56,6 @@ class CreateGroup extends Handler<AccountGroup.Id> {
final PerformCreateGroup performCreateGroup = performCreateGroupFactory.create();
final Account.Id me = user.getAccountId();
return performCreateGroup.createGroup(groupName, null, visibleToAll, null,
Collections.singleton(me), null);
Collections.singleton(me), null).getId();
}
}

View File

@@ -84,7 +84,7 @@ public class PerformCreateGroup {
* name already exists
* @throws PermissionDeniedException user cannot create a group.
*/
public AccountGroup.Id createGroup(final String groupName,
public AccountGroup createGroup(final String groupName,
final String groupDescription, final boolean visibleToAll,
final AccountGroup.Id ownerGroupId,
final Collection<? extends Account.Id> initialMembers,
@@ -133,7 +133,7 @@ public class PerformCreateGroup {
groupCache.onCreateGroup(nameKey);
return groupId;
return group;
}
private void addMembers(final AccountGroup.Id groupId,

View File

@@ -52,6 +52,7 @@ import com.google.gerrit.server.account.GroupIncludeCacheImpl;
import com.google.gerrit.server.account.GroupInfoCacheFactory;
import com.google.gerrit.server.account.IncludingGroupMembership;
import com.google.gerrit.server.account.InternalGroupBackend;
import com.google.gerrit.server.account.PerformCreateGroup;
import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.account.UniversalGroupBackend;
import com.google.gerrit.server.auth.AuthBackend;
@@ -159,6 +160,7 @@ public class GerritGlobalModule extends FactoryModule {
factory(ChangeQueryBuilder.Factory.class);
factory(GroupInfoCacheFactory.Factory.class);
factory(GroupDetailFactory.Factory.class);
factory(PerformCreateGroup.Factory.class);
factory(InternalUser.Factory.class);
factory(ProjectNode.Factory.class);
factory(ProjectState.Factory.class);

View File

@@ -20,7 +20,6 @@ import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.RequestCleanup;
import com.google.gerrit.server.account.GroupMembers;
import com.google.gerrit.server.account.PerformCreateGroup;
import com.google.gerrit.server.account.PerformRenameGroup;
import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
import com.google.gerrit.server.changedetail.PublishDraft;
@@ -79,7 +78,6 @@ public class GerritRequestModule extends FactoryModule {
factory(RemoveReviewer.Factory.class);
factory(MergedSender.Factory.class);
factory(MergeFailSender.Factory.class);
factory(PerformCreateGroup.Factory.class);
factory(PerformRenameGroup.Factory.class);
factory(GroupMembers.Factory.class);
factory(CreateProject.Factory.class);

View File

@@ -0,0 +1,90 @@
// Copyright (C) 2013 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.server.group;
import com.google.common.base.Strings;
import com.google.gerrit.common.data.GroupDescriptions;
import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.common.errors.PermissionDeniedException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.PerformCreateGroup;
import com.google.gerrit.server.group.CreateGroup.Input;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;
import org.eclipse.jgit.lib.Config;
import java.util.Collections;
public class CreateGroup implements RestModifyView<TopLevelResource, Input> {
static class Input {
@DefaultInput
String name;
}
private final PerformCreateGroup.Factory performCreateGroupFactory;
private final GroupCache groupCache;
private final Provider<CurrentUser> self;
final boolean visibleToAll;
CreateGroup(final PerformCreateGroup.Factory performCreateGroupFactory,
final GroupCache groupCache, final Provider<CurrentUser> self,
final Config cfg) {
this.performCreateGroupFactory = performCreateGroupFactory;
this.groupCache = groupCache;
this.self = self;
this.visibleToAll = cfg.getBoolean("groups", "newGroupsVisibleToAll", false);
}
@Override
public Class<Input> inputType() {
return Input.class;
}
@Override
public GroupInfo apply(TopLevelResource resource, Input input)
throws AuthException, BadRequestException, OrmException,
NameAlreadyUsedException {
final IdentifiedUser me = ((IdentifiedUser) self.get());
if (!me.getCapabilities().canCreateGroup()) {
throw new AuthException("Cannot create group");
}
if (input == null || Strings.isNullOrEmpty(input.name)) {
throw new BadRequestException("group name missing");
}
AccountGroup group = groupCache.get(new AccountGroup.NameKey(input.name));
if (group != null) {
return new GroupInfo(GroupDescriptions.forAccountGroup(group));
}
try {
group = performCreateGroupFactory.create().createGroup(input.name, null,
visibleToAll, null, Collections.singleton(me.getAccountId()), null);
} catch (PermissionDeniedException e) {
throw new AuthException(e.getMessage());
}
return new GroupInfo(GroupDescriptions.forAccountGroup(group));
}
}

View File

@@ -18,6 +18,7 @@ import com.google.common.collect.Iterables;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AcceptsPost;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestCollection;
@@ -28,32 +29,45 @@ import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.account.PerformCreateGroup;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.util.Url;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collection;
import org.eclipse.jgit.lib.Config;
public class GroupsCollection implements
RestCollection<TopLevelResource, GroupResource> {
RestCollection<TopLevelResource, GroupResource>,
AcceptsPost<TopLevelResource> {
private final DynamicMap<RestView<GroupResource>> views;
private final Provider<ListGroups> list;
private final GroupControl.Factory groupControlFactory;
private final GroupBackend groupBackend;
private final Provider<CurrentUser> self;
private final PerformCreateGroup.Factory performCreateGroupFactory;
private final GroupCache groupCache;
private final Config cfg;
@Inject
GroupsCollection(final DynamicMap<RestView<GroupResource>> views,
final Provider<ListGroups> list,
final GroupControl.Factory groupControlFactory,
final GroupBackend groupBackend,
final Provider<CurrentUser> self) {
final Provider<CurrentUser> self,
final PerformCreateGroup.Factory performCreateGroupFactory,
final GroupCache groupCache, @GerritServerConfig final Config cfg) {
this.views = views;
this.list = list;
this.groupControlFactory = groupControlFactory;
this.groupBackend = groupBackend;
this.self = self;
this.performCreateGroupFactory = performCreateGroupFactory;
this.groupCache = groupCache;
this.cfg = cfg;
}
@Override
@@ -120,6 +134,12 @@ public class GroupsCollection implements
throw new ResourceNotFoundException(urlId);
}
@SuppressWarnings("unchecked")
@Override
public CreateGroup post(TopLevelResource parent) {
return new CreateGroup(performCreateGroupFactory, groupCache, self, cfg);
}
@Override
public DynamicMap<RestView<GroupResource>> views() {
return views;