]> source.dussan.org Git - sonarqube.git/commitdiff
Add template package in the permission.ws package
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 7 Sep 2015 15:00:10 +0000 (17:00 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 28 Sep 2015 14:34:54 +0000 (16:34 +0200)
71 files changed:
server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupToTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/ApplyTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/CreateTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/DefaultPermissionTemplateFinder.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/DeleteTemplateAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionChangeBuilder.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionDependenciesFinder.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionQueryParser.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionTemplateDtoBuilder.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionTemplateDtoToPermissionTemplateResponse.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupFromTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/ResourceTypeToQualifier.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesData.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesDataLoader.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SetDefaultTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/UpdateTemplateAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/WsGroupRef.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/WsPermissionParameters.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/WsProjectRef.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/WsTemplateRef.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddGroupToTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddUserToTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/ApplyTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/CreateTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/DefaultPermissionTemplateFinder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/PermissionTemplateDtoBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/PermissionTemplateDtoToPermissionTemplateResponse.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/RemoveGroupFromTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/RemoveUserFromTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesData.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesDataLoader.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/UpdateTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/package-info.java [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/create_template-example.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/search_templates-example.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/create_template-example.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/search_templates-example.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/update_template-example.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/update_template-example.json [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/ApplyTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/CreateTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/DefaultPermissionTemplateFinderTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/DeleteTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupFromTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchTemplatesActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/SetDefaultTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/UpdateTemplateActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddGroupToTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddUserToTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/CreateTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DefaultPermissionTemplateFinderTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveGroupFromTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveUserFromTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SearchTemplatesActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/UpdateTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/permission/ws/SearchTemplatesActionTest/empty.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/permission/ws/template/SearchTemplatesActionTest/empty.json [new file with mode: 0644]

diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupToTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupToTemplateAction.java
deleted file mode 100644 (file)
index 741b4dc..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import javax.annotation.Nullable;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionQuery;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.server.user.UserSession;
-
-import static org.sonar.api.security.DefaultGroups.ANYONE;
-import static org.sonar.db.user.GroupMembershipQuery.IN;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupIdParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupNameParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateNotAnyoneAndAdminPermission;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
-
-public class AddGroupToTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final PermissionDependenciesFinder dependenciesFinder;
-  private final UserSession userSession;
-
-  public AddGroupToTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.dependenciesFinder = dependenciesFinder;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context
-      .createAction("add_group_to_template")
-      .setPost(true)
-      .setSince("5.2")
-      .setDescription("Add a group to a permission template.<br /> " +
-        "The group id or group name must be provided. <br />" +
-        "It requires administration permissions to access.")
-      .setHandler(this);
-
-    createTemplateParameters(action);
-    createProjectPermissionParameter(action);
-    createGroupIdParameter(action);
-    createGroupNameParameter(action);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    checkGlobalAdminUser(userSession);
-
-    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
-    WsGroupRef group = WsGroupRef.fromRequest(wsRequest);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      validateProjectPermission(permission);
-      validateNotAnyoneAndAdminPermission(permission, group.name());
-
-      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
-      GroupDto groupDto = dependenciesFinder.getGroup(dbSession, group);
-
-      if (!groupAlreadyAdded(dbSession, template.getId(), groupDto, permission)) {
-        Long groupId = groupDto == null ? null : groupDto.getId();
-        dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getId(), groupId, permission);
-      }
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-
-    wsResponse.noContent();
-  }
-
-  private boolean groupAlreadyAdded(DbSession dbSession, long templateId, @Nullable GroupDto group, String permission) {
-    String groupName = group == null ? ANYONE : group.getName();
-    PermissionQuery permissionQuery = PermissionQuery.builder().membership(IN).permission(permission).build();
-    return dbClient.permissionTemplateDao().hasGroup(dbSession, permissionQuery, templateId, groupName);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java
deleted file mode 100644 (file)
index 16a2f53..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Predicate;
-import java.util.List;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionQuery;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.permission.UserWithPermissionDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.user.UserSession;
-
-import static com.google.common.collect.FluentIterable.from;
-import static org.sonar.db.user.GroupMembershipQuery.IN;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createUserLoginParameter;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
-
-public class AddUserToTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final PermissionDependenciesFinder dependenciesFinder;
-  private final UserSession userSession;
-
-  public AddUserToTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.dependenciesFinder = dependenciesFinder;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context
-      .createAction("add_user_to_template")
-      .setPost(true)
-      .setSince("5.2")
-      .setDescription("Add a user to a permission template.<br /> " +
-        "It requires administration permissions to access.")
-      .setHandler(this);
-
-    createTemplateParameters(action);
-    createProjectPermissionParameter(action);
-    createUserLoginParameter(action);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    checkGlobalAdminUser(userSession);
-
-    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
-    final String userLogin = wsRequest.mandatoryParam(PARAM_USER_LOGIN);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      validateProjectPermission(permission);
-      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
-      UserDto user = dependenciesFinder.getUser(dbSession, userLogin);
-
-      if (!isUserAlreadyAdded(dbSession, template.getId(), userLogin, permission)) {
-        dbClient.permissionTemplateDao().insertUserPermission(dbSession, template.getId(), user.getId(), permission);
-      }
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-
-    wsResponse.noContent();
-  }
-
-  private boolean isUserAlreadyAdded(DbSession dbSession, long templateId, String userLogin, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
-    List<UserWithPermissionDto> usersWithPermission = dbClient.permissionTemplateDao().selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE);
-    return from(usersWithPermission).anyMatch(new HasUserPredicate(userLogin));
-  }
-
-  private static class HasUserPredicate implements Predicate<UserWithPermissionDto> {
-    private final String userLogin;
-
-    public HasUserPredicate(String userLogin) {
-      this.userLogin = userLogin;
-    }
-
-    @Override
-    public boolean apply(UserWithPermissionDto userWithPermission) {
-      return userLogin.equals(userWithPermission.getLogin());
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/ApplyTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/ApplyTemplateAction.java
deleted file mode 100644 (file)
index 7556a66..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.permission.ApplyPermissionTemplateQuery;
-import org.sonar.server.permission.PermissionService;
-
-import static java.util.Collections.singletonList;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
-
-public class ApplyTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final PermissionService permissionService;
-  private final PermissionDependenciesFinder finder;
-
-  public ApplyTemplateAction(DbClient dbClient, PermissionService permissionService, PermissionDependenciesFinder finder) {
-    this.dbClient = dbClient;
-    this.permissionService = permissionService;
-    this.finder = finder;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context.createAction("apply_template")
-      .setDescription("Apply a permission template to one or several projects.<br />" +
-        "The project id or project key must be provided.<br />" +
-        "It requires administration permissions to access.")
-      .setPost(true)
-      .setSince("5.2")
-      .setHandler(this);
-
-    createTemplateParameters(action);
-    createProjectParameter(action);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      PermissionTemplateDto template = finder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
-      ComponentDto project = finder.getProject(dbSession, WsProjectRef.fromRequest(wsRequest));
-
-      ApplyPermissionTemplateQuery query = ApplyPermissionTemplateQuery.create(
-        template.getUuid(),
-        singletonList(project.key()));
-      permissionService.applyPermissionTemplate(query);
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-
-    wsResponse.noContent();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/CreateTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/CreateTemplateAction.java
deleted file mode 100644 (file)
index 69f2f6f..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.WsPermissions.PermissionTemplate;
-import org.sonarqube.ws.WsPermissions.WsCreatePermissionTemplateResponse;
-
-import static java.lang.String.format;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateDescriptionParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateProjectKeyPatternParameter;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.MSG_TEMPLATE_WITH_SAME_NAME;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPattern;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateTemplateNameFormat;
-import static org.sonar.server.permission.ws.PermissionTemplateDtoBuilder.create;
-import static org.sonar.server.permission.ws.PermissionTemplateDtoToPermissionTemplateResponse.toPermissionTemplateResponse;
-import static org.sonar.server.ws.WsUtils.checkRequest;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
-
-public class CreateTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final UserSession userSession;
-  private final System2 system;
-
-  public CreateTemplateAction(DbClient dbClient, UserSession userSession, System2 system) {
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-    this.system = system;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context.createAction("create_template")
-      .setDescription("Create a permission template.<br />" +
-        "It requires administration permissions to access.")
-      .setResponseExample(getClass().getResource("create_template-example.json"))
-      .setSince("5.2")
-      .setPost(true)
-      .setHandler(this);
-
-    action.createParam(PARAM_NAME)
-      .setRequired(true)
-      .setDescription("Name")
-      .setExampleValue("Financial Service Permissions");
-
-    createTemplateProjectKeyPatternParameter(action);
-    createTemplateDescriptionParameter(action);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    String name = wsRequest.mandatoryParam(PARAM_NAME);
-    String description = wsRequest.param(PARAM_DESCRIPTION);
-    String projectPattern = wsRequest.param(PARAM_PATTERN);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      checkGlobalAdminUser(userSession);
-      validateTemplateNameForCreation(dbSession, name);
-      validateProjectPattern(projectPattern);
-
-      PermissionTemplateDto permissionTemplate = insertTemplate(dbSession, name, description, projectPattern);
-
-      WsCreatePermissionTemplateResponse response = buildResponse(permissionTemplate);
-      writeProtobuf(response, wsRequest, wsResponse);
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-  }
-
-  private void validateTemplateNameForCreation(DbSession dbSession, String name) {
-    validateTemplateNameFormat(name);
-
-    PermissionTemplateDto permissionTemplateWithSameName = dbClient.permissionTemplateDao().selectByName(dbSession, name);
-    checkRequest(permissionTemplateWithSameName == null, format(MSG_TEMPLATE_WITH_SAME_NAME, name));
-  }
-
-  private PermissionTemplateDto insertTemplate(DbSession dbSession, String name, String description, String projectPattern) {
-    PermissionTemplateDto template = dbClient.permissionTemplateDao().insert(dbSession, create(system)
-      .setName(name)
-      .setDescription(description)
-      .setProjectKeyPattern(projectPattern)
-      .toDto());
-    dbSession.commit();
-    return template;
-  }
-
-  private static WsCreatePermissionTemplateResponse buildResponse(PermissionTemplateDto permissionTemplateDto) {
-    PermissionTemplate permissionTemplateBuilder = toPermissionTemplateResponse(permissionTemplateDto);
-    return WsCreatePermissionTemplateResponse.newBuilder().setPermissionTemplate(permissionTemplateBuilder).build();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/DefaultPermissionTemplateFinder.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/DefaultPermissionTemplateFinder.java
deleted file mode 100644 (file)
index d1381b4..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Function;
-import java.util.List;
-import java.util.Set;
-import javax.annotation.Nonnull;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceTypes;
-
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Ordering.natural;
-import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
-import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
-import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
-
-public class DefaultPermissionTemplateFinder {
-  private final Settings settings;
-  private final ResourceTypes resourceTypes;
-
-  public DefaultPermissionTemplateFinder(Settings settings, ResourceTypes resourceTypes) {
-    this.settings = settings;
-    this.resourceTypes = resourceTypes;
-  }
-
-  Set<String> getDefaultTemplateUuids() {
-    return from(resourceTypes.getRoots())
-      .transform(RESOURCE_TYPE_TO_QUALIFIER)
-      .transform(new QualifierToDefaultTemplate(settings))
-      .toSortedSet(natural());
-  }
-
-  List<TemplateUuidQualifier> getDefaultTemplatesByQualifier() {
-    return from(resourceTypes.getRoots())
-      .transform(RESOURCE_TYPE_TO_QUALIFIER)
-      .transform(new QualifierToTemplateUuidQualifier(settings))
-      .toList();
-  }
-
-  static class TemplateUuidQualifier {
-    private final String templateUuid;
-    private final String qualifier;
-
-    TemplateUuidQualifier(String templateUuid, String qualifier) {
-      this.templateUuid = templateUuid;
-      this.qualifier = qualifier;
-    }
-
-    public String getTemplateUuid() {
-      return templateUuid;
-    }
-
-    public String getQualifier() {
-      return qualifier;
-    }
-  }
-
-  private static class QualifierToDefaultTemplate implements Function<String, String> {
-    private final Settings settings;
-
-    QualifierToDefaultTemplate(Settings settings) {
-      this.settings = settings;
-    }
-
-    @Override
-    public String apply(@Nonnull String qualifier) {
-      String effectiveTemplateUuid = effectiveTemplateUuid(settings, qualifier);
-      return effectiveTemplateUuid;
-    }
-  }
-
-  private static class QualifierToTemplateUuidQualifier implements Function<String, TemplateUuidQualifier> {
-    private final Settings settings;
-
-    QualifierToTemplateUuidQualifier(Settings settings) {
-      this.settings = settings;
-    }
-
-    @Override
-    public TemplateUuidQualifier apply(@Nonnull String qualifier) {
-      String effectiveTemplateUuid = effectiveTemplateUuid(settings, qualifier);
-
-      return new TemplateUuidQualifier(effectiveTemplateUuid, qualifier);
-    }
-  }
-
-  private static String effectiveTemplateUuid(Settings settings, String qualifier) {
-    String qualifierTemplateUuid = settings.getString(defaultRootQualifierTemplateProperty(qualifier));
-    String projectTemplateUuid = settings.getString(defaultRootQualifierTemplateProperty(Qualifiers.PROJECT));
-    String defaultTemplateUuid = settings.getString(DEFAULT_TEMPLATE_PROPERTY);
-
-    if (qualifierTemplateUuid != null) {
-      return qualifierTemplateUuid;
-    } else if (projectTemplateUuid != null) {
-      return projectTemplateUuid;
-    } else {
-      return defaultTemplateUuid;
-    }
-  }
-
-}
index 4acc8fcdff699a7bd81e52e79a9b31cdbf76c8ab..4813560a92cf658451408fc662147bee7a408685 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ws.template.DefaultPermissionTemplateFinder;
 import org.sonar.server.user.UserSession;
 
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
index 2049200bbe48e8526c569bca3468339f024e2924..3418bfe041301d34df4219237235b19437b75eed 100644 (file)
@@ -33,7 +33,7 @@ public class PermissionChangeBuilder {
     this.dependenciesFinder = dependenciesFinder;
   }
 
-  PermissionChange buildUserPermissionChange(DbSession dbSession, PermissionRequest request) {
+  public PermissionChange buildUserPermissionChange(DbSession dbSession, PermissionRequest request) {
     PermissionChange permissionChange = new PermissionChange()
       .setPermission(request.permission())
       .setUserLogin(request.userLogin());
@@ -42,7 +42,7 @@ public class PermissionChangeBuilder {
     return permissionChange;
   }
 
-  PermissionChange buildGroupPermissionChange(DbSession dbSession, PermissionRequest request) {
+  public PermissionChange buildGroupPermissionChange(DbSession dbSession, PermissionRequest request) {
     String groupName = dependenciesFinder.getGroupName(dbSession, request);
 
     PermissionChange permissionChange = new PermissionChange()
index fd56efbd8b0e94be2df2a6168553fbea8b11e03d..9838e66f73364aac1fea8f65a791c1d35f26e367 100644 (file)
@@ -47,7 +47,7 @@ public class PermissionDependenciesFinder {
   /**
    * @throws org.sonar.server.exceptions.NotFoundException if a project identifier is provided but it's not found
    */
-  Optional<ComponentDto> searchProject(DbSession dbSession, PermissionRequest request) {
+  public Optional<ComponentDto> searchProject(DbSession dbSession, PermissionRequest request) {
     if (!request.project().isPresent()) {
       return Optional.absent();
     }
@@ -56,11 +56,11 @@ public class PermissionDependenciesFinder {
     return Optional.of(componentFinder.getProjectByUuidOrKey(dbSession, wsProjectRef.uuid(), wsProjectRef.key()));
   }
 
-  ComponentDto getProject(DbSession dbSession, WsProjectRef projectRef) {
+  public ComponentDto getProject(DbSession dbSession, WsProjectRef projectRef) {
     return componentFinder.getProjectByUuidOrKey(dbSession, projectRef.uuid(), projectRef.key());
   }
 
-  String getGroupName(DbSession dbSession, PermissionRequest request) {
+  public String getGroupName(DbSession dbSession, PermissionRequest request) {
     GroupDto group = getGroup(dbSession, request.group());
 
     return group == null ? ANYONE : group.getName();
@@ -71,7 +71,7 @@ public class PermissionDependenciesFinder {
    * @return null if it's the anyone group
    */
   @CheckForNull
-  GroupDto getGroup(DbSession dbSession, WsGroupRef group) {
+  public GroupDto getGroup(DbSession dbSession, WsGroupRef group) {
     Long groupId = group.id();
     String groupName = group.name();
 
@@ -94,12 +94,12 @@ public class PermissionDependenciesFinder {
     return groupDto;
   }
 
-  UserDto getUser(DbSession dbSession, String userLogin) {
+  public UserDto getUser(DbSession dbSession, String userLogin) {
     return checkFound(dbClient.userDao().selectActiveUserByLogin(dbSession, userLogin),
       format("User with login '%s' is not found'", userLogin));
   }
 
-  PermissionTemplateDto getTemplate(DbSession dbSession, WsTemplateRef template) {
+  public PermissionTemplateDto getTemplate(DbSession dbSession, WsTemplateRef template) {
     if (template.uuid() != null) {
       return checkFound(dbClient.permissionTemplateDao().selectByUuid(dbSession, template.uuid()),
         format("Permission template with id '%s' is not found", template.uuid()));
index 27f2c9b58c137a19007abafa405654f5ebd6177c..8f39e643329ace8c9fcfe0f2d33ba81b730530f9 100644 (file)
@@ -29,7 +29,7 @@ class PermissionQueryParser {
     // Utility class
   }
 
-  static String fromSelectionModeToMembership(String selectionModeString) {
+  public static String fromSelectionModeToMembership(String selectionModeString) {
     SelectionMode selectionMode = SelectionMode.fromParam(selectionModeString);
     if (SelectionMode.SELECTED == selectionMode) {
       return GroupMembershipQuery.IN;
index fcce33c3cd93f0e253e78a3b6e4dedfbce652075..11e48d6b1beb46ca89dc2de0e0fe979821459fa6 100644 (file)
@@ -54,7 +54,7 @@ class PermissionRequest {
     query = builder.query;
   }
 
-  static class Builder {
+  public static class Builder {
 
     private final Request request;
 
@@ -72,7 +72,7 @@ class PermissionRequest {
     private String selected;
     private String query;
 
-    Builder(Request request) {
+    public Builder(Request request) {
       this.request = request;
     }
 
@@ -89,17 +89,17 @@ class PermissionRequest {
       return new PermissionRequest(this);
     }
 
-    Builder withUser() {
+    public Builder withUser() {
       this.withUser = true;
       return this;
     }
 
-    Builder withGroup() {
+    public Builder withGroup() {
       this.withGroup = true;
       return this;
     }
 
-    Builder withPagination() {
+    public Builder withPagination() {
       this.withPagination = true;
       return this;
     }
@@ -151,35 +151,35 @@ class PermissionRequest {
     }
   }
 
-  String permission() {
+  public String permission() {
     return permission;
   }
 
-  String userLogin() {
+  public String userLogin() {
     return userLogin;
   }
 
-  WsGroupRef group() {
+  public WsGroupRef group() {
     return group;
   }
 
-  Optional<WsProjectRef> project() {
+  public Optional<WsProjectRef> project() {
     return project;
   }
 
-  Integer page() {
+  public Integer page() {
     return page;
   }
 
-  Integer pageSize() {
+  public Integer pageSize() {
     return pageSize;
   }
 
-  String selected() {
+  public String selected() {
     return selected;
   }
 
-  String query() {
+  public String query() {
     return query;
   }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionTemplateDtoBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionTemplateDtoBuilder.java
deleted file mode 100644 (file)
index 55702eb..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.Date;
-import org.sonar.api.utils.System2;
-import org.sonar.core.util.Uuids;
-import org.sonar.db.permission.PermissionTemplateDto;
-
-class PermissionTemplateDtoBuilder {
-  private final System2 system;
-  private String name;
-  private String description;
-  private String projectKeyPattern;
-
-  private PermissionTemplateDtoBuilder(System2 system) {
-    this.system = system;
-  }
-
-  static PermissionTemplateDtoBuilder create(System2 system) {
-    return new PermissionTemplateDtoBuilder(system);
-  }
-
-  PermissionTemplateDtoBuilder setName(String name) {
-    this.name = name;
-    return this;
-  }
-
-  PermissionTemplateDtoBuilder setDescription(String description) {
-    this.description = description;
-    return this;
-  }
-
-  PermissionTemplateDtoBuilder setProjectKeyPattern(String projectKeyPattern) {
-    this.projectKeyPattern = projectKeyPattern;
-    return this;
-  }
-
-  PermissionTemplateDto toDto() {
-    long now = system.now();
-    return new PermissionTemplateDto()
-      .setName(name)
-      .setDescription(description)
-      .setKeyPattern(projectKeyPattern)
-      .setKee(Uuids.create())
-      .setCreatedAt(new Date(now))
-      .setUpdatedAt(new Date(now));
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionTemplateDtoToPermissionTemplateResponse.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionTemplateDtoToPermissionTemplateResponse.java
deleted file mode 100644 (file)
index 1b9be42..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Function;
-import javax.annotation.Nonnull;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonarqube.ws.WsPermissions.PermissionTemplate;
-
-class PermissionTemplateDtoToPermissionTemplateResponse {
-
-  static PermissionTemplate toPermissionTemplateResponse(PermissionTemplateDto dto) {
-    return Singleton.INSTANCE.apply(dto);
-  }
-
-  private enum Singleton implements Function<PermissionTemplateDto, PermissionTemplate> {
-    INSTANCE;
-    @Override
-    public PermissionTemplate apply(@Nonnull PermissionTemplateDto permissionTemplate) {
-      PermissionTemplate.Builder permissionTemplateBuilder = PermissionTemplate.newBuilder()
-        .setId(permissionTemplate.getKee())
-        .setName(permissionTemplate.getName())
-        .setCreatedAt(DateUtils.formatDateTime(permissionTemplate.getCreatedAt()))
-        .setUpdatedAt(DateUtils.formatDateTime(permissionTemplate.getUpdatedAt()));
-      if (permissionTemplate.getDescription() != null) {
-        permissionTemplateBuilder.setDescription(permissionTemplate.getDescription());
-      }
-      if (permissionTemplate.getKeyPattern() != null) {
-        permissionTemplateBuilder.setProjectKeyPattern(permissionTemplate.getKeyPattern());
-      }
-      return permissionTemplateBuilder.build();
-    }
-  }
-}
index 9f9ed0213dc7d4b9d47bfd1e1060ee6a4f455596..957ef41e692218f61ad99efc31063a98a9c91262 100644 (file)
 package org.sonar.server.permission.ws;
 
 import org.sonar.core.platform.Module;
+import org.sonar.server.permission.ws.template.AddGroupToTemplateAction;
+import org.sonar.server.permission.ws.template.AddUserToTemplateAction;
+import org.sonar.server.permission.ws.template.ApplyTemplateAction;
+import org.sonar.server.permission.ws.template.CreateTemplateAction;
+import org.sonar.server.permission.ws.template.DefaultPermissionTemplateFinder;
+import org.sonar.server.permission.ws.template.RemoveGroupFromTemplateAction;
+import org.sonar.server.permission.ws.template.RemoveUserFromTemplateAction;
+import org.sonar.server.permission.ws.template.SearchTemplatesAction;
+import org.sonar.server.permission.ws.template.SearchTemplatesDataLoader;
+import org.sonar.server.permission.ws.template.SetDefaultTemplateAction;
+import org.sonar.server.permission.ws.template.UpdateTemplateAction;
 
 public class PermissionsWsModule extends Module {
   @Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupFromTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupFromTemplateAction.java
deleted file mode 100644 (file)
index 3661409..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.server.user.UserSession;
-
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupIdParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupNameParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
-
-public class RemoveGroupFromTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final PermissionDependenciesFinder dependenciesFinder;
-  private final UserSession userSession;
-
-  public RemoveGroupFromTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.dependenciesFinder = dependenciesFinder;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context
-      .createAction("remove_group_from_template")
-      .setPost(true)
-      .setSince("5.2")
-      .setDescription("Remove a group from a permission template.<br /> " +
-        "The group id or group name must be provided. <br />" +
-        "It requires administration permissions to access.")
-      .setHandler(this);
-
-    createTemplateParameters(action);
-    createProjectPermissionParameter(action);
-    createGroupIdParameter(action);
-    createGroupNameParameter(action);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    checkGlobalAdminUser(userSession);
-
-    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
-    WsGroupRef group = WsGroupRef.fromRequest(wsRequest);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      validateProjectPermission(permission);
-
-      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
-      GroupDto groupDto = dependenciesFinder.getGroup(dbSession, group);
-
-      Long groupId = groupDto == null ? null : groupDto.getId();
-      dbClient.permissionTemplateDao().deleteGroupPermission(dbSession, template.getId(), groupId, permission);
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-
-    wsResponse.noContent();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java
deleted file mode 100644 (file)
index dd22e79..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.user.UserSession;
-
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createUserLoginParameter;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
-
-public class RemoveUserFromTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final PermissionDependenciesFinder dependenciesFinder;
-  private final UserSession userSession;
-
-  public RemoveUserFromTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
-    this.dbClient = dbClient;
-    this.dependenciesFinder = dependenciesFinder;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context
-      .createAction("remove_user_from_template")
-      .setPost(true)
-      .setSince("5.2")
-      .setDescription("Remove a user from a permission template.<br /> " +
-        "It requires administration permissions to access.")
-      .setHandler(this);
-
-    createTemplateParameters(action);
-    createProjectPermissionParameter(action);
-    createUserLoginParameter(action);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    checkGlobalAdminUser(userSession);
-
-    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
-    String userLogin = wsRequest.mandatoryParam(PARAM_USER_LOGIN);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      validateProjectPermission(permission);
-      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
-      UserDto user = dependenciesFinder.getUser(dbSession, userLogin);
-
-      dbClient.permissionTemplateDao().deleteUserPermission(dbSession, template.getId(), user.getId(), permission);
-      dbSession.commit();
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-
-    wsResponse.noContent();
-  }
-}
index a751be79838d30d9ee819fb19c36a60986c4bcf2..8c850cbd33d01ed829a9aeff249f55b44e50032f 100644 (file)
@@ -24,9 +24,9 @@ import com.google.common.base.Function;
 import javax.annotation.Nonnull;
 import org.sonar.api.resources.ResourceType;
 
-class ResourceTypeToQualifier {
+public class ResourceTypeToQualifier {
 
-  static final Function<ResourceType, String> RESOURCE_TYPE_TO_QUALIFIER = Singleton.INSTANCE;
+  public static final Function<ResourceType, String> RESOURCE_TYPE_TO_QUALIFIER = Singleton.INSTANCE;
 
   private enum Singleton implements Function<ResourceType, String> {
     INSTANCE;
index a3785a785984993eefc3648b8c21674faa695e4f..a8489228ae691b776db4bf01536e0a15dab59889 100644 (file)
@@ -58,7 +58,7 @@ public class SearchProjectPermissionsDataLoader {
     this.rootQualifiers = Collections2.transform(resourceTypes.getRoots(), RESOURCE_TYPE_TO_QUALIFIER);
   }
 
-  public SearchProjectPermissionsData load(Request wsRequest) {
+  SearchProjectPermissionsData load(Request wsRequest) {
     DbSession dbSession = dbClient.openSession(false);
     try {
       SearchProjectPermissionsData.Builder data = newBuilder();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesAction.java
deleted file mode 100644 (file)
index 87abcb2..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.ProjectPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.WsPermissions.Permission;
-import org.sonarqube.ws.WsPermissions.PermissionTemplate;
-import org.sonarqube.ws.WsPermissions.WsSearchTemplatesResponse;
-import org.sonarqube.ws.WsPermissions.WsSearchTemplatesResponse.TemplateIdQualifier;
-
-import static org.sonar.api.utils.DateUtils.formatDateTime;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
-
-public class SearchTemplatesAction implements PermissionsWsAction {
-  private static final String PROPERTY_PREFIX = "projects_role.";
-  private static final String DESCRIPTION_SUFFIX = ".desc";
-
-  private final DbClient dbClient;
-  private final UserSession userSession;
-  private final I18n i18n;
-  private final SearchTemplatesDataLoader dataLoader;
-
-  public SearchTemplatesAction(DbClient dbClient, UserSession userSession, I18n i18n, SearchTemplatesDataLoader dataLoader) {
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-    this.i18n = i18n;
-    this.dataLoader = dataLoader;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    context.createAction("search_templates")
-      .setDescription("List permission templates.<br />" +
-        "It requires administration permissions to access.")
-      .setResponseExample(getClass().getResource("search_templates-example.json"))
-      .setSince("5.2")
-      .addSearchQuery("defau", "permission template names")
-      .setHandler(this);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    checkGlobalAdminUser(userSession);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      SearchTemplatesData data = dataLoader.load(wsRequest);
-      WsSearchTemplatesResponse response = buildResponse(data);
-      writeProtobuf(response, wsRequest, wsResponse);
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-  }
-
-  private WsSearchTemplatesResponse buildResponse(SearchTemplatesData data) {
-    WsSearchTemplatesResponse.Builder response = WsSearchTemplatesResponse.newBuilder();
-
-    buildTemplatesResponse(response, data);
-    buildDefaultTemplatesResponse(response, data);
-    buildPermissionsResponse(response);
-
-    return response.build();
-  }
-
-  private static void buildDefaultTemplatesResponse(WsSearchTemplatesResponse.Builder response, SearchTemplatesData data) {
-    TemplateIdQualifier.Builder templateUuidQualifierBuilder = TemplateIdQualifier.newBuilder();
-    for (DefaultPermissionTemplateFinder.TemplateUuidQualifier templateUuidQualifier : data.defaultTempltes()) {
-      response.addDefaultTemplates(templateUuidQualifierBuilder
-        .clear()
-        .setQualifier(templateUuidQualifier.getQualifier())
-        .setTemplateId(templateUuidQualifier.getTemplateUuid()));
-    }
-  }
-
-  private static void buildTemplatesResponse(WsSearchTemplatesResponse.Builder response, SearchTemplatesData data) {
-    Permission.Builder permissionResponse = Permission.newBuilder();
-    PermissionTemplate.Builder templateBuilder = PermissionTemplate.newBuilder();
-
-    for (PermissionTemplateDto templateDto : data.templates()) {
-      templateBuilder
-        .clear()
-        .setId(templateDto.getUuid())
-        .setName(templateDto.getName())
-        .setCreatedAt(formatDateTime(templateDto.getCreatedAt()))
-        .setUpdatedAt(formatDateTime(templateDto.getUpdatedAt()));
-      if (templateDto.getKeyPattern() != null) {
-        templateBuilder.setProjectKeyPattern(templateDto.getKeyPattern());
-      }
-      if (templateDto.getDescription() != null) {
-        templateBuilder.setDescription(templateDto.getDescription());
-      }
-      for (String permission : data.permissions(templateDto.getId())) {
-        templateBuilder.addPermissions(
-          permissionResponse
-            .clear()
-            .setKey(permission)
-            .setUsersCount(data.userCount(templateDto.getId(), permission))
-            .setGroupsCount(data.groupCount(templateDto.getId(), permission)));
-      }
-      response.addPermissionTemplates(templateBuilder);
-    }
-  }
-
-  private void buildPermissionsResponse(WsSearchTemplatesResponse.Builder response) {
-    Permission.Builder permissionResponse = Permission.newBuilder();
-    for (String permissionKey : ProjectPermissions.ALL) {
-      response.addPermissions(
-        permissionResponse
-          .clear()
-          .setKey(permissionKey)
-          .setName(i18nName(permissionKey))
-          .setDescription(i18nDescriptionMessage(permissionKey))
-        );
-    }
-  }
-
-  private String i18nDescriptionMessage(String permissionKey) {
-    return i18n.message(userSession.locale(), PROPERTY_PREFIX + permissionKey + DESCRIPTION_SUFFIX, "");
-  }
-
-  private String i18nName(String permissionKey) {
-    return i18n.message(userSession.locale(), PROPERTY_PREFIX + permissionKey, permissionKey);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesData.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesData.java
deleted file mode 100644 (file)
index dac2868..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Table;
-import java.util.List;
-import java.util.Set;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.permission.ws.DefaultPermissionTemplateFinder.TemplateUuidQualifier;
-
-import static com.google.common.base.Objects.firstNonNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.ImmutableList.copyOf;
-import static com.google.common.collect.ImmutableTable.copyOf;
-import static com.google.common.collect.Ordering.natural;
-
-class SearchTemplatesData {
-  private final List<PermissionTemplateDto> templates;
-  private final List<TemplateUuidQualifier> defaultTemplates;
-  private final Table<Long, String, Integer> userCountByTemplateIdAndPermission;
-  private final Table<Long, String, Integer> groupCountByTemplateIdAndPermission;
-
-  private SearchTemplatesData(Builder builder) {
-    this.templates = copyOf(builder.templates);
-    this.defaultTemplates = copyOf(builder.defaultTemplates);
-    this.userCountByTemplateIdAndPermission = copyOf(builder.userCountByTemplateIdAndPermission);
-    this.groupCountByTemplateIdAndPermission = copyOf(builder.groupCountByTemplateIdAndPermission);
-  }
-
-  public static Builder newBuilder() {
-    return new Builder();
-  }
-
-  public List<PermissionTemplateDto> templates() {
-    return templates;
-  }
-
-  public List<TemplateUuidQualifier> defaultTempltes() {
-    return defaultTemplates;
-  }
-
-  public int userCount(long templateId, String permission) {
-    return firstNonNull(userCountByTemplateIdAndPermission.get(templateId, permission), 0);
-  }
-
-  public int groupCount(long templateId, String permission) {
-    return firstNonNull(groupCountByTemplateIdAndPermission.get(templateId, permission), 0);
-  }
-
-  public Set<String> permissions(long templateId) {
-    return FluentIterable.from(
-      Iterables.concat(
-        userCountByTemplateIdAndPermission.row(templateId).keySet(),
-        groupCountByTemplateIdAndPermission.row(templateId).keySet()
-        )
-      ).toSortedSet(natural());
-  }
-
-  public static class Builder {
-    private List<PermissionTemplateDto> templates;
-    private List<TemplateUuidQualifier> defaultTemplates;
-    private Table<Long, String, Integer> userCountByTemplateIdAndPermission;
-    private Table<Long, String, Integer> groupCountByTemplateIdAndPermission;
-
-    private Builder() {
-      // prevents instantiation outside main class
-    }
-
-    public SearchTemplatesData build() {
-      checkState(templates != null);
-      checkState(defaultTemplates != null);
-      checkState(userCountByTemplateIdAndPermission != null);
-      checkState(groupCountByTemplateIdAndPermission != null);
-
-      return new SearchTemplatesData(this);
-    }
-
-    public Builder templates(List<PermissionTemplateDto> templates) {
-      this.templates = templates;
-      return this;
-    }
-
-    public Builder defaultTemplates(List<TemplateUuidQualifier> defaultTemplates) {
-      this.defaultTemplates = defaultTemplates;
-      return this;
-    }
-
-    public Builder userCountByTemplateIdAndPermission(Table<Long, String, Integer> userCountByTemplateIdAndPermission) {
-      this.userCountByTemplateIdAndPermission = userCountByTemplateIdAndPermission;
-      return this;
-    }
-
-    public Builder groupCountByTemplateIdAndPermission(Table<Long, String, Integer> groupCountByTemplateIdAndPermission) {
-      this.groupCountByTemplateIdAndPermission = groupCountByTemplateIdAndPermission;
-      return this;
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesDataLoader.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchTemplatesDataLoader.java
deleted file mode 100644 (file)
index 79a2984..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Table;
-import com.google.common.collect.TreeBasedTable;
-import java.util.List;
-import javax.annotation.Nonnull;
-import org.apache.ibatis.session.ResultContext;
-import org.apache.ibatis.session.ResultHandler;
-import org.sonar.api.server.ws.Request;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.CountByTemplateAndPermissionDto;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.permission.ws.DefaultPermissionTemplateFinder.TemplateUuidQualifier;
-
-import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
-import static org.sonar.server.permission.ws.SearchTemplatesData.newBuilder;
-
-public class SearchTemplatesDataLoader {
-  private final DbClient dbClient;
-  private final DefaultPermissionTemplateFinder defaultPermissionTemplateFinder;
-
-  public SearchTemplatesDataLoader(DbClient dbClient, DefaultPermissionTemplateFinder defaultPermissionTemplateFinder) {
-    this.dbClient = dbClient;
-    this.defaultPermissionTemplateFinder = defaultPermissionTemplateFinder;
-  }
-
-  public SearchTemplatesData load(Request wsRequest) {
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      SearchTemplatesData.Builder data = newBuilder();
-      List<PermissionTemplateDto> templates = searchTemplates(dbSession, wsRequest);
-      List<Long> templateIds = Lists.transform(templates, TemplateToIdFunction.INSTANCE);
-      List<TemplateUuidQualifier> defaultTemplates = defaultPermissionTemplateFinder.getDefaultTemplatesByQualifier();
-
-      data.templates(templates)
-        .defaultTemplates(defaultTemplates)
-        .userCountByTemplateIdAndPermission(userCountByTemplateIdAndPermission(dbSession, templateIds))
-        .groupCountByTemplateIdAndPermission(groupCountByTemplateIdAndPermission(dbSession, templateIds));
-
-      return data.build();
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-  }
-
-  private List<PermissionTemplateDto> searchTemplates(DbSession dbSession, Request wsRequest) {
-    String nameMatch = wsRequest.param(TEXT_QUERY);
-
-    return nameMatch == null ?
-      dbClient.permissionTemplateDao().selectAll(dbSession)
-      : dbClient.permissionTemplateDao().selectAll(dbSession, nameMatch);
-  }
-
-  private Table<Long, String, Integer> userCountByTemplateIdAndPermission(DbSession dbSession, List<Long> templateIds) {
-    final Table<Long, String, Integer> userCountByTemplateIdAndPermission = TreeBasedTable.create();
-
-    dbClient.permissionTemplateDao().usersCountByTemplateIdAndPermission(dbSession, templateIds, new ResultHandler() {
-      @Override
-      public void handleResult(ResultContext context) {
-        CountByTemplateAndPermissionDto row = (CountByTemplateAndPermissionDto) context.getResultObject();
-        userCountByTemplateIdAndPermission.put(row.getTemplateId(), row.getPermission(), row.getCount());
-      }
-    });
-
-    return userCountByTemplateIdAndPermission;
-  }
-
-  private Table<Long, String, Integer> groupCountByTemplateIdAndPermission(DbSession dbSession, List<Long> templateIds) {
-    final Table<Long, String, Integer> userCountByTemplateIdAndPermission = TreeBasedTable.create();
-
-    dbClient.permissionTemplateDao().groupsCountByTemplateIdAndPermission(dbSession, templateIds, new ResultHandler() {
-      @Override
-      public void handleResult(ResultContext context) {
-        CountByTemplateAndPermissionDto row = (CountByTemplateAndPermissionDto) context.getResultObject();
-        userCountByTemplateIdAndPermission.put(row.getTemplateId(), row.getPermission(), row.getCount());
-      }
-    });
-
-    return userCountByTemplateIdAndPermission;
-  }
-
-  private enum TemplateToIdFunction implements Function<PermissionTemplateDto, Long> {
-    INSTANCE;
-
-    @Override
-    public Long apply(@Nonnull PermissionTemplateDto template) {
-      return template.getId();
-    }
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SetDefaultTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/SetDefaultTemplateAction.java
deleted file mode 100644 (file)
index 79a54ed..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.Set;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.platform.PersistentSettings;
-import org.sonar.server.user.UserSession;
-
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Ordering.natural;
-import static java.lang.String.format;
-import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_QUALIFIER;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
-import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
-
-public class SetDefaultTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final PermissionDependenciesFinder finder;
-  private final ResourceTypes resourceTypes;
-  private final PersistentSettings settings;
-  private final UserSession userSession;
-  private final I18n i18n;
-
-  public SetDefaultTemplateAction(DbClient dbClient, PermissionDependenciesFinder finder, ResourceTypes resourceTypes, PersistentSettings settings, UserSession userSession,
-    I18n i18n) {
-    this.dbClient = dbClient;
-    this.finder = finder;
-    this.resourceTypes = resourceTypes;
-    this.settings = settings;
-    this.userSession = userSession;
-    this.i18n = i18n;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context.createAction("set_default_template")
-      .setDescription("Set a permission template as default.<br />" +
-        "It requires administration permissions to access.")
-      .setPost(true)
-      .setSince("5.2")
-      .setHandler(this);
-
-    createTemplateParameters(action);
-
-    action.createParam(PARAM_QUALIFIER)
-      .setDescription("Project qualifier. Possible values are:" + buildRootQualifiersDescription())
-      .setDefaultValue(Qualifiers.PROJECT)
-      .setPossibleValues(getRootQualifiers());
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    checkGlobalAdminUser(userSession);
-
-    String qualifier = wsRequest.mandatoryParam(PARAM_QUALIFIER);
-
-    PermissionTemplateDto template = getTemplate(wsRequest);
-    validateQualifier(qualifier, getRootQualifiers());
-    setDefaultTemplateUuid(template.getUuid(), qualifier);
-    wsResponse.noContent();
-  }
-
-  private Set<String> getRootQualifiers() {
-    return from(resourceTypes.getRoots())
-      .transform(RESOURCE_TYPE_TO_QUALIFIER)
-      .toSortedSet(natural());
-  }
-
-  private String buildRootQualifiersDescription() {
-    StringBuilder description = new StringBuilder();
-    description.append("<ul>");
-    String qualifierPattern = "<li>%s - %s</li>";
-    for (String qualifier : getRootQualifiers()) {
-      description.append(format(qualifierPattern, qualifier, i18n(qualifier)));
-    }
-    description.append("</ul>");
-
-    return description.toString();
-  }
-
-  private String i18n(String qualifier) {
-    String qualifiersPropertyPrefix = "qualifiers.";
-    return i18n.message(userSession.locale(), qualifiersPropertyPrefix + qualifier, "");
-  }
-
-  private PermissionTemplateDto getTemplate(Request wsRequest) {
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      return finder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-  }
-
-  private void setDefaultTemplateUuid(String templateUuid, String qualifier) {
-    settings.saveProperty(defaultRootQualifierTemplateProperty(qualifier), templateUuid);
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/UpdateTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/UpdateTemplateAction.java
deleted file mode 100644 (file)
index d7ba4b5..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.Date;
-import javax.annotation.Nullable;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.user.UserSession;
-import org.sonarqube.ws.WsPermissions.PermissionTemplate;
-import org.sonarqube.ws.WsPermissions.WsUpdatePermissionTemplateResponse;
-
-import static com.google.common.base.Objects.firstNonNull;
-import static java.lang.String.format;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createIdParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateDescriptionParameter;
-import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateProjectKeyPatternParameter;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.MSG_TEMPLATE_WITH_SAME_NAME;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPattern;
-import static org.sonar.server.permission.ws.PermissionRequestValidator.validateTemplateNameFormat;
-import static org.sonar.server.permission.ws.PermissionTemplateDtoToPermissionTemplateResponse.toPermissionTemplateResponse;
-import static org.sonar.server.ws.WsUtils.checkRequest;
-import static org.sonar.server.ws.WsUtils.writeProtobuf;
-
-public class UpdateTemplateAction implements PermissionsWsAction {
-  private final DbClient dbClient;
-  private final UserSession userSession;
-  private final System2 system;
-  private final PermissionDependenciesFinder finder;
-
-  public UpdateTemplateAction(DbClient dbClient, UserSession userSession, System2 system, PermissionDependenciesFinder finder) {
-    this.dbClient = dbClient;
-    this.userSession = userSession;
-    this.system = system;
-    this.finder = finder;
-  }
-
-  @Override
-  public void define(WebService.NewController context) {
-    WebService.NewAction action = context.createAction("update_template")
-      .setDescription("Update a permission template.<br />" +
-        "It requires administration permissions to access.")
-      .setResponseExample(getClass().getResource("update_template-example.json"))
-      .setSince("5.2")
-      .setPost(true)
-      .setHandler(this);
-
-    createIdParameter(action);
-
-    action.createParam(PARAM_NAME)
-      .setDescription("Name")
-      .setExampleValue("Financial Service Permissions");
-
-    createTemplateProjectKeyPatternParameter(action);
-    createTemplateDescriptionParameter(action);
-  }
-
-  @Override
-  public void handle(Request wsRequest, Response wsResponse) throws Exception {
-    checkGlobalAdminUser(userSession);
-
-    String uuid = wsRequest.mandatoryParam(PARAM_ID);
-    String nameParam = wsRequest.param(PARAM_NAME);
-    String descriptionParam = wsRequest.param(PARAM_DESCRIPTION);
-    String projectPatternParam = wsRequest.param(PARAM_PATTERN);
-
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      PermissionTemplateDto templateToUpdate = getAndBuildTemplateToUpdate(dbSession, uuid, nameParam, descriptionParam, projectPatternParam);
-      validateTemplate(dbSession, templateToUpdate);
-      PermissionTemplateDto updatedTemplate = updateTemplate(dbSession, templateToUpdate);
-
-      WsUpdatePermissionTemplateResponse response = buildResponse(updatedTemplate);
-      writeProtobuf(response, wsRequest, wsResponse);
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-  }
-
-  private void validateTemplate(DbSession dbSession, PermissionTemplateDto templateToUpdate) {
-    validateTemplateNameForUpdate(dbSession, templateToUpdate.getName(), templateToUpdate.getId());
-    validateProjectPattern(templateToUpdate.getKeyPattern());
-  }
-
-  private PermissionTemplateDto getAndBuildTemplateToUpdate(DbSession dbSession, String uuid, @Nullable String newName, @Nullable String newDescription,
-    @Nullable String newProjectKeyPattern) {
-    PermissionTemplateDto templateToUpdate = finder.getTemplate(dbSession, WsTemplateRef.newTemplateRef(uuid, null));
-    templateToUpdate.setName(firstNonNull(newName, templateToUpdate.getName()));
-    templateToUpdate.setDescription(firstNonNull(newDescription, templateToUpdate.getDescription()));
-    templateToUpdate.setKeyPattern(firstNonNull(newProjectKeyPattern, templateToUpdate.getKeyPattern()));
-    templateToUpdate.setUpdatedAt(new Date(system.now()));
-
-    return templateToUpdate;
-  }
-
-  private PermissionTemplateDto updateTemplate(DbSession dbSession, PermissionTemplateDto templateToUpdate) {
-    return dbClient.permissionTemplateDao().update(dbSession, templateToUpdate);
-  }
-
-  private static WsUpdatePermissionTemplateResponse buildResponse(PermissionTemplateDto permissionTemplate) {
-    PermissionTemplate permissionTemplateBuilder = toPermissionTemplateResponse(permissionTemplate);
-    return WsUpdatePermissionTemplateResponse.newBuilder().setPermissionTemplate(permissionTemplateBuilder).build();
-  }
-
-  private void validateTemplateNameForUpdate(DbSession dbSession, String name, long id) {
-    validateTemplateNameFormat(name);
-
-    PermissionTemplateDto permissionTemplateWithSameName = dbClient.permissionTemplateDao().selectByName(dbSession, name);
-    checkRequest(permissionTemplateWithSameName == null || permissionTemplateWithSameName.getId() == id,
-      format(MSG_TEMPLATE_WITH_SAME_NAME, name));
-  }
-}
index 2c735193a12a733855c626da24fcdb1af81f1551..329b2d4f665736778ab8dcccaaa6770d79b9db49 100644 (file)
@@ -31,7 +31,7 @@ import static org.sonar.server.ws.WsUtils.checkRequest;
 /**
  * Group from a WS request. Guaranties the group id or the group name is provided, not both.
  */
-class WsGroupRef {
+public class WsGroupRef {
 
   private final Long id;
   private final String name;
@@ -43,7 +43,7 @@ class WsGroupRef {
     this.name = name;
   }
 
-  static WsGroupRef fromRequest(Request wsRequest) {
+  public static WsGroupRef fromRequest(Request wsRequest) {
     Long id = wsRequest.paramAsLong(PARAM_GROUP_ID);
     String name = wsRequest.param(PARAM_GROUP_NAME);
 
@@ -51,12 +51,12 @@ class WsGroupRef {
   }
 
   @CheckForNull
-  Long id() {
+  public Long id() {
     return this.id;
   }
 
   @CheckForNull
-  String name() {
+  public String name() {
     return this.name;
   }
 }
index 274c2c2991b3870eb43fbe0db46cb3c3d52e6b26..41f8aeefe306b66cfed84d88fc987ad1153c6d68 100644 (file)
@@ -27,23 +27,23 @@ import org.sonar.core.util.Uuids;
 
 import static java.lang.String.format;
 
-class WsPermissionParameters {
+public class WsPermissionParameters {
 
-  static final String PARAM_PERMISSION = "permission";
-  static final String PARAM_GROUP_NAME = "groupName";
-  static final String PARAM_GROUP_ID = "groupId";
-  static final String PARAM_PROJECT_ID = "projectId";
-  static final String PARAM_PROJECT_KEY = "projectKey";
-  static final String PARAM_USER_LOGIN = "login";
-  static final String PARAM_TEMPLATE_ID = "templateId";
-  static final String PARAM_TEMPLATE_NAME = "templateName";
+  public static final String PARAM_PERMISSION = "permission";
+  public static final String PARAM_GROUP_NAME = "groupName";
+  public static final String PARAM_GROUP_ID = "groupId";
+  public static final String PARAM_PROJECT_ID = "projectId";
+  public static final String PARAM_PROJECT_KEY = "projectKey";
+  public static final String PARAM_USER_LOGIN = "login";
+  public static final String PARAM_TEMPLATE_ID = "templateId";
+  public static final String PARAM_TEMPLATE_NAME = "templateName";
 
-  static final String PARAM_ID = "id";
-  static final String PARAM_NAME = "name";
-  static final String PARAM_DESCRIPTION = "description";
-  static final String PARAM_PATTERN = "projectKeyPattern";
+  public static final String PARAM_ID = "id";
+  public static final String PARAM_NAME = "name";
+  public static final String PARAM_DESCRIPTION = "description";
+  public static final String PARAM_PATTERN = "projectKeyPattern";
 
-  static final String PARAM_QUALIFIER = "qualifier";
+  public static final String PARAM_QUALIFIER = "qualifier";
 
   private static final String PERMISSION_PARAM_DESCRIPTION = format("Permission" +
     "<ul>" +
@@ -62,31 +62,31 @@ class WsPermissionParameters {
     // static methods only
   }
 
-  static void createPermissionParameter(NewAction action) {
+  public static void createPermissionParameter(NewAction action) {
     action.createParam(PARAM_PERMISSION)
       .setDescription(PERMISSION_PARAM_DESCRIPTION)
       .setRequired(true);
   }
 
-  static void createProjectPermissionParameter(NewAction action) {
+  public static void createProjectPermissionParameter(NewAction action) {
     action.createParam(PARAM_PERMISSION)
       .setDescription(PROJECT_PERMISSION_PARAM_DESCRIPTION)
       .setRequired(true);
   }
 
-  static void createGroupNameParameter(NewAction action) {
+  public static void createGroupNameParameter(NewAction action) {
     action.createParam(PARAM_GROUP_NAME)
       .setDescription("Group name or 'anyone' (case insensitive)")
       .setExampleValue("sonar-administrators");
   }
 
-  static void createGroupIdParameter(NewAction action) {
+  public static void createGroupIdParameter(NewAction action) {
     action.createParam(PARAM_GROUP_ID)
       .setDescription("Group id")
       .setExampleValue("42");
   }
 
-  static void createProjectParameter(NewAction action) {
+  public static void createProjectParameter(NewAction action) {
     createProjectIdParameter(action);
     createProjectKeyParameter(action);
   }
@@ -103,14 +103,14 @@ class WsPermissionParameters {
       .setExampleValue("org.apache.hbas:hbase");
   }
 
-  static void createUserLoginParameter(NewAction action) {
+  public static void createUserLoginParameter(NewAction action) {
     action.createParam(PARAM_USER_LOGIN)
       .setRequired(true)
       .setDescription("User login")
       .setExampleValue("g.hopper");
   }
 
-  static void createTemplateParameters(NewAction action) {
+  public static void createTemplateParameters(NewAction action) {
     createTemplateIdParameter(action);
     createTemplateNameParameter(action);
   }
@@ -127,19 +127,19 @@ class WsPermissionParameters {
       .setExampleValue("Default Permission Template for Projects");
   }
 
-  static void createTemplateProjectKeyPatternParameter(NewAction action) {
+  public static void createTemplateProjectKeyPatternParameter(NewAction action) {
     action.createParam(PARAM_PATTERN)
       .setDescription("Project key pattern. Must be a valid Java regular expression")
       .setExampleValue(".*\\.finance\\..*");
   }
 
-  static void createTemplateDescriptionParameter(NewAction action) {
+  public static void createTemplateDescriptionParameter(NewAction action) {
     action.createParam(PARAM_DESCRIPTION)
       .setDescription("Description")
       .setExampleValue("Permissions for all projects related to the financial service");
   }
 
-  static void createIdParameter(NewAction action) {
+  public static void createIdParameter(NewAction action) {
     action.createParam(PARAM_ID)
       .setRequired(true)
       .setDescription("Id")
index feda183aba9d3d8a925b20f6a1c41d8533c2c8f6..9e1f6989edc96f07d9cbfe18b7685b06b2d6402a 100644 (file)
@@ -31,7 +31,7 @@ import static org.sonar.server.ws.WsUtils.checkRequest;
 /**
  * Project identifiers from a WS request. Guaranties the project id and project key are not provided at the same time.
  */
-class WsProjectRef {
+public class WsProjectRef {
   private final String uuid;
   private final String key;
 
@@ -41,7 +41,7 @@ class WsProjectRef {
     checkRequest(uuid != null ^ key != null, "Project id or project key can be provided, not both.");
   }
 
-  static Optional<WsProjectRef> optionalFromRequest(Request wsRequest) {
+  public static Optional<WsProjectRef> optionalFromRequest(Request wsRequest) {
     if (!hasProjectParam(wsRequest)) {
       return Optional.absent();
     }
@@ -49,19 +49,19 @@ class WsProjectRef {
     return Optional.of(new WsProjectRef(wsRequest));
   }
 
-  static WsProjectRef fromRequest(Request wsRequest) {
+  public static WsProjectRef fromRequest(Request wsRequest) {
     checkRequest(hasProjectParam(wsRequest), "Project id or project key must be provided, not both.");
 
     return new WsProjectRef(wsRequest);
   }
 
   @CheckForNull
-  String uuid() {
+  public String uuid() {
     return this.uuid;
   }
 
   @CheckForNull
-  String key() {
+  public String key() {
     return this.key;
   }
 
index 82377eea06d03dcf13b50906cb596a1af7bc93be..aeb3f8c01406102168c294bebd24d03b289343d3 100644 (file)
@@ -31,7 +31,7 @@ import static org.sonar.server.ws.WsUtils.checkRequest;
 /**
  * Template from a WS request. Guaranties the template id or the template name is provided, not both.
  */
-class WsTemplateRef {
+public class WsTemplateRef {
 
   private final String uuid;
   private final String name;
@@ -43,24 +43,24 @@ class WsTemplateRef {
     this.name = name;
   }
 
-  static WsTemplateRef fromRequest(Request wsRequest) {
+  public static WsTemplateRef fromRequest(Request wsRequest) {
     String uuid = wsRequest.param(PARAM_TEMPLATE_ID);
     String name = wsRequest.param(PARAM_TEMPLATE_NAME);
 
     return new WsTemplateRef(uuid, name);
   }
 
-  static WsTemplateRef newTemplateRef(@Nullable String uuid, @Nullable String name) {
+  public static WsTemplateRef newTemplateRef(@Nullable String uuid, @Nullable String name) {
     return new WsTemplateRef(uuid, name);
   }
 
   @CheckForNull
-  String uuid() {
+  public String uuid() {
     return this.uuid;
   }
 
   @CheckForNull
-  String name() {
+  public String name() {
     return this.name;
   }
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddGroupToTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddGroupToTemplateAction.java
new file mode 100644 (file)
index 0000000..7b459b8
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import javax.annotation.Nullable;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.permission.ws.WsGroupRef;
+import org.sonar.server.permission.ws.WsTemplateRef;
+import org.sonar.server.user.UserSession;
+
+import static org.sonar.api.security.DefaultGroups.ANYONE;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateNotAnyoneAndAdminPermission;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupIdParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupNameParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
+
+public class AddGroupToTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final PermissionDependenciesFinder dependenciesFinder;
+  private final UserSession userSession;
+
+  public AddGroupToTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.dependenciesFinder = dependenciesFinder;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context
+      .createAction("add_group_to_template")
+      .setPost(true)
+      .setSince("5.2")
+      .setDescription("Add a group to a permission template.<br /> " +
+        "The group id or group name must be provided. <br />" +
+        "It requires administration permissions to access.")
+      .setHandler(this);
+
+    createTemplateParameters(action);
+    createProjectPermissionParameter(action);
+    createGroupIdParameter(action);
+    createGroupNameParameter(action);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    checkGlobalAdminUser(userSession);
+
+    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
+    WsGroupRef group = WsGroupRef.fromRequest(wsRequest);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      validateProjectPermission(permission);
+      validateNotAnyoneAndAdminPermission(permission, group.name());
+
+      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
+      GroupDto groupDto = dependenciesFinder.getGroup(dbSession, group);
+
+      if (!groupAlreadyAdded(dbSession, template.getId(), groupDto, permission)) {
+        Long groupId = groupDto == null ? null : groupDto.getId();
+        dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getId(), groupId, permission);
+      }
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+
+    wsResponse.noContent();
+  }
+
+  private boolean groupAlreadyAdded(DbSession dbSession, long templateId, @Nullable GroupDto group, String permission) {
+    String groupName = group == null ? ANYONE : group.getName();
+    PermissionQuery permissionQuery = PermissionQuery.builder().membership(IN).permission(permission).build();
+    return dbClient.permissionTemplateDao().hasGroup(dbSession, permissionQuery, templateId, groupName);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddUserToTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/AddUserToTemplateAction.java
new file mode 100644 (file)
index 0000000..c8658d3
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Predicate;
+import java.util.List;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.permission.UserWithPermissionDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.permission.ws.WsTemplateRef;
+import org.sonar.server.user.UserSession;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createUserLoginParameter;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
+
+public class AddUserToTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final PermissionDependenciesFinder dependenciesFinder;
+  private final UserSession userSession;
+
+  public AddUserToTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.dependenciesFinder = dependenciesFinder;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context
+      .createAction("add_user_to_template")
+      .setPost(true)
+      .setSince("5.2")
+      .setDescription("Add a user to a permission template.<br /> " +
+        "It requires administration permissions to access.")
+      .setHandler(this);
+
+    createTemplateParameters(action);
+    createProjectPermissionParameter(action);
+    createUserLoginParameter(action);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    checkGlobalAdminUser(userSession);
+
+    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
+    final String userLogin = wsRequest.mandatoryParam(PARAM_USER_LOGIN);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      validateProjectPermission(permission);
+      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
+      UserDto user = dependenciesFinder.getUser(dbSession, userLogin);
+
+      if (!isUserAlreadyAdded(dbSession, template.getId(), userLogin, permission)) {
+        dbClient.permissionTemplateDao().insertUserPermission(dbSession, template.getId(), user.getId(), permission);
+      }
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+
+    wsResponse.noContent();
+  }
+
+  private boolean isUserAlreadyAdded(DbSession dbSession, long templateId, String userLogin, String permission) {
+    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    List<UserWithPermissionDto> usersWithPermission = dbClient.permissionTemplateDao().selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE);
+    return from(usersWithPermission).anyMatch(new HasUserPredicate(userLogin));
+  }
+
+  private static class HasUserPredicate implements Predicate<UserWithPermissionDto> {
+    private final String userLogin;
+
+    public HasUserPredicate(String userLogin) {
+      this.userLogin = userLogin;
+    }
+
+    @Override
+    public boolean apply(UserWithPermissionDto userWithPermission) {
+      return userLogin.equals(userWithPermission.getLogin());
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/ApplyTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/ApplyTemplateAction.java
new file mode 100644 (file)
index 0000000..ab97c35
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ApplyPermissionTemplateQuery;
+import org.sonar.server.permission.PermissionService;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.permission.ws.WsProjectRef;
+import org.sonar.server.permission.ws.WsTemplateRef;
+
+import static java.util.Collections.singletonList;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
+
+public class ApplyTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final PermissionService permissionService;
+  private final PermissionDependenciesFinder finder;
+
+  public ApplyTemplateAction(DbClient dbClient, PermissionService permissionService, PermissionDependenciesFinder finder) {
+    this.dbClient = dbClient;
+    this.permissionService = permissionService;
+    this.finder = finder;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context.createAction("apply_template")
+      .setDescription("Apply a permission template to one or several projects.<br />" +
+        "The project id or project key must be provided.<br />" +
+        "It requires administration permissions to access.")
+      .setPost(true)
+      .setSince("5.2")
+      .setHandler(this);
+
+    createTemplateParameters(action);
+    createProjectParameter(action);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      PermissionTemplateDto template = finder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
+      ComponentDto project = finder.getProject(dbSession, WsProjectRef.fromRequest(wsRequest));
+
+      ApplyPermissionTemplateQuery query = ApplyPermissionTemplateQuery.create(
+        template.getUuid(),
+        singletonList(project.key()));
+      permissionService.applyPermissionTemplate(query);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+
+    wsResponse.noContent();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/CreateTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/CreateTemplateAction.java
new file mode 100644 (file)
index 0000000..2e94984
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.WsPermissions.PermissionTemplate;
+import org.sonarqube.ws.WsPermissions.WsCreatePermissionTemplateResponse;
+
+import static java.lang.String.format;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateDescriptionParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateProjectKeyPatternParameter;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.MSG_TEMPLATE_WITH_SAME_NAME;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPattern;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateTemplateNameFormat;
+import static org.sonar.server.permission.ws.template.PermissionTemplateDtoBuilder.create;
+import static org.sonar.server.permission.ws.template.PermissionTemplateDtoToPermissionTemplateResponse.toPermissionTemplateResponse;
+import static org.sonar.server.ws.WsUtils.checkRequest;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+
+public class CreateTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final UserSession userSession;
+  private final System2 system;
+
+  public CreateTemplateAction(DbClient dbClient, UserSession userSession, System2 system) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+    this.system = system;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context.createAction("create_template")
+      .setDescription("Create a permission template.<br />" +
+        "It requires administration permissions to access.")
+      .setResponseExample(getClass().getResource("create_template-example.json"))
+      .setSince("5.2")
+      .setPost(true)
+      .setHandler(this);
+
+    action.createParam(PARAM_NAME)
+      .setRequired(true)
+      .setDescription("Name")
+      .setExampleValue("Financial Service Permissions");
+
+    createTemplateProjectKeyPatternParameter(action);
+    createTemplateDescriptionParameter(action);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    String name = wsRequest.mandatoryParam(PARAM_NAME);
+    String description = wsRequest.param(PARAM_DESCRIPTION);
+    String projectPattern = wsRequest.param(PARAM_PATTERN);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      checkGlobalAdminUser(userSession);
+      validateTemplateNameForCreation(dbSession, name);
+      validateProjectPattern(projectPattern);
+
+      PermissionTemplateDto permissionTemplate = insertTemplate(dbSession, name, description, projectPattern);
+
+      WsCreatePermissionTemplateResponse response = buildResponse(permissionTemplate);
+      writeProtobuf(response, wsRequest, wsResponse);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private void validateTemplateNameForCreation(DbSession dbSession, String name) {
+    validateTemplateNameFormat(name);
+
+    PermissionTemplateDto permissionTemplateWithSameName = dbClient.permissionTemplateDao().selectByName(dbSession, name);
+    checkRequest(permissionTemplateWithSameName == null, format(MSG_TEMPLATE_WITH_SAME_NAME, name));
+  }
+
+  private PermissionTemplateDto insertTemplate(DbSession dbSession, String name, String description, String projectPattern) {
+    PermissionTemplateDto template = dbClient.permissionTemplateDao().insert(dbSession, create(system)
+      .setName(name)
+      .setDescription(description)
+      .setProjectKeyPattern(projectPattern)
+      .toDto());
+    dbSession.commit();
+    return template;
+  }
+
+  private static WsCreatePermissionTemplateResponse buildResponse(PermissionTemplateDto permissionTemplateDto) {
+    PermissionTemplate permissionTemplateBuilder = toPermissionTemplateResponse(permissionTemplateDto);
+    return WsCreatePermissionTemplateResponse.newBuilder().setPermissionTemplate(permissionTemplateBuilder).build();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/DefaultPermissionTemplateFinder.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/DefaultPermissionTemplateFinder.java
new file mode 100644 (file)
index 0000000..2ee4951
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Function;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceTypes;
+
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Ordering.natural;
+import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
+import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
+import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
+
+public class DefaultPermissionTemplateFinder {
+  private final Settings settings;
+  private final ResourceTypes resourceTypes;
+
+  public DefaultPermissionTemplateFinder(Settings settings, ResourceTypes resourceTypes) {
+    this.settings = settings;
+    this.resourceTypes = resourceTypes;
+  }
+
+  public Set<String> getDefaultTemplateUuids() {
+    return from(resourceTypes.getRoots())
+      .transform(RESOURCE_TYPE_TO_QUALIFIER)
+      .transform(new QualifierToDefaultTemplate(settings))
+      .toSortedSet(natural());
+  }
+
+  public List<TemplateUuidQualifier> getDefaultTemplatesByQualifier() {
+    return from(resourceTypes.getRoots())
+      .transform(RESOURCE_TYPE_TO_QUALIFIER)
+      .transform(new QualifierToTemplateUuidQualifier(settings))
+      .toList();
+  }
+
+  public static class TemplateUuidQualifier {
+    private final String templateUuid;
+    private final String qualifier;
+
+    TemplateUuidQualifier(String templateUuid, String qualifier) {
+      this.templateUuid = templateUuid;
+      this.qualifier = qualifier;
+    }
+
+    public String getTemplateUuid() {
+      return templateUuid;
+    }
+
+    public String getQualifier() {
+      return qualifier;
+    }
+  }
+
+  private static class QualifierToDefaultTemplate implements Function<String, String> {
+    private final Settings settings;
+
+    QualifierToDefaultTemplate(Settings settings) {
+      this.settings = settings;
+    }
+
+    @Override
+    public String apply(@Nonnull String qualifier) {
+      String effectiveTemplateUuid = effectiveTemplateUuid(settings, qualifier);
+      return effectiveTemplateUuid;
+    }
+  }
+
+  private static class QualifierToTemplateUuidQualifier implements Function<String, TemplateUuidQualifier> {
+    private final Settings settings;
+
+    QualifierToTemplateUuidQualifier(Settings settings) {
+      this.settings = settings;
+    }
+
+    @Override
+    public TemplateUuidQualifier apply(@Nonnull String qualifier) {
+      String effectiveTemplateUuid = effectiveTemplateUuid(settings, qualifier);
+
+      return new TemplateUuidQualifier(effectiveTemplateUuid, qualifier);
+    }
+  }
+
+  private static String effectiveTemplateUuid(Settings settings, String qualifier) {
+    String qualifierTemplateUuid = settings.getString(defaultRootQualifierTemplateProperty(qualifier));
+    String projectTemplateUuid = settings.getString(defaultRootQualifierTemplateProperty(Qualifiers.PROJECT));
+    String defaultTemplateUuid = settings.getString(DEFAULT_TEMPLATE_PROPERTY);
+
+    if (qualifierTemplateUuid != null) {
+      return qualifierTemplateUuid;
+    } else if (projectTemplateUuid != null) {
+      return projectTemplateUuid;
+    } else {
+      return defaultTemplateUuid;
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/PermissionTemplateDtoBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/PermissionTemplateDtoBuilder.java
new file mode 100644 (file)
index 0000000..79e658d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.Date;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.permission.PermissionTemplateDto;
+
+public class PermissionTemplateDtoBuilder {
+  private final System2 system;
+  private String name;
+  private String description;
+  private String projectKeyPattern;
+
+  private PermissionTemplateDtoBuilder(System2 system) {
+    this.system = system;
+  }
+
+  public static PermissionTemplateDtoBuilder create(System2 system) {
+    return new PermissionTemplateDtoBuilder(system);
+  }
+
+  public PermissionTemplateDtoBuilder setName(String name) {
+    this.name = name;
+    return this;
+  }
+
+  public PermissionTemplateDtoBuilder setDescription(String description) {
+    this.description = description;
+    return this;
+  }
+
+  public PermissionTemplateDtoBuilder setProjectKeyPattern(String projectKeyPattern) {
+    this.projectKeyPattern = projectKeyPattern;
+    return this;
+  }
+
+  public PermissionTemplateDto toDto() {
+    long now = system.now();
+    return new PermissionTemplateDto()
+      .setName(name)
+      .setDescription(description)
+      .setKeyPattern(projectKeyPattern)
+      .setKee(Uuids.create())
+      .setCreatedAt(new Date(now))
+      .setUpdatedAt(new Date(now));
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/PermissionTemplateDtoToPermissionTemplateResponse.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/PermissionTemplateDtoToPermissionTemplateResponse.java
new file mode 100644 (file)
index 0000000..28f77ac
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Function;
+import javax.annotation.Nonnull;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonarqube.ws.WsPermissions.PermissionTemplate;
+
+public class PermissionTemplateDtoToPermissionTemplateResponse {
+
+  public static PermissionTemplate toPermissionTemplateResponse(PermissionTemplateDto dto) {
+    return Singleton.INSTANCE.apply(dto);
+  }
+
+  private enum Singleton implements Function<PermissionTemplateDto, PermissionTemplate> {
+    INSTANCE;
+    @Override
+    public PermissionTemplate apply(@Nonnull PermissionTemplateDto permissionTemplate) {
+      PermissionTemplate.Builder permissionTemplateBuilder = PermissionTemplate.newBuilder()
+        .setId(permissionTemplate.getKee())
+        .setName(permissionTemplate.getName())
+        .setCreatedAt(DateUtils.formatDateTime(permissionTemplate.getCreatedAt()))
+        .setUpdatedAt(DateUtils.formatDateTime(permissionTemplate.getUpdatedAt()));
+      if (permissionTemplate.getDescription() != null) {
+        permissionTemplateBuilder.setDescription(permissionTemplate.getDescription());
+      }
+      if (permissionTemplate.getKeyPattern() != null) {
+        permissionTemplateBuilder.setProjectKeyPattern(permissionTemplate.getKeyPattern());
+      }
+      return permissionTemplateBuilder.build();
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/RemoveGroupFromTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/RemoveGroupFromTemplateAction.java
new file mode 100644 (file)
index 0000000..d86cd25
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.permission.ws.WsGroupRef;
+import org.sonar.server.permission.ws.WsTemplateRef;
+import org.sonar.server.user.UserSession;
+
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupIdParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createGroupNameParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
+
+public class RemoveGroupFromTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final PermissionDependenciesFinder dependenciesFinder;
+  private final UserSession userSession;
+
+  public RemoveGroupFromTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.dependenciesFinder = dependenciesFinder;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context
+      .createAction("remove_group_from_template")
+      .setPost(true)
+      .setSince("5.2")
+      .setDescription("Remove a group from a permission template.<br /> " +
+        "The group id or group name must be provided. <br />" +
+        "It requires administration permissions to access.")
+      .setHandler(this);
+
+    createTemplateParameters(action);
+    createProjectPermissionParameter(action);
+    createGroupIdParameter(action);
+    createGroupNameParameter(action);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    checkGlobalAdminUser(userSession);
+
+    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
+    WsGroupRef group = WsGroupRef.fromRequest(wsRequest);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      validateProjectPermission(permission);
+
+      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
+      GroupDto groupDto = dependenciesFinder.getGroup(dbSession, group);
+
+      Long groupId = groupDto == null ? null : groupDto.getId();
+      dbClient.permissionTemplateDao().deleteGroupPermission(dbSession, template.getId(), groupId, permission);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+
+    wsResponse.noContent();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/RemoveUserFromTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/RemoveUserFromTemplateAction.java
new file mode 100644 (file)
index 0000000..a8147e4
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.permission.ws.WsTemplateRef;
+import org.sonar.server.user.UserSession;
+
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createProjectPermissionParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createUserLoginParameter;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
+
+public class RemoveUserFromTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final PermissionDependenciesFinder dependenciesFinder;
+  private final UserSession userSession;
+
+  public RemoveUserFromTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.dependenciesFinder = dependenciesFinder;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context
+      .createAction("remove_user_from_template")
+      .setPost(true)
+      .setSince("5.2")
+      .setDescription("Remove a user from a permission template.<br /> " +
+        "It requires administration permissions to access.")
+      .setHandler(this);
+
+    createTemplateParameters(action);
+    createProjectPermissionParameter(action);
+    createUserLoginParameter(action);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    checkGlobalAdminUser(userSession);
+
+    String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
+    String userLogin = wsRequest.mandatoryParam(PARAM_USER_LOGIN);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      validateProjectPermission(permission);
+      PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
+      UserDto user = dependenciesFinder.getUser(dbSession, userLogin);
+
+      dbClient.permissionTemplateDao().deleteUserPermission(dbSession, template.getId(), user.getId(), permission);
+      dbSession.commit();
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+
+    wsResponse.noContent();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesAction.java
new file mode 100644 (file)
index 0000000..81ac05f
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.ProjectPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.WsPermissions.Permission;
+import org.sonarqube.ws.WsPermissions.PermissionTemplate;
+import org.sonarqube.ws.WsPermissions.WsSearchTemplatesResponse;
+import org.sonarqube.ws.WsPermissions.WsSearchTemplatesResponse.TemplateIdQualifier;
+
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+
+public class SearchTemplatesAction implements PermissionsWsAction {
+  private static final String PROPERTY_PREFIX = "projects_role.";
+  private static final String DESCRIPTION_SUFFIX = ".desc";
+
+  private final DbClient dbClient;
+  private final UserSession userSession;
+  private final I18n i18n;
+  private final SearchTemplatesDataLoader dataLoader;
+
+  public SearchTemplatesAction(DbClient dbClient, UserSession userSession, I18n i18n, SearchTemplatesDataLoader dataLoader) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+    this.i18n = i18n;
+    this.dataLoader = dataLoader;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    context.createAction("search_templates")
+      .setDescription("List permission templates.<br />" +
+        "It requires administration permissions to access.")
+      .setResponseExample(getClass().getResource("search_templates-example.json"))
+      .setSince("5.2")
+      .addSearchQuery("defau", "permission template names")
+      .setHandler(this);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    checkGlobalAdminUser(userSession);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      SearchTemplatesData data = dataLoader.load(wsRequest);
+      WsSearchTemplatesResponse response = buildResponse(data);
+      writeProtobuf(response, wsRequest, wsResponse);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private WsSearchTemplatesResponse buildResponse(SearchTemplatesData data) {
+    WsSearchTemplatesResponse.Builder response = WsSearchTemplatesResponse.newBuilder();
+
+    buildTemplatesResponse(response, data);
+    buildDefaultTemplatesResponse(response, data);
+    buildPermissionsResponse(response);
+
+    return response.build();
+  }
+
+  private static void buildDefaultTemplatesResponse(WsSearchTemplatesResponse.Builder response, SearchTemplatesData data) {
+    TemplateIdQualifier.Builder templateUuidQualifierBuilder = TemplateIdQualifier.newBuilder();
+    for (DefaultPermissionTemplateFinder.TemplateUuidQualifier templateUuidQualifier : data.defaultTempltes()) {
+      response.addDefaultTemplates(templateUuidQualifierBuilder
+        .clear()
+        .setQualifier(templateUuidQualifier.getQualifier())
+        .setTemplateId(templateUuidQualifier.getTemplateUuid()));
+    }
+  }
+
+  private static void buildTemplatesResponse(WsSearchTemplatesResponse.Builder response, SearchTemplatesData data) {
+    Permission.Builder permissionResponse = Permission.newBuilder();
+    PermissionTemplate.Builder templateBuilder = PermissionTemplate.newBuilder();
+
+    for (PermissionTemplateDto templateDto : data.templates()) {
+      templateBuilder
+        .clear()
+        .setId(templateDto.getUuid())
+        .setName(templateDto.getName())
+        .setCreatedAt(formatDateTime(templateDto.getCreatedAt()))
+        .setUpdatedAt(formatDateTime(templateDto.getUpdatedAt()));
+      if (templateDto.getKeyPattern() != null) {
+        templateBuilder.setProjectKeyPattern(templateDto.getKeyPattern());
+      }
+      if (templateDto.getDescription() != null) {
+        templateBuilder.setDescription(templateDto.getDescription());
+      }
+      for (String permission : data.permissions(templateDto.getId())) {
+        templateBuilder.addPermissions(
+          permissionResponse
+            .clear()
+            .setKey(permission)
+            .setUsersCount(data.userCount(templateDto.getId(), permission))
+            .setGroupsCount(data.groupCount(templateDto.getId(), permission)));
+      }
+      response.addPermissionTemplates(templateBuilder);
+    }
+  }
+
+  private void buildPermissionsResponse(WsSearchTemplatesResponse.Builder response) {
+    Permission.Builder permissionResponse = Permission.newBuilder();
+    for (String permissionKey : ProjectPermissions.ALL) {
+      response.addPermissions(
+        permissionResponse
+          .clear()
+          .setKey(permissionKey)
+          .setName(i18nName(permissionKey))
+          .setDescription(i18nDescriptionMessage(permissionKey))
+        );
+    }
+  }
+
+  private String i18nDescriptionMessage(String permissionKey) {
+    return i18n.message(userSession.locale(), PROPERTY_PREFIX + permissionKey + DESCRIPTION_SUFFIX, "");
+  }
+
+  private String i18nName(String permissionKey) {
+    return i18n.message(userSession.locale(), PROPERTY_PREFIX + permissionKey, permissionKey);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesData.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesData.java
new file mode 100644 (file)
index 0000000..b328477
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Table;
+import java.util.List;
+import java.util.Set;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ws.template.DefaultPermissionTemplateFinder.TemplateUuidQualifier;
+
+import static com.google.common.base.Objects.firstNonNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableList.copyOf;
+import static com.google.common.collect.ImmutableTable.copyOf;
+import static com.google.common.collect.Ordering.natural;
+
+class SearchTemplatesData {
+  private final List<PermissionTemplateDto> templates;
+  private final List<TemplateUuidQualifier> defaultTemplates;
+  private final Table<Long, String, Integer> userCountByTemplateIdAndPermission;
+  private final Table<Long, String, Integer> groupCountByTemplateIdAndPermission;
+
+  private SearchTemplatesData(Builder builder) {
+    this.templates = copyOf(builder.templates);
+    this.defaultTemplates = copyOf(builder.defaultTemplates);
+    this.userCountByTemplateIdAndPermission = copyOf(builder.userCountByTemplateIdAndPermission);
+    this.groupCountByTemplateIdAndPermission = copyOf(builder.groupCountByTemplateIdAndPermission);
+  }
+
+  public static Builder newBuilder() {
+    return new Builder();
+  }
+
+  public List<PermissionTemplateDto> templates() {
+    return templates;
+  }
+
+  public List<TemplateUuidQualifier> defaultTempltes() {
+    return defaultTemplates;
+  }
+
+  public int userCount(long templateId, String permission) {
+    return firstNonNull(userCountByTemplateIdAndPermission.get(templateId, permission), 0);
+  }
+
+  public int groupCount(long templateId, String permission) {
+    return firstNonNull(groupCountByTemplateIdAndPermission.get(templateId, permission), 0);
+  }
+
+  public Set<String> permissions(long templateId) {
+    return FluentIterable.from(
+      Iterables.concat(
+        userCountByTemplateIdAndPermission.row(templateId).keySet(),
+        groupCountByTemplateIdAndPermission.row(templateId).keySet()
+        )
+      ).toSortedSet(natural());
+  }
+
+  public static class Builder {
+    private List<PermissionTemplateDto> templates;
+    private List<TemplateUuidQualifier> defaultTemplates;
+    private Table<Long, String, Integer> userCountByTemplateIdAndPermission;
+    private Table<Long, String, Integer> groupCountByTemplateIdAndPermission;
+
+    private Builder() {
+      // prevents instantiation outside main class
+    }
+
+    public SearchTemplatesData build() {
+      checkState(templates != null);
+      checkState(defaultTemplates != null);
+      checkState(userCountByTemplateIdAndPermission != null);
+      checkState(groupCountByTemplateIdAndPermission != null);
+
+      return new SearchTemplatesData(this);
+    }
+
+    public Builder templates(List<PermissionTemplateDto> templates) {
+      this.templates = templates;
+      return this;
+    }
+
+    public Builder defaultTemplates(List<TemplateUuidQualifier> defaultTemplates) {
+      this.defaultTemplates = defaultTemplates;
+      return this;
+    }
+
+    public Builder userCountByTemplateIdAndPermission(Table<Long, String, Integer> userCountByTemplateIdAndPermission) {
+      this.userCountByTemplateIdAndPermission = userCountByTemplateIdAndPermission;
+      return this;
+    }
+
+    public Builder groupCountByTemplateIdAndPermission(Table<Long, String, Integer> groupCountByTemplateIdAndPermission) {
+      this.groupCountByTemplateIdAndPermission = groupCountByTemplateIdAndPermission;
+      return this;
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesDataLoader.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SearchTemplatesDataLoader.java
new file mode 100644 (file)
index 0000000..dd56114
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Table;
+import com.google.common.collect.TreeBasedTable;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.apache.ibatis.session.ResultContext;
+import org.apache.ibatis.session.ResultHandler;
+import org.sonar.api.server.ws.Request;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.CountByTemplateAndPermissionDto;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ws.template.DefaultPermissionTemplateFinder.TemplateUuidQualifier;
+
+import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
+import static org.sonar.server.permission.ws.template.SearchTemplatesData.newBuilder;
+
+public class SearchTemplatesDataLoader {
+  private final DbClient dbClient;
+  private final DefaultPermissionTemplateFinder defaultPermissionTemplateFinder;
+
+  public SearchTemplatesDataLoader(DbClient dbClient, DefaultPermissionTemplateFinder defaultPermissionTemplateFinder) {
+    this.dbClient = dbClient;
+    this.defaultPermissionTemplateFinder = defaultPermissionTemplateFinder;
+  }
+
+  public SearchTemplatesData load(Request wsRequest) {
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      SearchTemplatesData.Builder data = newBuilder();
+      List<PermissionTemplateDto> templates = searchTemplates(dbSession, wsRequest);
+      List<Long> templateIds = Lists.transform(templates, TemplateToIdFunction.INSTANCE);
+      List<TemplateUuidQualifier> defaultTemplates = defaultPermissionTemplateFinder.getDefaultTemplatesByQualifier();
+
+      data.templates(templates)
+        .defaultTemplates(defaultTemplates)
+        .userCountByTemplateIdAndPermission(userCountByTemplateIdAndPermission(dbSession, templateIds))
+        .groupCountByTemplateIdAndPermission(groupCountByTemplateIdAndPermission(dbSession, templateIds));
+
+      return data.build();
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private List<PermissionTemplateDto> searchTemplates(DbSession dbSession, Request wsRequest) {
+    String nameMatch = wsRequest.param(TEXT_QUERY);
+
+    return nameMatch == null ?
+      dbClient.permissionTemplateDao().selectAll(dbSession)
+      : dbClient.permissionTemplateDao().selectAll(dbSession, nameMatch);
+  }
+
+  private Table<Long, String, Integer> userCountByTemplateIdAndPermission(DbSession dbSession, List<Long> templateIds) {
+    final Table<Long, String, Integer> userCountByTemplateIdAndPermission = TreeBasedTable.create();
+
+    dbClient.permissionTemplateDao().usersCountByTemplateIdAndPermission(dbSession, templateIds, new ResultHandler() {
+      @Override
+      public void handleResult(ResultContext context) {
+        CountByTemplateAndPermissionDto row = (CountByTemplateAndPermissionDto) context.getResultObject();
+        userCountByTemplateIdAndPermission.put(row.getTemplateId(), row.getPermission(), row.getCount());
+      }
+    });
+
+    return userCountByTemplateIdAndPermission;
+  }
+
+  private Table<Long, String, Integer> groupCountByTemplateIdAndPermission(DbSession dbSession, List<Long> templateIds) {
+    final Table<Long, String, Integer> userCountByTemplateIdAndPermission = TreeBasedTable.create();
+
+    dbClient.permissionTemplateDao().groupsCountByTemplateIdAndPermission(dbSession, templateIds, new ResultHandler() {
+      @Override
+      public void handleResult(ResultContext context) {
+        CountByTemplateAndPermissionDto row = (CountByTemplateAndPermissionDto) context.getResultObject();
+        userCountByTemplateIdAndPermission.put(row.getTemplateId(), row.getPermission(), row.getCount());
+      }
+    });
+
+    return userCountByTemplateIdAndPermission;
+  }
+
+  private enum TemplateToIdFunction implements Function<PermissionTemplateDto, Long> {
+    INSTANCE;
+
+    @Override
+    public Long apply(@Nonnull PermissionTemplateDto template) {
+      return template.getId();
+    }
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java
new file mode 100644 (file)
index 0000000..d2ffbb4
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.Set;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.permission.ws.WsTemplateRef;
+import org.sonar.server.platform.PersistentSettings;
+import org.sonar.server.user.UserSession;
+
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Ordering.natural;
+import static java.lang.String.format;
+import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_QUALIFIER;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
+import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
+
+public class SetDefaultTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final PermissionDependenciesFinder finder;
+  private final ResourceTypes resourceTypes;
+  private final PersistentSettings settings;
+  private final UserSession userSession;
+  private final I18n i18n;
+
+  public SetDefaultTemplateAction(DbClient dbClient, PermissionDependenciesFinder finder, ResourceTypes resourceTypes, PersistentSettings settings, UserSession userSession,
+    I18n i18n) {
+    this.dbClient = dbClient;
+    this.finder = finder;
+    this.resourceTypes = resourceTypes;
+    this.settings = settings;
+    this.userSession = userSession;
+    this.i18n = i18n;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context.createAction("set_default_template")
+      .setDescription("Set a permission template as default.<br />" +
+        "It requires administration permissions to access.")
+      .setPost(true)
+      .setSince("5.2")
+      .setHandler(this);
+
+    createTemplateParameters(action);
+
+    action.createParam(PARAM_QUALIFIER)
+      .setDescription("Project qualifier. Possible values are:" + buildRootQualifiersDescription())
+      .setDefaultValue(Qualifiers.PROJECT)
+      .setPossibleValues(getRootQualifiers());
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    checkGlobalAdminUser(userSession);
+
+    String qualifier = wsRequest.mandatoryParam(PARAM_QUALIFIER);
+
+    PermissionTemplateDto template = getTemplate(wsRequest);
+    validateQualifier(qualifier, getRootQualifiers());
+    setDefaultTemplateUuid(template.getUuid(), qualifier);
+    wsResponse.noContent();
+  }
+
+  private Set<String> getRootQualifiers() {
+    return from(resourceTypes.getRoots())
+      .transform(RESOURCE_TYPE_TO_QUALIFIER)
+      .toSortedSet(natural());
+  }
+
+  private String buildRootQualifiersDescription() {
+    StringBuilder description = new StringBuilder();
+    description.append("<ul>");
+    String qualifierPattern = "<li>%s - %s</li>";
+    for (String qualifier : getRootQualifiers()) {
+      description.append(format(qualifierPattern, qualifier, i18n(qualifier)));
+    }
+    description.append("</ul>");
+
+    return description.toString();
+  }
+
+  private String i18n(String qualifier) {
+    String qualifiersPropertyPrefix = "qualifiers.";
+    return i18n.message(userSession.locale(), qualifiersPropertyPrefix + qualifier, "");
+  }
+
+  private PermissionTemplateDto getTemplate(Request wsRequest) {
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      return finder.getTemplate(dbSession, WsTemplateRef.fromRequest(wsRequest));
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private void setDefaultTemplateUuid(String templateUuid, String qualifier) {
+    settings.saveProperty(defaultRootQualifierTemplateProperty(qualifier), templateUuid);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/UpdateTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/UpdateTemplateAction.java
new file mode 100644 (file)
index 0000000..8eaf61c
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.Date;
+import javax.annotation.Nullable;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.PermissionsWsAction;
+import org.sonar.server.permission.ws.WsTemplateRef;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.WsPermissions.PermissionTemplate;
+import org.sonarqube.ws.WsPermissions.WsUpdatePermissionTemplateResponse;
+
+import static com.google.common.base.Objects.firstNonNull;
+import static java.lang.String.format;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createIdParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateDescriptionParameter;
+import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateProjectKeyPatternParameter;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.MSG_TEMPLATE_WITH_SAME_NAME;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPattern;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateTemplateNameFormat;
+import static org.sonar.server.permission.ws.template.PermissionTemplateDtoToPermissionTemplateResponse.toPermissionTemplateResponse;
+import static org.sonar.server.ws.WsUtils.checkRequest;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+
+public class UpdateTemplateAction implements PermissionsWsAction {
+  private final DbClient dbClient;
+  private final UserSession userSession;
+  private final System2 system;
+  private final PermissionDependenciesFinder finder;
+
+  public UpdateTemplateAction(DbClient dbClient, UserSession userSession, System2 system, PermissionDependenciesFinder finder) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+    this.system = system;
+    this.finder = finder;
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context.createAction("update_template")
+      .setDescription("Update a permission template.<br />" +
+        "It requires administration permissions to access.")
+      .setResponseExample(getClass().getResource("update_template-example.json"))
+      .setSince("5.2")
+      .setPost(true)
+      .setHandler(this);
+
+    createIdParameter(action);
+
+    action.createParam(PARAM_NAME)
+      .setDescription("Name")
+      .setExampleValue("Financial Service Permissions");
+
+    createTemplateProjectKeyPatternParameter(action);
+    createTemplateDescriptionParameter(action);
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    checkGlobalAdminUser(userSession);
+
+    String uuid = wsRequest.mandatoryParam(PARAM_ID);
+    String nameParam = wsRequest.param(PARAM_NAME);
+    String descriptionParam = wsRequest.param(PARAM_DESCRIPTION);
+    String projectPatternParam = wsRequest.param(PARAM_PATTERN);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      PermissionTemplateDto templateToUpdate = getAndBuildTemplateToUpdate(dbSession, uuid, nameParam, descriptionParam, projectPatternParam);
+      validateTemplate(dbSession, templateToUpdate);
+      PermissionTemplateDto updatedTemplate = updateTemplate(dbSession, templateToUpdate);
+
+      WsUpdatePermissionTemplateResponse response = buildResponse(updatedTemplate);
+      writeProtobuf(response, wsRequest, wsResponse);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private void validateTemplate(DbSession dbSession, PermissionTemplateDto templateToUpdate) {
+    validateTemplateNameForUpdate(dbSession, templateToUpdate.getName(), templateToUpdate.getId());
+    validateProjectPattern(templateToUpdate.getKeyPattern());
+  }
+
+  private PermissionTemplateDto getAndBuildTemplateToUpdate(DbSession dbSession, String uuid, @Nullable String newName, @Nullable String newDescription,
+    @Nullable String newProjectKeyPattern) {
+    PermissionTemplateDto templateToUpdate = finder.getTemplate(dbSession, WsTemplateRef.newTemplateRef(uuid, null));
+    templateToUpdate.setName(firstNonNull(newName, templateToUpdate.getName()));
+    templateToUpdate.setDescription(firstNonNull(newDescription, templateToUpdate.getDescription()));
+    templateToUpdate.setKeyPattern(firstNonNull(newProjectKeyPattern, templateToUpdate.getKeyPattern()));
+    templateToUpdate.setUpdatedAt(new Date(system.now()));
+
+    return templateToUpdate;
+  }
+
+  private PermissionTemplateDto updateTemplate(DbSession dbSession, PermissionTemplateDto templateToUpdate) {
+    return dbClient.permissionTemplateDao().update(dbSession, templateToUpdate);
+  }
+
+  private static WsUpdatePermissionTemplateResponse buildResponse(PermissionTemplateDto permissionTemplate) {
+    PermissionTemplate permissionTemplateBuilder = toPermissionTemplateResponse(permissionTemplate);
+    return WsUpdatePermissionTemplateResponse.newBuilder().setPermissionTemplate(permissionTemplateBuilder).build();
+  }
+
+  private void validateTemplateNameForUpdate(DbSession dbSession, String name, long id) {
+    validateTemplateNameFormat(name);
+
+    PermissionTemplateDto permissionTemplateWithSameName = dbClient.permissionTemplateDao().selectByName(dbSession, name);
+    checkRequest(permissionTemplateWithSameName == null || permissionTemplateWithSameName.getId() == id,
+      format(MSG_TEMPLATE_WITH_SAME_NAME, name));
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/package-info.java
new file mode 100644 (file)
index 0000000..a252c1b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.permission.ws.template;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/create_template-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/create_template-example.json
deleted file mode 100644 (file)
index 5a49450..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "permissionTemplate": {
-    "id": "af8cb8cc-1e78-4c4e-8c00-ee8e814009a5",
-    "name": "Finance",
-    "description": "Permissions for financially related projects",
-    "projectKeyPattern": ".*\\.finance\\..*",
-    "createdAt": "2015-08-25T16:18:48+0200",
-    "updatedAt": "2015-08-25T16:18:48+0200"
-  }
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/search_templates-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/search_templates-example.json
deleted file mode 100644 (file)
index 523c5eb..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-{
-  "permissionTemplates": [
-    {
-      "id": "AU-TpxcA-iU5OvuD2FL0",
-      "name": "Default template for Developers",
-      "projectKeyPattern": ".*sonar.developer.*",
-      "createdAt": "2004-11-15T07:26:40+0100",
-      "updatedAt": "2004-11-19T22:33:20+0100",
-      "permissions": [
-        {
-          "key": "user",
-          "usersCount": 0,
-          "groupsCount": 1
-        }
-      ]
-    },
-    {
-      "id": "AU-Tpxb--iU5OvuD2FLy",
-      "name": "Default template for Projects",
-      "description": "Template for new projects",
-      "createdAt": "2001-09-09T03:46:40+0200",
-      "updatedAt": "2001-09-09T03:46:40+0200",
-      "permissions": [
-        {
-          "key": "admin",
-          "usersCount": 0,
-          "groupsCount": 1
-        },
-        {
-          "key": "codeviewer",
-          "usersCount": 1,
-          "groupsCount": 0
-        },
-        {
-          "key": "issueadmin",
-          "usersCount": 3,
-          "groupsCount": 0
-        }
-      ]
-    },
-    {
-      "id": "AU-TpxcA-iU5OvuD2FLz",
-      "name": "Default template for Views",
-      "description": "Template for new views",
-      "projectKeyPattern": ".*sonar.views.*",
-      "createdAt": "2001-09-09T03:46:40+0200",
-      "updatedAt": "2004-11-09T12:33:20+0100",
-      "permissions": [
-        {
-          "key": "issueadmin",
-          "usersCount": 0,
-          "groupsCount": 3
-        },
-        {
-          "key": "user",
-          "usersCount": 2,
-          "groupsCount": 0
-        }
-      ]
-    }
-  ],
-  "defaultTemplates": [
-    {
-      "templateId": "AU-Tpxb--iU5OvuD2FLy",
-      "qualifier": "TRK"
-    },
-    {
-      "templateId": "AU-TpxcA-iU5OvuD2FLz",
-      "qualifier": "VW"
-    },
-    {
-      "templateId": "AU-TpxcA-iU5OvuD2FL0",
-      "qualifier": "DEV"
-    }
-  ],
-  "permissions": [
-    {
-      "key": "user",
-      "name": "Browse",
-      "description": "Ability to access a project, browse its measures, and create/edit issues for it."
-    },
-    {
-      "key": "admin",
-      "name": "Administer",
-      "description": "Ability to access project settings and perform administration tasks. (Users will also need \"Browse\" permission)"
-    },
-    {
-      "key": "issueadmin",
-      "name": "Administer Issues",
-      "description": "Grants the permission to perform advanced editing on issues: marking an issue False Positive / Won\u0027t Fix or changing an Issue\u0027s severity. (Users will also need \"Browse\" permission)"
-    },
-    {
-      "key": "codeviewer",
-      "name": "See Source Code",
-      "description": "Ability to view the project\u0027s source code. (Users will also need \"Browse\" permission)"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/create_template-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/create_template-example.json
new file mode 100644 (file)
index 0000000..5a49450
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "permissionTemplate": {
+    "id": "af8cb8cc-1e78-4c4e-8c00-ee8e814009a5",
+    "name": "Finance",
+    "description": "Permissions for financially related projects",
+    "projectKeyPattern": ".*\\.finance\\..*",
+    "createdAt": "2015-08-25T16:18:48+0200",
+    "updatedAt": "2015-08-25T16:18:48+0200"
+  }
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/search_templates-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/search_templates-example.json
new file mode 100644 (file)
index 0000000..523c5eb
--- /dev/null
@@ -0,0 +1,98 @@
+{
+  "permissionTemplates": [
+    {
+      "id": "AU-TpxcA-iU5OvuD2FL0",
+      "name": "Default template for Developers",
+      "projectKeyPattern": ".*sonar.developer.*",
+      "createdAt": "2004-11-15T07:26:40+0100",
+      "updatedAt": "2004-11-19T22:33:20+0100",
+      "permissions": [
+        {
+          "key": "user",
+          "usersCount": 0,
+          "groupsCount": 1
+        }
+      ]
+    },
+    {
+      "id": "AU-Tpxb--iU5OvuD2FLy",
+      "name": "Default template for Projects",
+      "description": "Template for new projects",
+      "createdAt": "2001-09-09T03:46:40+0200",
+      "updatedAt": "2001-09-09T03:46:40+0200",
+      "permissions": [
+        {
+          "key": "admin",
+          "usersCount": 0,
+          "groupsCount": 1
+        },
+        {
+          "key": "codeviewer",
+          "usersCount": 1,
+          "groupsCount": 0
+        },
+        {
+          "key": "issueadmin",
+          "usersCount": 3,
+          "groupsCount": 0
+        }
+      ]
+    },
+    {
+      "id": "AU-TpxcA-iU5OvuD2FLz",
+      "name": "Default template for Views",
+      "description": "Template for new views",
+      "projectKeyPattern": ".*sonar.views.*",
+      "createdAt": "2001-09-09T03:46:40+0200",
+      "updatedAt": "2004-11-09T12:33:20+0100",
+      "permissions": [
+        {
+          "key": "issueadmin",
+          "usersCount": 0,
+          "groupsCount": 3
+        },
+        {
+          "key": "user",
+          "usersCount": 2,
+          "groupsCount": 0
+        }
+      ]
+    }
+  ],
+  "defaultTemplates": [
+    {
+      "templateId": "AU-Tpxb--iU5OvuD2FLy",
+      "qualifier": "TRK"
+    },
+    {
+      "templateId": "AU-TpxcA-iU5OvuD2FLz",
+      "qualifier": "VW"
+    },
+    {
+      "templateId": "AU-TpxcA-iU5OvuD2FL0",
+      "qualifier": "DEV"
+    }
+  ],
+  "permissions": [
+    {
+      "key": "user",
+      "name": "Browse",
+      "description": "Ability to access a project, browse its measures, and create/edit issues for it."
+    },
+    {
+      "key": "admin",
+      "name": "Administer",
+      "description": "Ability to access project settings and perform administration tasks. (Users will also need \"Browse\" permission)"
+    },
+    {
+      "key": "issueadmin",
+      "name": "Administer Issues",
+      "description": "Grants the permission to perform advanced editing on issues: marking an issue False Positive / Won\u0027t Fix or changing an Issue\u0027s severity. (Users will also need \"Browse\" permission)"
+    },
+    {
+      "key": "codeviewer",
+      "name": "See Source Code",
+      "description": "Ability to view the project\u0027s source code. (Users will also need \"Browse\" permission)"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/update_template-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/template/update_template-example.json
new file mode 100644 (file)
index 0000000..3ef7211
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "permissionTemplate": {
+    "id": "af8cb8cc-1e78-4c4e-8c00-ee8e814009a5",
+    "name": "Finance",
+    "description": "Permissions for financially related projects",
+    "projectKeyPattern": ".*\\.finance\\..*",
+    "createdAt": "2001-09-09T03:46:40+0200",
+    "updatedAt": "2015-08-25T16:18:48+0200"
+  }
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/update_template-example.json b/server/sonar-server/src/main/resources/org/sonar/server/permission/ws/update_template-example.json
deleted file mode 100644 (file)
index 3ef7211..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "permissionTemplate": {
-    "id": "af8cb8cc-1e78-4c4e-8c00-ee8e814009a5",
-    "name": "Finance",
-    "description": "Permissions for financially related projects",
-    "projectKeyPattern": ".*\\.finance\\..*",
-    "createdAt": "2001-09-09T03:46:40+0200",
-    "updatedAt": "2015-08-25T16:18:48+0200"
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java
deleted file mode 100644 (file)
index d84111c..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Function;
-import java.util.List;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.DbTests;
-
-import static com.google.common.collect.FluentIterable.from;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.security.DefaultGroups.ANYONE;
-import static org.sonar.api.web.UserRole.ADMIN;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.db.user.GroupMembershipQuery.IN;
-import static org.sonar.db.user.GroupTesting.newGroupDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
-
-@Category(DbTests.class)
-public class AddGroupToTemplateActionTest {
-
-  private static final String GROUP_NAME = "group-name";
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  GroupDto group;
-  PermissionTemplateDto permissionTemplate;
-
-  @Before
-  public void setUp() {
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
-    ws = new WsActionTester(new AddGroupToTemplateAction(dbClient, dependenciesFinder, userSession));
-
-    group = insertGroup(newGroupDto().setName(GROUP_NAME));
-    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
-    commit();
-  }
-
-  @Test
-  public void add_group_to_template() {
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
-  }
-
-  @Test
-  public void add_group_to_template_by_name() {
-    ws.newRequest()
-      .setParam(PARAM_GROUP_NAME, GROUP_NAME)
-      .setParam(PARAM_PERMISSION, CODEVIEWER)
-      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
-      .execute();
-    commit();
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
-  }
-
-  @Test
-  public void add_with_group_id() {
-    ws.newRequest()
-      .setParam(PARAM_TEMPLATE_ID, permissionTemplate.getKee())
-      .setParam(PARAM_PERMISSION, CODEVIEWER)
-      .setParam(PARAM_GROUP_ID, String.valueOf(group.getId()))
-      .execute();
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
-  }
-
-  @Test
-  public void does_not_add_a_group_twice() {
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), ISSUE_ADMIN);
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), ISSUE_ADMIN);
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), ISSUE_ADMIN)).containsExactly(GROUP_NAME);
-  }
-
-  @Test
-  public void add_anyone_group_to_template() {
-    newRequest(ANYONE, permissionTemplate.getKee(), CODEVIEWER);
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(ANYONE);
-  }
-
-  @Test
-  public void fail_if_add_anyone_group_to_admin_permission() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage(String.format("It is not possible to add the '%s' permission to the '%s' group.", UserRole.ADMIN, ANYONE));
-
-    newRequest(ANYONE, permissionTemplate.getKee(), ADMIN);
-  }
-
-  @Test
-  public void fail_if_not_a_project_permission() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
-  }
-
-  @Test
-  public void fail_if_insufficient_privileges() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_group_params_missing() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(null, permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_permission_missing() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), null);
-  }
-
-  @Test
-  public void fail_if_template_uuid_and_name_missing() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(GROUP_NAME, null, CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_group_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Group with name 'unknown-group-name' is not found");
-
-    newRequest("unknown-group-name", permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_template_key_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
-
-    newRequest(GROUP_NAME, "unknown-key", CODEVIEWER);
-  }
-
-  private void newRequest(@Nullable String groupName, @Nullable String templateKey, @Nullable String permission) {
-    TestRequest request = ws.newRequest();
-    if (groupName != null) {
-      request.setParam(WsPermissionParameters.PARAM_GROUP_NAME, groupName);
-    }
-    if (templateKey != null) {
-      request.setParam(PARAM_TEMPLATE_ID, templateKey);
-    }
-    if (permission != null) {
-      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
-    }
-
-    request.execute();
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private GroupDto insertGroup(GroupDto groupDto) {
-    return dbClient.groupDao().insert(dbSession, groupDto);
-  }
-
-  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
-  }
-
-  private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
-    return from(dbClient.permissionTemplateDao()
-      .selectGroups(dbSession, permissionQuery, templateId))
-      .transform(GroupWithPermissionToGroupName.INSTANCE)
-      .toList();
-  }
-
-  private enum GroupWithPermissionToGroupName implements Function<GroupWithPermissionDto, String> {
-    INSTANCE;
-
-    @Override
-    public String apply(@Nonnull GroupWithPermissionDto groupWithPermission) {
-      return groupWithPermission.getName();
-    }
-
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java
deleted file mode 100644 (file)
index 6a28cbd..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Function;
-import java.util.List;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionQuery;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.permission.UserWithPermissionDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.DbTests;
-
-import static com.google.common.collect.FluentIterable.from;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.db.user.GroupMembershipQuery.IN;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
-
-@Category(DbTests.class)
-public class AddUserToTemplateActionTest {
-
-  private static final String USER_LOGIN = "user-login";
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  UserDto user;
-  PermissionTemplateDto permissionTemplate;
-
-  @Before
-  public void setUp() {
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
-    ws = new WsActionTester(new AddUserToTemplateAction(dbClient, dependenciesFinder, userSession));
-
-    user = insertUser(newUserDto().setLogin(USER_LOGIN));
-    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
-    commit();
-  }
-
-  @Test
-  public void add_user_to_template() {
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), CODEVIEWER);
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(USER_LOGIN);
-  }
-
-  @Test
-  public void add_user_to_template_by_name() {
-    ws.newRequest()
-      .setParam(PARAM_USER_LOGIN, USER_LOGIN)
-      .setParam(PARAM_PERMISSION, CODEVIEWER)
-      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
-      .execute();
-    commit();
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(USER_LOGIN);
-  }
-
-  @Test
-  public void does_not_add_a_user_twice() {
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), ISSUE_ADMIN);
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), ISSUE_ADMIN);
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), ISSUE_ADMIN)).containsExactly(USER_LOGIN);
-  }
-
-  @Test
-  public void fail_if_not_a_project_permission() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
-  }
-
-  @Test
-  public void fail_if_insufficient_privileges() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_user_missing() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(null, permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_permission_missing() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), null);
-  }
-
-  @Test
-  public void fail_if_template_uuid_and_name_are_missing() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(USER_LOGIN, null, CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_user_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("User with login 'unknown-login' is not found");
-
-    newRequest("unknown-login", permissionTemplate.getKee(), CODEVIEWER);
-  }
-
-  @Test
-  public void fail_if_template_key_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
-
-    newRequest(USER_LOGIN, "unknown-key", CODEVIEWER);
-  }
-
-  private void newRequest(@Nullable String userLogin, @Nullable String templateKey, @Nullable String permission) {
-    TestRequest request = ws.newRequest();
-    if (userLogin != null) {
-      request.setParam(PARAM_USER_LOGIN, userLogin);
-    }
-    if (templateKey != null) {
-      request.setParam(WsPermissionParameters.PARAM_TEMPLATE_ID, templateKey);
-    }
-    if (permission != null) {
-      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
-    }
-
-    request.execute();
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private UserDto insertUser(UserDto userDto) {
-    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
-  }
-
-  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
-  }
-
-  private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
-    return from(dbClient.permissionTemplateDao()
-      .selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE))
-      .transform(UserWithPermissionToUserLogin.INSTANCE)
-      .toList();
-  }
-
-  private enum UserWithPermissionToUserLogin implements Function<UserWithPermissionDto, String> {
-    INSTANCE;
-
-    @Override
-    public String apply(@Nonnull UserWithPermissionDto userWithPermission) {
-      return userWithPermission.getLogin();
-    }
-
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/ApplyTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/ApplyTemplateActionTest.java
deleted file mode 100644 (file)
index 27f64b1..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import java.util.List;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
-import org.sonar.db.permission.PermissionRepository;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.permission.UserWithPermissionDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.GroupRoleDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserRoleDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
-import org.sonar.server.permission.PermissionFinder;
-import org.sonar.server.permission.PermissionService;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.TestResponse;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.sonar.db.component.ComponentTesting.newProjectDto;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.db.user.GroupMembershipQuery.IN;
-import static org.sonar.db.user.GroupTesting.newGroupDto;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PROJECT_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PROJECT_KEY;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
-
-@Category(DbTests.class)
-public class ApplyTemplateActionTest {
-
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-
-  UserDto user1;
-  UserDto user2;
-  GroupDto group1;
-  GroupDto group2;
-  ComponentDto project;
-  PermissionTemplateDto template1;
-  PermissionTemplateDto template2;
-  IssueAuthorizationIndexer issueAuthorizationIndexer = mock(IssueAuthorizationIndexer.class);
-
-  @Before
-  public void setUp() {
-    userSession.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-
-    PermissionRepository repository = new PermissionRepository(dbClient, new Settings());
-    PermissionFinder permissionFinder = new PermissionFinder(dbClient);
-    ComponentFinder componentFinder = new ComponentFinder(dbClient);
-    PermissionService permissionService = new PermissionService(dbClient, repository, issueAuthorizationIndexer, userSession, componentFinder);
-    PermissionDependenciesFinder permissionDependenciesFinder = new PermissionDependenciesFinder(dbClient, componentFinder);
-
-    ApplyTemplateAction underTest = new ApplyTemplateAction(dbClient, permissionService, permissionDependenciesFinder);
-    ws = new WsActionTester(underTest);
-
-    user1 = insertUser(newUserDto().setLogin("user-login-1"));
-    user2 = insertUser(newUserDto().setLogin("user-login-2"));
-    group1 = insertGroup(newGroupDto().setName("group-name-1"));
-    group2 = insertGroup(newGroupDto().setName("group-name-2"));
-
-    // template 1
-    template1 = insertTemplate(newPermissionTemplateDto().setUuid("permission-template-uuid-1"));
-    addUserToTemplate(user1, template1, UserRole.CODEVIEWER);
-    addUserToTemplate(user2, template1, UserRole.ISSUE_ADMIN);
-    addGroupToTemplate(group1, template1, UserRole.ADMIN);
-    addGroupToTemplate(group2, template1, UserRole.USER);
-    // template 2
-    template2 = insertTemplate(newPermissionTemplateDto().setUuid("permission-template-uuid-2"));
-    addUserToTemplate(user1, template2, UserRole.USER);
-    addUserToTemplate(user2, template2, UserRole.USER);
-    addGroupToTemplate(group1, template2, UserRole.USER);
-    addGroupToTemplate(group2, template2, UserRole.USER);
-
-    project = insertProject(newProjectDto("project-uuid-1"));
-    addUserPermissionToProject(user1, project, UserRole.ADMIN);
-    addUserPermissionToProject(user2, project, UserRole.ADMIN);
-    addGroupPermissionToProject(group1, project, UserRole.ADMIN);
-    addGroupPermissionToProject(group2, project, UserRole.ADMIN);
-
-    commit();
-  }
-
-  @Test
-  public void apply_template_with_project_uuid() {
-    assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).hasSize(2);
-    assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).hasSize(2);
-
-    newRequest(template1.getUuid(), project.uuid(), null);
-
-    assertTemplate1AppliedToProject();
-    verify(issueAuthorizationIndexer).index();
-  }
-
-  @Test
-  public void apply_template_with_project_uuid_by_template_name() {
-    ws.newRequest()
-      .setParam(PARAM_TEMPLATE_NAME, template1.getName().toUpperCase())
-      .setParam(PARAM_PROJECT_ID, project.uuid())
-      .execute();
-    commit();
-
-    assertTemplate1AppliedToProject();
-  }
-
-  @Test
-  public void apply_template_with_project_key() {
-    newRequest(template1.getUuid(), null, project.key());
-
-    assertTemplate1AppliedToProject();
-  }
-
-  @Test
-  public void fail_when_unknown_template() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Permission template with id 'unknown-template-uuid' is not found");
-
-    newRequest("unknown-template-uuid", project.uuid(), null);
-  }
-
-  @Test
-  public void fail_when_unknown_project_uuid() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Project id 'unknown-project-uuid' not found");
-
-    newRequest(template1.getUuid(), "unknown-project-uuid", null);
-  }
-
-  @Test
-  public void fail_when_unknown_project_key() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Project key 'unknown-project-key' not found");
-
-    newRequest(template1.getUuid(), null, "unknown-project-key");
-  }
-
-  @Test
-  public void fail_when_template_is_not_provided() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(null, project.uuid(), null);
-  }
-
-  @Test
-  public void fail_when_project_uuid_and_key_not_provided() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("Project id or project key must be provided, not both.");
-
-    newRequest(template1.getUuid(), null, null);
-  }
-
-  @Test
-  public void fail_when_anonymous() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(template1.getUuid(), project.uuid(), null);
-  }
-
-  @Test
-  public void fail_when_insufficient_privileges() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.login().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-
-    newRequest(template1.getUuid(), project.uuid(), null);
-  }
-
-  private void assertTemplate1AppliedToProject() {
-    assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).extracting("name").containsExactly(group1.getName());
-    assertThat(selectProjectPermissionGroups(project, UserRole.USER)).extracting("name").containsExactly(group2.getName());
-    assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty();
-    assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).extracting("login").containsExactly(user1.getLogin());
-    assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).extracting("login").containsExactly(user2.getLogin());
-  }
-
-  private TestResponse newRequest(@Nullable String templateUuid, @Nullable String projectUuid, @Nullable String projectKey) {
-    TestRequest request = ws.newRequest();
-    if (templateUuid != null) {
-      request.setParam(PARAM_TEMPLATE_ID, templateUuid);
-    }
-    if (projectUuid != null) {
-      request.setParam(PARAM_PROJECT_ID, projectUuid);
-    }
-    if (projectKey != null) {
-      request.setParam(PARAM_PROJECT_KEY, projectKey);
-    }
-
-    TestResponse result = request.execute();
-    commit();
-
-    return result;
-  }
-
-  private ComponentDto insertProject(ComponentDto project) {
-    dbClient.componentDao().insert(dbSession, project);
-    return dbClient.componentDao().selectOrFailByUuid(dbSession, project.uuid());
-  }
-
-  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
-    return dbClient.permissionTemplateDao().insert(dbSession, template);
-  }
-
-  private UserDto insertUser(UserDto userDto) {
-    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
-  }
-
-  private GroupDto insertGroup(GroupDto group) {
-    return dbClient.groupDao().insert(dbSession, group);
-  }
-
-  private void addUserToTemplate(UserDto user, PermissionTemplateDto permissionTemplate, String permission) {
-    dbClient.permissionTemplateDao().insertUserPermission(dbSession, permissionTemplate.getId(), user.getId(), permission);
-  }
-
-  private void addGroupToTemplate(GroupDto group, PermissionTemplateDto permissionTemplate, String permission) {
-    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, permissionTemplate.getId(), group.getId(), permission);
-  }
-
-  private void addUserPermissionToProject(UserDto user, ComponentDto project, String permission) {
-    dbClient.roleDao().insertUserRole(dbSession, new UserRoleDto()
-      .setRole(permission)
-      .setUserId(user.getId())
-      .setResourceId(project.getId()));
-  }
-
-  private void addGroupPermissionToProject(GroupDto group, ComponentDto project, String permission) {
-    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto()
-      .setRole(permission)
-      .setResourceId(project.getId())
-      .setGroupId(group.getId()));
-  }
-
-  private List<GroupWithPermissionDto> selectProjectPermissionGroups(ComponentDto project, String permission) {
-    return FluentIterable.from(dbClient.permissionDao().selectGroups(dbSession, query(permission), project.getId()))
-      .filter(new PermissionNotNull())
-      .toList();
-  }
-
-  private List<UserWithPermissionDto> selectProjectPermissionUsers(ComponentDto project, String permission) {
-    return dbClient.permissionDao().selectUsers(dbSession, query(permission), project.getId(), 0, Integer.MAX_VALUE);
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private static PermissionQuery query(String permission) {
-    return PermissionQuery.builder().membership(IN).permission(permission).build();
-  }
-
-  private static class PermissionNotNull implements Predicate<GroupWithPermissionDto> {
-    @Override
-    public boolean apply(@Nullable GroupWithPermissionDto input) {
-      return input.getPermission() != null;
-    }
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/CreateTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/CreateTemplateActionTest.java
deleted file mode 100644 (file)
index 160aebb..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.TestResponse;
-import org.sonar.server.ws.WsActionTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class CreateTemplateActionTest {
-
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  System2 system = mock(System2.class);
-
-  @Before
-  public void setUp() {
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-    when(system.now()).thenReturn(1440512328743L);
-
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-    ws = new WsActionTester(new CreateTemplateAction(dbClient, userSession, system));
-  }
-
-  @Test
-  public void create_full_permission_template() {
-    TestResponse result = newRequest("Finance", "Permissions for financially related projects", ".*\\.finance\\..*");
-
-    assertJson(result.getInput())
-      .ignoreFields("id")
-      .isSimilarTo(getClass().getResource("create_template-example.json"));
-    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
-    assertThat(finance.getName()).isEqualTo("Finance");
-    assertThat(finance.getDescription()).isEqualTo("Permissions for financially related projects");
-    assertThat(finance.getKeyPattern()).isEqualTo(".*\\.finance\\..*");
-    assertThat(finance.getKee()).isNotEmpty();
-    assertThat(finance.getCreatedAt().getTime()).isEqualTo(1440512328743L);
-    assertThat(finance.getUpdatedAt().getTime()).isEqualTo(1440512328743L);
-  }
-
-  @Test
-  public void create_minimalist_permission_template() {
-    newRequest("Finance", null, null);
-
-    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
-    assertThat(finance.getName()).isEqualTo("Finance");
-    assertThat(finance.getDescription()).isNullOrEmpty();
-    assertThat(finance.getKeyPattern()).isNullOrEmpty();
-    assertThat(finance.getKee()).isNotEmpty();
-    assertThat(finance.getCreatedAt().getTime()).isEqualTo(1440512328743L);
-    assertThat(finance.getUpdatedAt().getTime()).isEqualTo(1440512328743L);
-  }
-
-  @Test
-  public void fail_if_name_not_provided() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(null, null, null);
-  }
-
-  @Test
-  public void fail_if_name_empty() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The template name must not be blank");
-
-    newRequest("", null, null);
-  }
-
-  @Test
-  public void fail_if_regexp_if_not_valid() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The 'projectKeyPattern' parameter must be a valid Java regular expression. '[azerty' was passed");
-
-    newRequest("Finance", null, "[azerty");
-  }
-
-  @Test
-  public void fail_if_name_already_exists_in_database_case_insensitive() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("A template with the name 'Finance' already exists (case insensitive).");
-    insertTemplate(newPermissionTemplateDto().setName("finance"));
-    commit();
-
-    newRequest("Finance", null, null);
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest("Finance", null, null);
-  }
-
-  @Test
-  public void fail_if_not_admin() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest("Finance", null, null);
-  }
-
-  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
-    return dbClient.permissionTemplateDao().insert(dbSession, template);
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private TestResponse newRequest(@Nullable String name, @Nullable String description, @Nullable String projectPattern) {
-    TestRequest request = ws.newRequest();
-    if (name != null) {
-      request.setParam(PARAM_NAME, name);
-    }
-    if (description != null) {
-      request.setParam(PARAM_DESCRIPTION, description);
-    }
-    if (projectPattern != null) {
-      request.setParam(PARAM_PATTERN, projectPattern);
-    }
-
-    return request.execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/DefaultPermissionTemplateFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/DefaultPermissionTemplateFinderTest.java
deleted file mode 100644 (file)
index 5831af3..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.List;
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
-import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
-
-public class DefaultPermissionTemplateFinderTest {
-
-  ResourceTypes resourceTypes = mock(ResourceTypes.class);
-  Settings settings = new Settings();
-
-  DefaultPermissionTemplateFinder underTest;
-
-  @Before
-  public void setUp() {
-    underTest = new DefaultPermissionTemplateFinder(settings, resourceTypes);
-    settings
-      .setProperty(DEFAULT_TEMPLATE_PROPERTY, "default-template-uuid")
-      .setProperty(defaultRootQualifierTemplateProperty(Qualifiers.PROJECT), "default-project-template-uuid")
-      .setProperty(defaultRootQualifierTemplateProperty("DEV"), "default-dev-template-uuid")
-      .setProperty(defaultRootQualifierTemplateProperty(Qualifiers.VIEW), "default-view-template-uuid");
-    when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
-  }
-
-  @Test
-  public void get_default_template_uuids_in_settings() {
-    Set<String> result = underTest.getDefaultTemplateUuids();
-
-    assertThat(result).containsOnly("default-project-template-uuid", "default-view-template-uuid", "default-dev-template-uuid");
-  }
-
-  @Test
-  public void get_default_template_uuid_if_no_property() {
-    settings = new Settings();
-    settings.setProperty(DEFAULT_TEMPLATE_PROPERTY, "default-template-uuid");
-    underTest = new DefaultPermissionTemplateFinder(settings, resourceTypes);
-
-    Set<String> result = underTest.getDefaultTemplateUuids();
-
-    assertThat(result).containsOnly("default-template-uuid");
-  }
-
-  private static List<ResourceType> rootResourceTypes() {
-    ResourceType project = ResourceType.builder(Qualifiers.PROJECT).build();
-    ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
-    ResourceType dev = ResourceType.builder("DEV").build();
-
-    return asList(project, view, dev);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/DeleteTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/DeleteTemplateActionTest.java
deleted file mode 100644 (file)
index 33575ba..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.Collections;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.GroupTesting;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.TestResponse;
-import org.sonar.server.ws.WsActionTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.internal.util.collections.Sets.newSet;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
-
-public class DeleteTemplateActionTest {
-
-  static final String TEMPLATE_UUID = "permission-template-uuid";
-
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  DefaultPermissionTemplateFinder defaultTemplatePermissionFinder;
-
-  PermissionTemplateDto permissionTemplate;
-
-  @Before
-  public void setUp() {
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-    defaultTemplatePermissionFinder = mock(DefaultPermissionTemplateFinder.class);
-    when(defaultTemplatePermissionFinder.getDefaultTemplateUuids()).thenReturn(Collections.<String>emptySet());
-    PermissionDependenciesFinder finder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
-    ws = new WsActionTester(new DeleteTemplateAction(dbClient, userSession, finder, defaultTemplatePermissionFinder));
-
-    permissionTemplate = insertTemplateAndAssociatedPermissions(newPermissionTemplateDto().setKee(TEMPLATE_UUID));
-    PermissionTemplateDto permissionTemplateInDatabase = dbClient.permissionTemplateDao().selectByUuidWithUserAndGroupPermissions(dbSession, TEMPLATE_UUID);
-    assertThat(permissionTemplateInDatabase.getKee()).isEqualTo(TEMPLATE_UUID);
-    assertThat(permissionTemplateInDatabase.getGroupsPermissions()).isNotEmpty();
-    assertThat(permissionTemplateInDatabase.getUsersPermissions()).isNotEmpty();
-  }
-
-  @Test
-  public void delete_template_in_db() {
-    TestResponse result = newRequest(TEMPLATE_UUID);
-
-    assertThat(result.getInput()).isEmpty();
-    assertThat(dbClient.permissionTemplateDao().selectByUuidWithUserAndGroupPermissions(dbSession, TEMPLATE_UUID)).isNull();
-  }
-
-  @Test
-  public void delete_template_by_name_case_insensitive() {
-    ws.newRequest()
-      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
-      .execute();
-    commit();
-
-    assertThat(dbClient.permissionTemplateDao().selectByUuidWithUserAndGroupPermissions(dbSession, TEMPLATE_UUID)).isNull();
-  }
-
-  @Test
-  public void fail_if_uuid_is_not_known() {
-    expectedException.expect(NotFoundException.class);
-
-    newRequest("unknown-template-uuid");
-  }
-
-  @Test
-  public void fail_if_template_is_default() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("It is not possible to delete a default template");
-    when(defaultTemplatePermissionFinder.getDefaultTemplateUuids()).thenReturn(newSet(TEMPLATE_UUID));
-
-    newRequest(TEMPLATE_UUID);
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(TEMPLATE_UUID);
-  }
-
-  @Test
-  public void fail_if_not_admin() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.login().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest(TEMPLATE_UUID);
-  }
-
-  @Test
-  public void fail_if_uuid_is_not_provided() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(null);
-  }
-
-  private PermissionTemplateDto insertTemplateAndAssociatedPermissions(PermissionTemplateDto template) {
-    dbClient.permissionTemplateDao().insert(dbSession, template);
-    UserDto user = dbClient.userDao().insert(dbSession, UserTesting.newUserDto().setActive(true));
-    GroupDto group = dbClient.groupDao().insert(dbSession, GroupTesting.newGroupDto());
-    dbClient.permissionTemplateDao().insertUserPermission(dbSession, template.getId(), user.getId(), UserRole.ADMIN);
-    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getId(), group.getId(), UserRole.CODEVIEWER);
-    commit();
-
-    return template;
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private TestResponse newRequest(@Nullable String id) {
-    TestRequest request = ws.newRequest();
-    if (id != null) {
-      request.setParam(PARAM_TEMPLATE_ID, id);
-    }
-
-    TestResponse result = executeRequest(request);
-    commit();
-    return result;
-  }
-
-  private static TestResponse executeRequest(TestRequest request) {
-    return request.execute();
-  }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupFromTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupFromTemplateActionTest.java
deleted file mode 100644 (file)
index 517a988..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Function;
-import java.util.List;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.GroupWithPermissionDto;
-import org.sonar.db.permission.PermissionQuery;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.DbTests;
-
-import static com.google.common.collect.FluentIterable.from;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.security.DefaultGroups.ANYONE;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.db.user.GroupMembershipQuery.IN;
-import static org.sonar.db.user.GroupTesting.newGroupDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
-
-@Category(DbTests.class)
-public class RemoveGroupFromTemplateActionTest {
-
-  private static final String GROUP_NAME = "group-name";
-  private static final String PERMISSION = CODEVIEWER;
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  GroupDto group;
-  PermissionTemplateDto permissionTemplate;
-
-  @Before
-  public void setUp() {
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
-    ws = new WsActionTester(new RemoveGroupFromTemplateAction(dbClient, dependenciesFinder, userSession));
-
-    group = insertGroup(newGroupDto().setName(GROUP_NAME));
-    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
-    addGroupToPermissionTemplate(permissionTemplate.getId(), group.getId(), PERMISSION);
-    commit();
-  }
-
-  @Test
-  public void remove_group_from_template() {
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
-    commit();
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
-  }
-
-  @Test
-  public void remove_group_from_template_by_name_case_insensitive() {
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
-    commit();
-
-    ws.newRequest()
-      .setParam(PARAM_GROUP_NAME, GROUP_NAME)
-      .setParam(PARAM_PERMISSION, PERMISSION)
-      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
-      .execute();
-    commit();
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
-  }
-
-  @Test
-  public void remove_group_with_group_id() {
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
-    commit();
-
-    ws.newRequest()
-      .setParam(PARAM_TEMPLATE_ID, permissionTemplate.getKee())
-      .setParam(PARAM_PERMISSION, PERMISSION)
-      .setParam(PARAM_GROUP_ID, String.valueOf(group.getId()))
-      .execute();
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
-  }
-
-  @Test
-  public void remove_group_twice_without_error() {
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
-  }
-
-  @Test
-  public void remove_anyone_group_from_template() {
-    addGroupToPermissionTemplate(permissionTemplate.getId(), null, PERMISSION);
-    commit();
-
-    newRequest(ANYONE, permissionTemplate.getKee(), PERMISSION);
-
-    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
-  }
-
-  @Test
-  public void fail_if_not_a_project_permission() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
-  }
-
-  @Test
-  public void fail_if_insufficient_privileges() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
-  }
-
-  @Test
-  public void fail_if_group_params_missing() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(null, permissionTemplate.getKee(), PERMISSION);
-  }
-
-  @Test
-  public void fail_if_permission_missing() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(GROUP_NAME, permissionTemplate.getKee(), null);
-  }
-
-  @Test
-  public void fail_if_template_missing() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(GROUP_NAME, null, PERMISSION);
-  }
-
-  @Test
-  public void fail_if_group_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Group with name 'unknown-group-name' is not found");
-
-    newRequest("unknown-group-name", permissionTemplate.getKee(), PERMISSION);
-  }
-
-  @Test
-  public void fail_if_template_key_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
-
-    newRequest(GROUP_NAME, "unknown-key", PERMISSION);
-  }
-
-  private void newRequest(@Nullable String groupName, @Nullable String templateKey, @Nullable String permission) {
-    TestRequest request = ws.newRequest();
-    if (groupName != null) {
-      request.setParam(WsPermissionParameters.PARAM_GROUP_NAME, groupName);
-    }
-    if (templateKey != null) {
-      request.setParam(PARAM_TEMPLATE_ID, templateKey);
-    }
-    if (permission != null) {
-      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
-    }
-
-    request.execute();
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private GroupDto insertGroup(GroupDto groupDto) {
-    return dbClient.groupDao().insert(dbSession, groupDto);
-  }
-
-  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
-  }
-
-  private void addGroupToPermissionTemplate(long permissionTemplateId, @Nullable Long groupId, String permission) {
-    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, permissionTemplateId, groupId, permission);
-  }
-
-  private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
-    return from(dbClient.permissionTemplateDao()
-      .selectGroups(dbSession, permissionQuery, templateId))
-      .transform(GroupWithPermissionToGroupName.INSTANCE)
-      .toList();
-  }
-
-  private enum GroupWithPermissionToGroupName implements Function<GroupWithPermissionDto, String> {
-    INSTANCE;
-
-    @Override
-    public String apply(@Nonnull GroupWithPermissionDto groupWithPermission) {
-      return groupWithPermission.getName();
-    }
-
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java
deleted file mode 100644 (file)
index 7d71fdd..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import com.google.common.base.Function;
-import java.util.List;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionQuery;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.permission.UserWithPermissionDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.DbTests;
-
-import static com.google.common.collect.FluentIterable.from;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.web.UserRole.CODEVIEWER;
-import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.db.user.GroupMembershipQuery.IN;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
-
-@Category(DbTests.class)
-public class RemoveUserFromTemplateActionTest {
-
-  private static final String USER_LOGIN = "user-login";
-  private static final String DEFAULT_PERMISSION = CODEVIEWER;
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-  UserDto user;
-  PermissionTemplateDto permissionTemplate;
-
-  @Before
-  public void setUp() {
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
-    ws = new WsActionTester(new RemoveUserFromTemplateAction(dbClient, dependenciesFinder, userSession));
-
-    user = insertUser(newUserDto().setLogin(USER_LOGIN));
-    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
-    addUserToTemplate(user, permissionTemplate, DEFAULT_PERMISSION);
-    commit();
-  }
-
-  @Test
-  public void remove_user_from_template() {
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
-  }
-
-  @Test
-  public void remove_user_from_template_by_name_case_insensitive() {
-    ws.newRequest()
-      .setParam(PARAM_USER_LOGIN, USER_LOGIN)
-      .setParam(PARAM_PERMISSION, DEFAULT_PERMISSION)
-      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
-      .execute();
-    commit();
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
-  }
-
-  @Test
-  public void remove_user_from_template_twice_without_failing() {
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
-  }
-
-  @Test
-  public void keep_user_permission_not_removed() {
-    addUserToTemplate(user, permissionTemplate, ISSUE_ADMIN);
-    commit();
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), ISSUE_ADMIN)).containsExactly(user.getLogin());
-  }
-
-  @Test
-  public void keep_other_users_when_one_user_removed() {
-    UserDto newUser = insertUser(newUserDto().setLogin("new-login"));
-    addUserToTemplate(newUser, permissionTemplate, DEFAULT_PERMISSION);
-    commit();
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-
-    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).containsExactly("new-login");
-  }
-
-  @Test
-  public void fail_if_not_a_project_permission() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
-  }
-
-  @Test
-  public void fail_if_insufficient_privileges() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-  }
-
-  @Test
-  public void fail_if_user_missing() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(null, permissionTemplate.getKee(), DEFAULT_PERMISSION);
-  }
-
-  @Test
-  public void fail_if_permission_missing() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(USER_LOGIN, permissionTemplate.getKee(), null);
-  }
-
-  @Test
-  public void fail_if_template_missing() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(USER_LOGIN, null, DEFAULT_PERMISSION);
-  }
-
-  @Test
-  public void fail_if_user_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("User with login 'unknown-login' is not found");
-
-    newRequest("unknown-login", permissionTemplate.getKee(), DEFAULT_PERMISSION);
-  }
-
-  @Test
-  public void fail_if_template_key_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
-
-    newRequest(USER_LOGIN, "unknown-key", DEFAULT_PERMISSION);
-  }
-
-  private void newRequest(@Nullable String userLogin, @Nullable String templateKey, @Nullable String permission) {
-    TestRequest request = ws.newRequest();
-    if (userLogin != null) {
-      request.setParam(PARAM_USER_LOGIN, userLogin);
-    }
-    if (templateKey != null) {
-      request.setParam(WsPermissionParameters.PARAM_TEMPLATE_ID, templateKey);
-    }
-    if (permission != null) {
-      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
-    }
-
-    request.execute();
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private UserDto insertUser(UserDto userDto) {
-    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
-  }
-
-  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
-  }
-
-  private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
-    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
-    return from(dbClient.permissionTemplateDao()
-      .selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE))
-      .transform(UserWithPermissionToUserLogin.INSTANCE)
-      .toList();
-  }
-
-  private enum UserWithPermissionToUserLogin implements Function<UserWithPermissionDto, String> {
-    INSTANCE;
-
-    @Override
-    public String apply(@Nonnull UserWithPermissionDto userWithPermission) {
-      return userWithPermission.getLogin();
-    }
-
-  }
-
-  private void addUserToTemplate(UserDto user, PermissionTemplateDto permissionTemplate, String permission) {
-    dbClient.permissionTemplateDao().insertUserPermission(dbSession, permissionTemplate.getId(), user.getId(), permission);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchTemplatesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchTemplatesActionTest.java
deleted file mode 100644 (file)
index dcda800..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.Date;
-import java.util.List;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.i18n.I18nRule;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.DbTests;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
-import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.db.user.GroupTesting.newGroupDto;
-import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
-import static org.sonar.test.JsonAssert.assertJson;
-
-@Category(DbTests.class)
-public class SearchTemplatesActionTest {
-  @ClassRule
-  public static DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-
-  WsActionTester ws;
-  I18nRule i18n = new I18nRule();
-  DbClient dbClient = db.getDbClient();
-  DbSession dbSession = db.getSession();
-  ResourceTypes resourceTypes = mock(ResourceTypes.class);
-  SearchTemplatesDataLoader dataLoader;
-
-  SearchTemplatesAction underTest;
-
-  @Before
-  public void setUp() {
-    db.truncateTables();
-    i18n.setProjectPermissions();
-    when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
-
-    Settings settings = new Settings();
-    settings.setProperty(defaultRootQualifierTemplateProperty(Qualifiers.PROJECT), UUID_EXAMPLE_01);
-    settings.setProperty(defaultRootQualifierTemplateProperty(Qualifiers.VIEW), UUID_EXAMPLE_02);
-    settings.setProperty(defaultRootQualifierTemplateProperty("DEV"), UUID_EXAMPLE_03);
-
-    DefaultPermissionTemplateFinder defaultPermissionTemplateFinder = new DefaultPermissionTemplateFinder(settings, resourceTypes);
-
-    dataLoader = new SearchTemplatesDataLoader(dbClient, defaultPermissionTemplateFinder);
-    underTest = new SearchTemplatesAction(dbClient, userSession, i18n, dataLoader);
-
-    ws = new WsActionTester(underTest);
-
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-  }
-
-  @Test
-  public void search_project_permissions() {
-    PermissionTemplateDto projectTemplate = insertProjectTemplate();
-    PermissionTemplateDto viewsTemplate = insertViewsTemplate();
-    PermissionTemplateDto developerTemplate = insertDeveloperTemplate();
-
-    UserDto user1 = insertUser(newUserDto());
-    UserDto user2 = insertUser(newUserDto());
-    UserDto user3 = insertUser(newUserDto());
-
-    GroupDto group1 = insertGroup(newGroupDto());
-    GroupDto group2 = insertGroup(newGroupDto());
-    GroupDto group3 = insertGroup(newGroupDto());
-
-    addUserToTemplate(projectTemplate.getId(), user1.getId(), UserRole.ISSUE_ADMIN);
-    addUserToTemplate(projectTemplate.getId(), user2.getId(), UserRole.ISSUE_ADMIN);
-    addUserToTemplate(projectTemplate.getId(), user3.getId(), UserRole.ISSUE_ADMIN);
-    addUserToTemplate(projectTemplate.getId(), user1.getId(), UserRole.CODEVIEWER);
-    addGroupToTemplate(projectTemplate.getId(), group1.getId(), UserRole.ADMIN);
-
-    addUserToTemplate(viewsTemplate.getId(), user1.getId(), UserRole.USER);
-    addUserToTemplate(viewsTemplate.getId(), user2.getId(), UserRole.USER);
-    addGroupToTemplate(viewsTemplate.getId(), group1.getId(), UserRole.ISSUE_ADMIN);
-    addGroupToTemplate(viewsTemplate.getId(), group2.getId(), UserRole.ISSUE_ADMIN);
-    addGroupToTemplate(viewsTemplate.getId(), group3.getId(), UserRole.ISSUE_ADMIN);
-
-    addGroupToTemplate(developerTemplate.getId(), group1.getId(), UserRole.USER);
-
-    commit();
-
-    String result = newRequest();
-
-    assertJson(result)
-      .withStrictArrayOrder()
-      .isSimilarTo(getClass().getResource("search_templates-example.json"));
-  }
-
-  @Test
-  public void empty_result() {
-    String result = newRequest();
-
-    assertJson(result)
-      .withStrictArrayOrder()
-      .isSimilarTo(getClass().getResource("SearchTemplatesActionTest/empty.json"));
-  }
-
-  @Test
-  public void search_by_name() {
-    insertProjectTemplate();
-    insertViewsTemplate();
-    insertDeveloperTemplate();
-    commit();
-
-    String result = ws.newRequest()
-      .setParam(TEXT_QUERY, "views")
-      .execute().getInput();
-
-    assertThat(result).contains("Default template for Views")
-      .doesNotContain("projects")
-      .doesNotContain("developers");
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    ws.newRequest().execute();
-  }
-
-  @Test
-  public void fail_if_not_global_admin() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.login().setGlobalPermissions(QUALITY_PROFILE_ADMIN);
-
-    ws.newRequest().execute();
-  }
-
-  private String newRequest() {
-    return ws.newRequest().execute().getInput();
-  }
-
-  private PermissionTemplateDto insertProjectTemplate() {
-    return insertTemplate(newPermissionTemplateDto()
-      .setUuid(UUID_EXAMPLE_01)
-      .setName("Default template for Projects")
-      .setDescription("Template for new projects")
-      .setKeyPattern(null)
-      .setCreatedAt(new Date(1_000_000_000_000L))
-      .setUpdatedAt(new Date(1_000_000_000_000L)));
-  }
-
-  private PermissionTemplateDto insertViewsTemplate() {
-    return insertTemplate(newPermissionTemplateDto()
-      .setUuid(UUID_EXAMPLE_02)
-      .setName("Default template for Views")
-      .setDescription("Template for new views")
-      .setKeyPattern(".*sonar.views.*")
-      .setCreatedAt(new Date(1_000_000_000_000L))
-      .setUpdatedAt(new Date(1_100_000_000_000L)));
-  }
-
-  private PermissionTemplateDto insertDeveloperTemplate() {
-    return insertTemplate(newPermissionTemplateDto()
-      .setUuid(UUID_EXAMPLE_03)
-      .setName("Default template for Developers")
-      .setKeyPattern(".*sonar.developer.*")
-      .setDescription(null)
-      .setCreatedAt(new Date(1_100_500_000_000L))
-      .setUpdatedAt(new Date(1_100_900_000_000L)));
-  }
-
-  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
-    return dbClient.permissionTemplateDao().insert(dbSession, template);
-  }
-
-  private GroupDto insertGroup(GroupDto groupDto) {
-    return dbClient.groupDao().insert(dbSession, groupDto);
-  }
-
-  private UserDto insertUser(UserDto userDto) {
-    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
-  }
-
-  private void addGroupToTemplate(long templateId, @Nullable Long groupId, String permission) {
-    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, templateId, groupId, permission);
-  }
-
-  private void addUserToTemplate(long templateId, long userId, String permission) {
-    dbClient.permissionTemplateDao().insertUserPermission(dbSession, templateId, userId, permission);
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private static List<ResourceType> rootResourceTypes() {
-    ResourceType project = ResourceType.builder(Qualifiers.PROJECT).build();
-    ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
-    ResourceType dev = ResourceType.builder("DEV").build();
-
-    return asList(project, view, dev);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SetDefaultTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/SetDefaultTemplateActionTest.java
deleted file mode 100644 (file)
index defa13e..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.List;
-import java.util.Properties;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.permission.PermissionTemplateTesting;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.i18n.I18nRule;
-import org.sonar.server.platform.PersistentSettings;
-import org.sonar.server.platform.ServerSettings;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.DbTests;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.resources.Qualifiers.PROJECT;
-import static org.sonar.api.resources.Qualifiers.VIEW;
-import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
-import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_QUALIFIER;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
-
-@Category(DbTests.class)
-public class SetDefaultTemplateActionTest {
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  I18nRule i18n = new I18nRule();
-
-  WsActionTester ws;
-  PersistentSettings persistentSettings;
-  ResourceTypes resourceTypes = mock(ResourceTypes.class);
-
-  PermissionTemplateDto template;
-
-  @Before
-  public void setUp() {
-    DbClient dbClient = db.getDbClient();
-    persistentSettings = new PersistentSettings(dbClient.propertiesDao(), new ServerSettings(new PropertyDefinitions(), new Properties()));
-    persistentSettings.saveProperty(DEFAULT_TEMPLATE_PROPERTY, "any-template-uuid");
-    persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(PROJECT), "any-template-uuid");
-    persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(VIEW), "any-view-template-uuid");
-    persistentSettings.saveProperty(defaultRootQualifierTemplateProperty("DEV"), "any-dev-template-uuid");
-    when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    ws = new WsActionTester(new SetDefaultTemplateAction(
-      dbClient,
-      new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient)),
-      resourceTypes,
-      persistentSettings,
-      userSession, i18n));
-
-    template = dbClient.permissionTemplateDao().insert(db.getSession(), PermissionTemplateTesting.newPermissionTemplateDto().setUuid("permission-template-uuid"));
-  }
-
-  @Test
-  public void update_settings_for_project_qualifier() {
-    // default value is project qualifier's value
-    String result = newRequest(template.getUuid(), null);
-
-    assertThat(result).isEmpty();
-    assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo("any-template-uuid");
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo(template.getUuid());
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo("any-view-template-uuid");
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
-  }
-
-  @Test
-  public void update_settings_for_project_qualifier_by_template_name() {
-    ws.newRequest()
-      .setParam(PARAM_TEMPLATE_NAME, template.getName().toUpperCase())
-      .execute();
-    db.getSession().commit();
-
-    assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo("any-template-uuid");
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo(template.getUuid());
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo("any-view-template-uuid");
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
-  }
-
-  @Test
-  public void update_settings_of_views_property() {
-    newRequest(template.getUuid(), VIEW);
-
-    assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo("any-template-uuid");
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo("any-template-uuid");
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo(template.getUuid());
-    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
-  }
-
-  @Test
-  public void fail_if_anonymous() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(template.getUuid(), PROJECT);
-  }
-
-  @Test
-  public void fail_if_not_admin() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.login().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest(template.getUuid(), PROJECT);
-  }
-
-  @Test
-  public void fail_if_template_not_provided() {
-    expectedException.expect(BadRequestException.class);
-
-    newRequest(null, PROJECT);
-  }
-
-  @Test
-  public void fail_if_template_does_not_exist() {
-    expectedException.expect(NotFoundException.class);
-
-    newRequest("unknown-template-uuid", PROJECT);
-  }
-
-  @Test
-  public void fail_if_qualifier_is_not_root() {
-    expectedException.expect(BadRequestException.class);
-    when(resourceTypes.getRoots()).thenReturn(singletonList(ResourceType.builder(PROJECT).build()));
-
-    newRequest(template.getUuid(), VIEW);
-  }
-
-  private String newRequest(@Nullable String templateUuid, @Nullable String qualifier) {
-    TestRequest request = ws.newRequest();
-    if (templateUuid != null) {
-      request.setParam(PARAM_TEMPLATE_ID, templateUuid);
-    }
-    if (qualifier != null) {
-      request.setParam(PARAM_QUALIFIER, qualifier);
-    }
-
-    return request.execute().getInput();
-  }
-
-  private static List<ResourceType> rootResourceTypes() {
-    ResourceType project = ResourceType.builder(PROJECT).build();
-    ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
-    ResourceType dev = ResourceType.builder("DEV").build();
-
-    return asList(project, view, dev);
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/UpdateTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/UpdateTemplateActionTest.java
deleted file mode 100644 (file)
index 82d2404..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-package org.sonar.server.permission.ws;
-
-import java.util.Date;
-import javax.annotation.Nullable;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.utils.System2;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.permission.PermissionTemplateDto;
-import org.sonar.db.user.GroupDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.TestRequest;
-import org.sonar.server.ws.TestResponse;
-import org.sonar.server.ws.WsActionTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_ID;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
-import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class UpdateTemplateActionTest {
-
-  @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
-  @Rule
-  public UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  WsActionTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
-
-  PermissionTemplateDto templateDto;
-
-  @Before
-  public void setUp() {
-    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-    System2 system = mock(System2.class);
-    when(system.now()).thenReturn(1_440_512_328_743L);
-
-    dbClient = db.getDbClient();
-    dbSession = db.getSession();
-    PermissionDependenciesFinder finder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
-
-    ws = new WsActionTester(new UpdateTemplateAction(dbClient, userSession, system, finder));
-
-    templateDto = insertTemplate(newPermissionTemplateDto()
-      .setName("Permission Template Name")
-      .setDescription("Permission Template Description")
-      .setKeyPattern(".*\\.pattern\\..*")
-      .setCreatedAt(new Date(1_000_000_000_000L))
-      .setUpdatedAt(new Date(1_000_000_000_000L)));
-    commit();
-  }
-
-  @Test
-  public void update_all_permission_template_fields() {
-    TestResponse result = newRequest(templateDto.getKee(), "Finance", "Permissions for financially related projects", ".*\\.finance\\..*");
-
-    assertJson(result.getInput())
-      .ignoreFields("id")
-      .isSimilarTo(getClass().getResource("update_template-example.json"));
-    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
-    assertThat(finance.getName()).isEqualTo("Finance");
-    assertThat(finance.getDescription()).isEqualTo("Permissions for financially related projects");
-    assertThat(finance.getKeyPattern()).isEqualTo(".*\\.finance\\..*");
-    assertThat(finance.getKee()).isEqualTo(templateDto.getKee());
-    assertThat(finance.getCreatedAt()).isEqualTo(templateDto.getCreatedAt());
-    assertThat(finance.getUpdatedAt().getTime()).isEqualTo(1440512328743L);
-  }
-
-  @Test
-  public void update_with_the_same_values() {
-    newRequest(templateDto.getKee(), templateDto.getName(), templateDto.getDescription(), templateDto.getKeyPattern());
-
-    PermissionTemplateDto updatedTemplate = dbClient.permissionTemplateDao().selectByUuid(dbSession, templateDto.getKee());
-    assertThat(updatedTemplate.getName()).isEqualTo(templateDto.getName());
-    assertThat(updatedTemplate.getDescription()).isEqualTo(templateDto.getDescription());
-    assertThat(updatedTemplate.getKeyPattern()).isEqualTo(templateDto.getKeyPattern());
-  }
-
-  @Test
-  public void update_name_only() {
-    newRequest(templateDto.getKee(), "Finance", null, null);
-
-    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
-    assertThat(finance.getName()).isEqualTo("Finance");
-    assertThat(finance.getDescription()).isEqualTo(templateDto.getDescription());
-    assertThat(finance.getKeyPattern()).isEqualTo(templateDto.getKeyPattern());
-  }
-
-  @Test
-  public void fail_if_key_is_not_found() {
-    expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
-
-    newRequest("unknown-key", null, null, null);
-  }
-
-  @Test
-  public void fail_if_name_already_exists_in_another_template() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("A template with the name 'My Template' already exists (case insensitive).");
-
-    insertTemplate(newPermissionTemplateDto()
-      .setName("My Template")
-      .setKee("my-key")
-      .setCreatedAt(new Date(12345789L))
-      .setUpdatedAt(new Date(12345789L)));
-    commit();
-
-    newRequest(templateDto.getKee(), "My Template", null, null);
-  }
-
-  @Test
-  public void fail_if_key_is_not_provided() {
-    expectedException.expect(IllegalArgumentException.class);
-
-    newRequest(null, "Finance", null, null);
-  }
-
-  @Test
-  public void fail_if_name_empty() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The template name must not be blank");
-
-    newRequest(templateDto.getKee(), "", null, null);
-  }
-
-  @Test
-  public void fail_if_name_has_just_whitespaces() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The template name must not be blank");
-
-    newRequest(templateDto.getKee(), "  \r\n", null, null);
-  }
-
-  @Test
-  public void fail_if_regexp_if_not_valid() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("The 'projectKeyPattern' parameter must be a valid Java regular expression. '[azerty' was passed");
-
-    newRequest(templateDto.getKee(), "Finance", null, "[azerty");
-  }
-
-  @Test
-  public void fail_if_name_already_exists_in_database_case_insensitive() {
-    expectedException.expect(BadRequestException.class);
-    expectedException.expectMessage("A template with the name 'Finance' already exists (case insensitive).");
-    insertTemplate(newPermissionTemplateDto().setName("finance"));
-    commit();
-
-    newRequest(templateDto.getKee(), "Finance", null, null);
-  }
-
-  @Test
-  public void fail_if_not_logged_in() {
-    expectedException.expect(UnauthorizedException.class);
-    userSession.anonymous();
-
-    newRequest(templateDto.getKee(), "Finance", null, null);
-  }
-
-  @Test
-  public void fail_if_not_admin() {
-    expectedException.expect(ForbiddenException.class);
-    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
-
-    newRequest(templateDto.getKee(), "Finance", null, null);
-  }
-
-  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
-    return dbClient.permissionTemplateDao().insert(dbSession, template);
-  }
-
-  private GroupDto insertGroup(GroupDto group) {
-    return dbClient.groupDao().insert(db.getSession(), group);
-  }
-
-  private void commit() {
-    dbSession.commit();
-  }
-
-  private TestResponse newRequest(@Nullable String key, @Nullable String name, @Nullable String description, @Nullable String projectPattern) {
-    TestRequest request = ws.newRequest();
-    if (key != null) {
-      request.setParam(PARAM_ID, key);
-    }
-    if (name != null) {
-      request.setParam(PARAM_NAME, name);
-    }
-    if (description != null) {
-      request.setParam(PARAM_DESCRIPTION, description);
-    }
-    if (projectPattern != null) {
-      request.setParam(PARAM_PATTERN, projectPattern);
-    }
-
-    return request.execute();
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddGroupToTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddGroupToTemplateActionTest.java
new file mode 100644 (file)
index 0000000..006c552
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Function;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.GroupWithPermissionDto;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.WsPermissionParameters;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.security.DefaultGroups.ANYONE;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
+import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.db.user.GroupTesting.newGroupDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
+
+@Category(DbTests.class)
+public class AddGroupToTemplateActionTest {
+
+  private static final String GROUP_NAME = "group-name";
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  GroupDto group;
+  PermissionTemplateDto permissionTemplate;
+
+  @Before
+  public void setUp() {
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
+    ws = new WsActionTester(new AddGroupToTemplateAction(dbClient, dependenciesFinder, userSession));
+
+    group = insertGroup(newGroupDto().setName(GROUP_NAME));
+    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
+    commit();
+  }
+
+  @Test
+  public void add_group_to_template() {
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
+  }
+
+  @Test
+  public void add_group_to_template_by_name() {
+    ws.newRequest()
+      .setParam(PARAM_GROUP_NAME, GROUP_NAME)
+      .setParam(PARAM_PERMISSION, CODEVIEWER)
+      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
+      .execute();
+    commit();
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
+  }
+
+  @Test
+  public void add_with_group_id() {
+    ws.newRequest()
+      .setParam(PARAM_TEMPLATE_ID, permissionTemplate.getKee())
+      .setParam(PARAM_PERMISSION, CODEVIEWER)
+      .setParam(PARAM_GROUP_ID, String.valueOf(group.getId()))
+      .execute();
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
+  }
+
+  @Test
+  public void does_not_add_a_group_twice() {
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), ISSUE_ADMIN);
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), ISSUE_ADMIN);
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), ISSUE_ADMIN)).containsExactly(GROUP_NAME);
+  }
+
+  @Test
+  public void add_anyone_group_to_template() {
+    newRequest(ANYONE, permissionTemplate.getKee(), CODEVIEWER);
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(ANYONE);
+  }
+
+  @Test
+  public void fail_if_add_anyone_group_to_admin_permission() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage(String.format("It is not possible to add the '%s' permission to the '%s' group.", UserRole.ADMIN, ANYONE));
+
+    newRequest(ANYONE, permissionTemplate.getKee(), ADMIN);
+  }
+
+  @Test
+  public void fail_if_not_a_project_permission() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
+  }
+
+  @Test
+  public void fail_if_insufficient_privileges() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_group_params_missing() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(null, permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_permission_missing() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), null);
+  }
+
+  @Test
+  public void fail_if_template_uuid_and_name_missing() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(GROUP_NAME, null, CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_group_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Group with name 'unknown-group-name' is not found");
+
+    newRequest("unknown-group-name", permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_template_key_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
+
+    newRequest(GROUP_NAME, "unknown-key", CODEVIEWER);
+  }
+
+  private void newRequest(@Nullable String groupName, @Nullable String templateKey, @Nullable String permission) {
+    TestRequest request = ws.newRequest();
+    if (groupName != null) {
+      request.setParam(WsPermissionParameters.PARAM_GROUP_NAME, groupName);
+    }
+    if (templateKey != null) {
+      request.setParam(PARAM_TEMPLATE_ID, templateKey);
+    }
+    if (permission != null) {
+      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
+    }
+
+    request.execute();
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private GroupDto insertGroup(GroupDto groupDto) {
+    return dbClient.groupDao().insert(dbSession, groupDto);
+  }
+
+  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
+    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
+  }
+
+  private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
+    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    return from(dbClient.permissionTemplateDao()
+      .selectGroups(dbSession, permissionQuery, templateId))
+      .transform(GroupWithPermissionToGroupName.INSTANCE)
+      .toList();
+  }
+
+  private enum GroupWithPermissionToGroupName implements Function<GroupWithPermissionDto, String> {
+    INSTANCE;
+
+    @Override
+    public String apply(@Nonnull GroupWithPermissionDto groupWithPermission) {
+      return groupWithPermission.getName();
+    }
+
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddUserToTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/AddUserToTemplateActionTest.java
new file mode 100644 (file)
index 0000000..2ab68a4
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Function;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.permission.UserWithPermissionDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.WsPermissionParameters;
+import org.sonar.server.permission.ws.template.AddUserToTemplateAction;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
+import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.db.user.UserTesting.newUserDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
+
+@Category(DbTests.class)
+public class AddUserToTemplateActionTest {
+
+  private static final String USER_LOGIN = "user-login";
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  UserDto user;
+  PermissionTemplateDto permissionTemplate;
+
+  @Before
+  public void setUp() {
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
+    ws = new WsActionTester(new AddUserToTemplateAction(dbClient, dependenciesFinder, userSession));
+
+    user = insertUser(newUserDto().setLogin(USER_LOGIN));
+    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
+    commit();
+  }
+
+  @Test
+  public void add_user_to_template() {
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), CODEVIEWER);
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(USER_LOGIN);
+  }
+
+  @Test
+  public void add_user_to_template_by_name() {
+    ws.newRequest()
+      .setParam(PARAM_USER_LOGIN, USER_LOGIN)
+      .setParam(PARAM_PERMISSION, CODEVIEWER)
+      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
+      .execute();
+    commit();
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(USER_LOGIN);
+  }
+
+  @Test
+  public void does_not_add_a_user_twice() {
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), ISSUE_ADMIN);
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), ISSUE_ADMIN);
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), ISSUE_ADMIN)).containsExactly(USER_LOGIN);
+  }
+
+  @Test
+  public void fail_if_not_a_project_permission() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
+  }
+
+  @Test
+  public void fail_if_insufficient_privileges() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_user_missing() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(null, permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_permission_missing() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), null);
+  }
+
+  @Test
+  public void fail_if_template_uuid_and_name_are_missing() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(USER_LOGIN, null, CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_user_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("User with login 'unknown-login' is not found");
+
+    newRequest("unknown-login", permissionTemplate.getKee(), CODEVIEWER);
+  }
+
+  @Test
+  public void fail_if_template_key_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
+
+    newRequest(USER_LOGIN, "unknown-key", CODEVIEWER);
+  }
+
+  private void newRequest(@Nullable String userLogin, @Nullable String templateKey, @Nullable String permission) {
+    TestRequest request = ws.newRequest();
+    if (userLogin != null) {
+      request.setParam(PARAM_USER_LOGIN, userLogin);
+    }
+    if (templateKey != null) {
+      request.setParam(WsPermissionParameters.PARAM_TEMPLATE_ID, templateKey);
+    }
+    if (permission != null) {
+      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
+    }
+
+    request.execute();
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private UserDto insertUser(UserDto userDto) {
+    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
+  }
+
+  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
+    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
+  }
+
+  private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
+    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    return from(dbClient.permissionTemplateDao()
+      .selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE))
+      .transform(UserWithPermissionToUserLogin.INSTANCE)
+      .toList();
+  }
+
+  private enum UserWithPermissionToUserLogin implements Function<UserWithPermissionDto, String> {
+    INSTANCE;
+
+    @Override
+    public String apply(@Nonnull UserWithPermissionDto userWithPermission) {
+      return userWithPermission.getLogin();
+    }
+
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java
new file mode 100644 (file)
index 0000000..d8554d9
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.permission.GroupWithPermissionDto;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionRepository;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.permission.UserWithPermissionDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.GroupRoleDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserRoleDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.permission.PermissionFinder;
+import org.sonar.server.permission.PermissionService;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.template.ApplyTemplateAction;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.db.user.GroupTesting.newGroupDto;
+import static org.sonar.db.user.UserTesting.newUserDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PROJECT_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PROJECT_KEY;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
+
+@Category(DbTests.class)
+public class ApplyTemplateActionTest {
+
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+
+  UserDto user1;
+  UserDto user2;
+  GroupDto group1;
+  GroupDto group2;
+  ComponentDto project;
+  PermissionTemplateDto template1;
+  PermissionTemplateDto template2;
+  IssueAuthorizationIndexer issueAuthorizationIndexer = mock(IssueAuthorizationIndexer.class);
+
+  @Before
+  public void setUp() {
+    userSession.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+
+    PermissionRepository repository = new PermissionRepository(dbClient, new Settings());
+    PermissionFinder permissionFinder = new PermissionFinder(dbClient);
+    ComponentFinder componentFinder = new ComponentFinder(dbClient);
+    PermissionService permissionService = new PermissionService(dbClient, repository, issueAuthorizationIndexer, userSession, componentFinder);
+    PermissionDependenciesFinder permissionDependenciesFinder = new PermissionDependenciesFinder(dbClient, componentFinder);
+
+    ApplyTemplateAction underTest = new ApplyTemplateAction(dbClient, permissionService, permissionDependenciesFinder);
+    ws = new WsActionTester(underTest);
+
+    user1 = insertUser(newUserDto().setLogin("user-login-1"));
+    user2 = insertUser(newUserDto().setLogin("user-login-2"));
+    group1 = insertGroup(newGroupDto().setName("group-name-1"));
+    group2 = insertGroup(newGroupDto().setName("group-name-2"));
+
+    // template 1
+    template1 = insertTemplate(newPermissionTemplateDto().setUuid("permission-template-uuid-1"));
+    addUserToTemplate(user1, template1, UserRole.CODEVIEWER);
+    addUserToTemplate(user2, template1, UserRole.ISSUE_ADMIN);
+    addGroupToTemplate(group1, template1, UserRole.ADMIN);
+    addGroupToTemplate(group2, template1, UserRole.USER);
+    // template 2
+    template2 = insertTemplate(newPermissionTemplateDto().setUuid("permission-template-uuid-2"));
+    addUserToTemplate(user1, template2, UserRole.USER);
+    addUserToTemplate(user2, template2, UserRole.USER);
+    addGroupToTemplate(group1, template2, UserRole.USER);
+    addGroupToTemplate(group2, template2, UserRole.USER);
+
+    project = insertProject(newProjectDto("project-uuid-1"));
+    addUserPermissionToProject(user1, project, UserRole.ADMIN);
+    addUserPermissionToProject(user2, project, UserRole.ADMIN);
+    addGroupPermissionToProject(group1, project, UserRole.ADMIN);
+    addGroupPermissionToProject(group2, project, UserRole.ADMIN);
+
+    commit();
+  }
+
+  @Test
+  public void apply_template_with_project_uuid() {
+    assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).hasSize(2);
+    assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).hasSize(2);
+
+    newRequest(template1.getUuid(), project.uuid(), null);
+
+    assertTemplate1AppliedToProject();
+    verify(issueAuthorizationIndexer).index();
+  }
+
+  @Test
+  public void apply_template_with_project_uuid_by_template_name() {
+    ws.newRequest()
+      .setParam(PARAM_TEMPLATE_NAME, template1.getName().toUpperCase())
+      .setParam(PARAM_PROJECT_ID, project.uuid())
+      .execute();
+    commit();
+
+    assertTemplate1AppliedToProject();
+  }
+
+  @Test
+  public void apply_template_with_project_key() {
+    newRequest(template1.getUuid(), null, project.key());
+
+    assertTemplate1AppliedToProject();
+  }
+
+  @Test
+  public void fail_when_unknown_template() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Permission template with id 'unknown-template-uuid' is not found");
+
+    newRequest("unknown-template-uuid", project.uuid(), null);
+  }
+
+  @Test
+  public void fail_when_unknown_project_uuid() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Project id 'unknown-project-uuid' not found");
+
+    newRequest(template1.getUuid(), "unknown-project-uuid", null);
+  }
+
+  @Test
+  public void fail_when_unknown_project_key() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Project key 'unknown-project-key' not found");
+
+    newRequest(template1.getUuid(), null, "unknown-project-key");
+  }
+
+  @Test
+  public void fail_when_template_is_not_provided() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(null, project.uuid(), null);
+  }
+
+  @Test
+  public void fail_when_project_uuid_and_key_not_provided() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Project id or project key must be provided, not both.");
+
+    newRequest(template1.getUuid(), null, null);
+  }
+
+  @Test
+  public void fail_when_anonymous() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(template1.getUuid(), project.uuid(), null);
+  }
+
+  @Test
+  public void fail_when_insufficient_privileges() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.login().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+
+    newRequest(template1.getUuid(), project.uuid(), null);
+  }
+
+  private void assertTemplate1AppliedToProject() {
+    assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).extracting("name").containsExactly(group1.getName());
+    assertThat(selectProjectPermissionGroups(project, UserRole.USER)).extracting("name").containsExactly(group2.getName());
+    assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty();
+    assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).extracting("login").containsExactly(user1.getLogin());
+    assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).extracting("login").containsExactly(user2.getLogin());
+  }
+
+  private TestResponse newRequest(@Nullable String templateUuid, @Nullable String projectUuid, @Nullable String projectKey) {
+    TestRequest request = ws.newRequest();
+    if (templateUuid != null) {
+      request.setParam(PARAM_TEMPLATE_ID, templateUuid);
+    }
+    if (projectUuid != null) {
+      request.setParam(PARAM_PROJECT_ID, projectUuid);
+    }
+    if (projectKey != null) {
+      request.setParam(PARAM_PROJECT_KEY, projectKey);
+    }
+
+    TestResponse result = request.execute();
+    commit();
+
+    return result;
+  }
+
+  private ComponentDto insertProject(ComponentDto project) {
+    dbClient.componentDao().insert(dbSession, project);
+    return dbClient.componentDao().selectOrFailByUuid(dbSession, project.uuid());
+  }
+
+  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
+    return dbClient.permissionTemplateDao().insert(dbSession, template);
+  }
+
+  private UserDto insertUser(UserDto userDto) {
+    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
+  }
+
+  private GroupDto insertGroup(GroupDto group) {
+    return dbClient.groupDao().insert(dbSession, group);
+  }
+
+  private void addUserToTemplate(UserDto user, PermissionTemplateDto permissionTemplate, String permission) {
+    dbClient.permissionTemplateDao().insertUserPermission(dbSession, permissionTemplate.getId(), user.getId(), permission);
+  }
+
+  private void addGroupToTemplate(GroupDto group, PermissionTemplateDto permissionTemplate, String permission) {
+    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, permissionTemplate.getId(), group.getId(), permission);
+  }
+
+  private void addUserPermissionToProject(UserDto user, ComponentDto project, String permission) {
+    dbClient.roleDao().insertUserRole(dbSession, new UserRoleDto()
+      .setRole(permission)
+      .setUserId(user.getId())
+      .setResourceId(project.getId()));
+  }
+
+  private void addGroupPermissionToProject(GroupDto group, ComponentDto project, String permission) {
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto()
+      .setRole(permission)
+      .setResourceId(project.getId())
+      .setGroupId(group.getId()));
+  }
+
+  private List<GroupWithPermissionDto> selectProjectPermissionGroups(ComponentDto project, String permission) {
+    return FluentIterable.from(dbClient.permissionDao().selectGroups(dbSession, query(permission), project.getId()))
+      .filter(new PermissionNotNull())
+      .toList();
+  }
+
+  private List<UserWithPermissionDto> selectProjectPermissionUsers(ComponentDto project, String permission) {
+    return dbClient.permissionDao().selectUsers(dbSession, query(permission), project.getId(), 0, Integer.MAX_VALUE);
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private static PermissionQuery query(String permission) {
+    return PermissionQuery.builder().membership(IN).permission(permission).build();
+  }
+
+  private static class PermissionNotNull implements Predicate<GroupWithPermissionDto> {
+    @Override
+    public boolean apply(@Nullable GroupWithPermissionDto input) {
+      return input.getPermission() != null;
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/CreateTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/CreateTemplateActionTest.java
new file mode 100644 (file)
index 0000000..991600c
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class CreateTemplateActionTest {
+
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  System2 system = mock(System2.class);
+
+  @Before
+  public void setUp() {
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    when(system.now()).thenReturn(1440512328743L);
+
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    ws = new WsActionTester(new CreateTemplateAction(dbClient, userSession, system));
+  }
+
+  @Test
+  public void create_full_permission_template() {
+    TestResponse result = newRequest("Finance", "Permissions for financially related projects", ".*\\.finance\\..*");
+
+    assertJson(result.getInput())
+      .ignoreFields("id")
+      .isSimilarTo(getClass().getResource("create_template-example.json"));
+    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
+    assertThat(finance.getName()).isEqualTo("Finance");
+    assertThat(finance.getDescription()).isEqualTo("Permissions for financially related projects");
+    assertThat(finance.getKeyPattern()).isEqualTo(".*\\.finance\\..*");
+    assertThat(finance.getKee()).isNotEmpty();
+    assertThat(finance.getCreatedAt().getTime()).isEqualTo(1440512328743L);
+    assertThat(finance.getUpdatedAt().getTime()).isEqualTo(1440512328743L);
+  }
+
+  @Test
+  public void create_minimalist_permission_template() {
+    newRequest("Finance", null, null);
+
+    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
+    assertThat(finance.getName()).isEqualTo("Finance");
+    assertThat(finance.getDescription()).isNullOrEmpty();
+    assertThat(finance.getKeyPattern()).isNullOrEmpty();
+    assertThat(finance.getKee()).isNotEmpty();
+    assertThat(finance.getCreatedAt().getTime()).isEqualTo(1440512328743L);
+    assertThat(finance.getUpdatedAt().getTime()).isEqualTo(1440512328743L);
+  }
+
+  @Test
+  public void fail_if_name_not_provided() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(null, null, null);
+  }
+
+  @Test
+  public void fail_if_name_empty() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("The template name must not be blank");
+
+    newRequest("", null, null);
+  }
+
+  @Test
+  public void fail_if_regexp_if_not_valid() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("The 'projectKeyPattern' parameter must be a valid Java regular expression. '[azerty' was passed");
+
+    newRequest("Finance", null, "[azerty");
+  }
+
+  @Test
+  public void fail_if_name_already_exists_in_database_case_insensitive() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("A template with the name 'Finance' already exists (case insensitive).");
+    insertTemplate(newPermissionTemplateDto().setName("finance"));
+    commit();
+
+    newRequest("Finance", null, null);
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest("Finance", null, null);
+  }
+
+  @Test
+  public void fail_if_not_admin() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest("Finance", null, null);
+  }
+
+  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
+    return dbClient.permissionTemplateDao().insert(dbSession, template);
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private TestResponse newRequest(@Nullable String name, @Nullable String description, @Nullable String projectPattern) {
+    TestRequest request = ws.newRequest();
+    if (name != null) {
+      request.setParam(PARAM_NAME, name);
+    }
+    if (description != null) {
+      request.setParam(PARAM_DESCRIPTION, description);
+    }
+    if (projectPattern != null) {
+      request.setParam(PARAM_PATTERN, projectPattern);
+    }
+
+    return request.execute();
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DefaultPermissionTemplateFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DefaultPermissionTemplateFinderTest.java
new file mode 100644 (file)
index 0000000..2e8e621
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.List;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.server.permission.ws.template.DefaultPermissionTemplateFinder;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
+import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
+
+public class DefaultPermissionTemplateFinderTest {
+
+  ResourceTypes resourceTypes = mock(ResourceTypes.class);
+  Settings settings = new Settings();
+
+  DefaultPermissionTemplateFinder underTest;
+
+  @Before
+  public void setUp() {
+    underTest = new DefaultPermissionTemplateFinder(settings, resourceTypes);
+    settings
+      .setProperty(DEFAULT_TEMPLATE_PROPERTY, "default-template-uuid")
+      .setProperty(defaultRootQualifierTemplateProperty(Qualifiers.PROJECT), "default-project-template-uuid")
+      .setProperty(defaultRootQualifierTemplateProperty("DEV"), "default-dev-template-uuid")
+      .setProperty(defaultRootQualifierTemplateProperty(Qualifiers.VIEW), "default-view-template-uuid");
+    when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
+  }
+
+  @Test
+  public void get_default_template_uuids_in_settings() {
+    Set<String> result = underTest.getDefaultTemplateUuids();
+
+    assertThat(result).containsOnly("default-project-template-uuid", "default-view-template-uuid", "default-dev-template-uuid");
+  }
+
+  @Test
+  public void get_default_template_uuid_if_no_property() {
+    settings = new Settings();
+    settings.setProperty(DEFAULT_TEMPLATE_PROPERTY, "default-template-uuid");
+    underTest = new DefaultPermissionTemplateFinder(settings, resourceTypes);
+
+    Set<String> result = underTest.getDefaultTemplateUuids();
+
+    assertThat(result).containsOnly("default-template-uuid");
+  }
+
+  private static List<ResourceType> rootResourceTypes() {
+    ResourceType project = ResourceType.builder(Qualifiers.PROJECT).build();
+    ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
+    ResourceType dev = ResourceType.builder("DEV").build();
+
+    return asList(project, view, dev);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java
new file mode 100644 (file)
index 0000000..8515de5
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.Collections;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.GroupTesting;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTesting;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.permission.ws.DeleteTemplateAction;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.template.DefaultPermissionTemplateFinder;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.internal.util.collections.Sets.newSet;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
+
+public class DeleteTemplateActionTest {
+
+  static final String TEMPLATE_UUID = "permission-template-uuid";
+
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  DefaultPermissionTemplateFinder defaultTemplatePermissionFinder;
+
+  PermissionTemplateDto permissionTemplate;
+
+  @Before
+  public void setUp() {
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    defaultTemplatePermissionFinder = mock(DefaultPermissionTemplateFinder.class);
+    when(defaultTemplatePermissionFinder.getDefaultTemplateUuids()).thenReturn(Collections.<String>emptySet());
+    PermissionDependenciesFinder finder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
+    ws = new WsActionTester(new DeleteTemplateAction(dbClient, userSession, finder, defaultTemplatePermissionFinder));
+
+    permissionTemplate = insertTemplateAndAssociatedPermissions(newPermissionTemplateDto().setKee(TEMPLATE_UUID));
+    PermissionTemplateDto permissionTemplateInDatabase = dbClient.permissionTemplateDao().selectByUuidWithUserAndGroupPermissions(dbSession, TEMPLATE_UUID);
+    assertThat(permissionTemplateInDatabase.getKee()).isEqualTo(TEMPLATE_UUID);
+    assertThat(permissionTemplateInDatabase.getGroupsPermissions()).isNotEmpty();
+    assertThat(permissionTemplateInDatabase.getUsersPermissions()).isNotEmpty();
+  }
+
+  @Test
+  public void delete_template_in_db() {
+    TestResponse result = newRequest(TEMPLATE_UUID);
+
+    assertThat(result.getInput()).isEmpty();
+    assertThat(dbClient.permissionTemplateDao().selectByUuidWithUserAndGroupPermissions(dbSession, TEMPLATE_UUID)).isNull();
+  }
+
+  @Test
+  public void delete_template_by_name_case_insensitive() {
+    ws.newRequest()
+      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
+      .execute();
+    commit();
+
+    assertThat(dbClient.permissionTemplateDao().selectByUuidWithUserAndGroupPermissions(dbSession, TEMPLATE_UUID)).isNull();
+  }
+
+  @Test
+  public void fail_if_uuid_is_not_known() {
+    expectedException.expect(NotFoundException.class);
+
+    newRequest("unknown-template-uuid");
+  }
+
+  @Test
+  public void fail_if_template_is_default() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("It is not possible to delete a default template");
+    when(defaultTemplatePermissionFinder.getDefaultTemplateUuids()).thenReturn(newSet(TEMPLATE_UUID));
+
+    newRequest(TEMPLATE_UUID);
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(TEMPLATE_UUID);
+  }
+
+  @Test
+  public void fail_if_not_admin() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.login().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest(TEMPLATE_UUID);
+  }
+
+  @Test
+  public void fail_if_uuid_is_not_provided() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(null);
+  }
+
+  private PermissionTemplateDto insertTemplateAndAssociatedPermissions(PermissionTemplateDto template) {
+    dbClient.permissionTemplateDao().insert(dbSession, template);
+    UserDto user = dbClient.userDao().insert(dbSession, UserTesting.newUserDto().setActive(true));
+    GroupDto group = dbClient.groupDao().insert(dbSession, GroupTesting.newGroupDto());
+    dbClient.permissionTemplateDao().insertUserPermission(dbSession, template.getId(), user.getId(), UserRole.ADMIN);
+    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getId(), group.getId(), UserRole.CODEVIEWER);
+    commit();
+
+    return template;
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private TestResponse newRequest(@Nullable String id) {
+    TestRequest request = ws.newRequest();
+    if (id != null) {
+      request.setParam(PARAM_TEMPLATE_ID, id);
+    }
+
+    TestResponse result = executeRequest(request);
+    commit();
+    return result;
+  }
+
+  private static TestResponse executeRequest(TestRequest request) {
+    return request.execute();
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveGroupFromTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveGroupFromTemplateActionTest.java
new file mode 100644 (file)
index 0000000..e372afa
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Function;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.GroupWithPermissionDto;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.WsPermissionParameters;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.security.DefaultGroups.ANYONE;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.db.user.GroupTesting.newGroupDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_GROUP_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
+
+@Category(DbTests.class)
+public class RemoveGroupFromTemplateActionTest {
+
+  private static final String GROUP_NAME = "group-name";
+  private static final String PERMISSION = CODEVIEWER;
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  GroupDto group;
+  PermissionTemplateDto permissionTemplate;
+
+  @Before
+  public void setUp() {
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
+    ws = new WsActionTester(new RemoveGroupFromTemplateAction(dbClient, dependenciesFinder, userSession));
+
+    group = insertGroup(newGroupDto().setName(GROUP_NAME));
+    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
+    addGroupToPermissionTemplate(permissionTemplate.getId(), group.getId(), PERMISSION);
+    commit();
+  }
+
+  @Test
+  public void remove_group_from_template() {
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
+    commit();
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
+  }
+
+  @Test
+  public void remove_group_from_template_by_name_case_insensitive() {
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
+    commit();
+
+    ws.newRequest()
+      .setParam(PARAM_GROUP_NAME, GROUP_NAME)
+      .setParam(PARAM_PERMISSION, PERMISSION)
+      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
+      .execute();
+    commit();
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
+  }
+
+  @Test
+  public void remove_group_with_group_id() {
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
+    commit();
+
+    ws.newRequest()
+      .setParam(PARAM_TEMPLATE_ID, permissionTemplate.getKee())
+      .setParam(PARAM_PERMISSION, PERMISSION)
+      .setParam(PARAM_GROUP_ID, String.valueOf(group.getId()))
+      .execute();
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
+  }
+
+  @Test
+  public void remove_group_twice_without_error() {
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).isEmpty();
+  }
+
+  @Test
+  public void remove_anyone_group_from_template() {
+    addGroupToPermissionTemplate(permissionTemplate.getId(), null, PERMISSION);
+    commit();
+
+    newRequest(ANYONE, permissionTemplate.getKee(), PERMISSION);
+
+    assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), PERMISSION)).containsExactly(GROUP_NAME);
+  }
+
+  @Test
+  public void fail_if_not_a_project_permission() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
+  }
+
+  @Test
+  public void fail_if_insufficient_privileges() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), PERMISSION);
+  }
+
+  @Test
+  public void fail_if_group_params_missing() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(null, permissionTemplate.getKee(), PERMISSION);
+  }
+
+  @Test
+  public void fail_if_permission_missing() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(GROUP_NAME, permissionTemplate.getKee(), null);
+  }
+
+  @Test
+  public void fail_if_template_missing() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(GROUP_NAME, null, PERMISSION);
+  }
+
+  @Test
+  public void fail_if_group_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Group with name 'unknown-group-name' is not found");
+
+    newRequest("unknown-group-name", permissionTemplate.getKee(), PERMISSION);
+  }
+
+  @Test
+  public void fail_if_template_key_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
+
+    newRequest(GROUP_NAME, "unknown-key", PERMISSION);
+  }
+
+  private void newRequest(@Nullable String groupName, @Nullable String templateKey, @Nullable String permission) {
+    TestRequest request = ws.newRequest();
+    if (groupName != null) {
+      request.setParam(WsPermissionParameters.PARAM_GROUP_NAME, groupName);
+    }
+    if (templateKey != null) {
+      request.setParam(PARAM_TEMPLATE_ID, templateKey);
+    }
+    if (permission != null) {
+      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
+    }
+
+    request.execute();
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private GroupDto insertGroup(GroupDto groupDto) {
+    return dbClient.groupDao().insert(dbSession, groupDto);
+  }
+
+  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
+    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
+  }
+
+  private void addGroupToPermissionTemplate(long permissionTemplateId, @Nullable Long groupId, String permission) {
+    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, permissionTemplateId, groupId, permission);
+  }
+
+  private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
+    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    return from(dbClient.permissionTemplateDao()
+      .selectGroups(dbSession, permissionQuery, templateId))
+      .transform(GroupWithPermissionToGroupName.INSTANCE)
+      .toList();
+  }
+
+  private enum GroupWithPermissionToGroupName implements Function<GroupWithPermissionDto, String> {
+    INSTANCE;
+
+    @Override
+    public String apply(@Nonnull GroupWithPermissionDto groupWithPermission) {
+      return groupWithPermission.getName();
+    }
+
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveUserFromTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/RemoveUserFromTemplateActionTest.java
new file mode 100644 (file)
index 0000000..588e651
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import com.google.common.base.Function;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.permission.UserWithPermissionDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.WsPermissionParameters;
+import org.sonar.server.permission.ws.template.RemoveUserFromTemplateAction;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
+import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.db.user.UserTesting.newUserDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_USER_LOGIN;
+
+@Category(DbTests.class)
+public class RemoveUserFromTemplateActionTest {
+
+  private static final String USER_LOGIN = "user-login";
+  private static final String DEFAULT_PERMISSION = CODEVIEWER;
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+  UserDto user;
+  PermissionTemplateDto permissionTemplate;
+
+  @Before
+  public void setUp() {
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
+    ws = new WsActionTester(new RemoveUserFromTemplateAction(dbClient, dependenciesFinder, userSession));
+
+    user = insertUser(newUserDto().setLogin(USER_LOGIN));
+    permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
+    addUserToTemplate(user, permissionTemplate, DEFAULT_PERMISSION);
+    commit();
+  }
+
+  @Test
+  public void remove_user_from_template() {
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
+  }
+
+  @Test
+  public void remove_user_from_template_by_name_case_insensitive() {
+    ws.newRequest()
+      .setParam(PARAM_USER_LOGIN, USER_LOGIN)
+      .setParam(PARAM_PERMISSION, DEFAULT_PERMISSION)
+      .setParam(PARAM_TEMPLATE_NAME, permissionTemplate.getName().toUpperCase())
+      .execute();
+    commit();
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
+  }
+
+  @Test
+  public void remove_user_from_template_twice_without_failing() {
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
+  }
+
+  @Test
+  public void keep_user_permission_not_removed() {
+    addUserToTemplate(user, permissionTemplate, ISSUE_ADMIN);
+    commit();
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).isEmpty();
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), ISSUE_ADMIN)).containsExactly(user.getLogin());
+  }
+
+  @Test
+  public void keep_other_users_when_one_user_removed() {
+    UserDto newUser = insertUser(newUserDto().setLogin("new-login"));
+    addUserToTemplate(newUser, permissionTemplate, DEFAULT_PERMISSION);
+    commit();
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+
+    assertThat(getLoginsInTemplateAndPermission(permissionTemplate.getId(), DEFAULT_PERMISSION)).containsExactly("new-login");
+  }
+
+  @Test
+  public void fail_if_not_a_project_permission() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
+  }
+
+  @Test
+  public void fail_if_insufficient_privileges() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+  }
+
+  @Test
+  public void fail_if_user_missing() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(null, permissionTemplate.getKee(), DEFAULT_PERMISSION);
+  }
+
+  @Test
+  public void fail_if_permission_missing() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(USER_LOGIN, permissionTemplate.getKee(), null);
+  }
+
+  @Test
+  public void fail_if_template_missing() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(USER_LOGIN, null, DEFAULT_PERMISSION);
+  }
+
+  @Test
+  public void fail_if_user_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("User with login 'unknown-login' is not found");
+
+    newRequest("unknown-login", permissionTemplate.getKee(), DEFAULT_PERMISSION);
+  }
+
+  @Test
+  public void fail_if_template_key_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
+
+    newRequest(USER_LOGIN, "unknown-key", DEFAULT_PERMISSION);
+  }
+
+  private void newRequest(@Nullable String userLogin, @Nullable String templateKey, @Nullable String permission) {
+    TestRequest request = ws.newRequest();
+    if (userLogin != null) {
+      request.setParam(PARAM_USER_LOGIN, userLogin);
+    }
+    if (templateKey != null) {
+      request.setParam(WsPermissionParameters.PARAM_TEMPLATE_ID, templateKey);
+    }
+    if (permission != null) {
+      request.setParam(WsPermissionParameters.PARAM_PERMISSION, permission);
+    }
+
+    request.execute();
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private UserDto insertUser(UserDto userDto) {
+    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
+  }
+
+  private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
+    return dbClient.permissionTemplateDao().insert(dbSession, permissionTemplate);
+  }
+
+  private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
+    PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+    return from(dbClient.permissionTemplateDao()
+      .selectUsers(dbSession, permissionQuery, templateId, 0, Integer.MAX_VALUE))
+      .transform(UserWithPermissionToUserLogin.INSTANCE)
+      .toList();
+  }
+
+  private enum UserWithPermissionToUserLogin implements Function<UserWithPermissionDto, String> {
+    INSTANCE;
+
+    @Override
+    public String apply(@Nonnull UserWithPermissionDto userWithPermission) {
+      return userWithPermission.getLogin();
+    }
+
+  }
+
+  private void addUserToTemplate(UserDto user, PermissionTemplateDto permissionTemplate, String permission) {
+    dbClient.permissionTemplateDao().insertUserPermission(dbSession, permissionTemplate.getId(), user.getId(), permission);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SearchTemplatesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SearchTemplatesActionTest.java
new file mode 100644 (file)
index 0000000..230b542
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.Date;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.i18n.I18nRule;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
+import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.db.user.GroupTesting.newGroupDto;
+import static org.sonar.db.user.UserTesting.newUserDto;
+import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
+import static org.sonar.test.JsonAssert.assertJson;
+
+@Category(DbTests.class)
+public class SearchTemplatesActionTest {
+  @ClassRule
+  public static DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  WsActionTester ws;
+  I18nRule i18n = new I18nRule();
+  DbClient dbClient = db.getDbClient();
+  DbSession dbSession = db.getSession();
+  ResourceTypes resourceTypes = mock(ResourceTypes.class);
+  SearchTemplatesDataLoader dataLoader;
+
+  SearchTemplatesAction underTest;
+
+  @Before
+  public void setUp() {
+    db.truncateTables();
+    i18n.setProjectPermissions();
+    when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
+
+    Settings settings = new Settings();
+    settings.setProperty(defaultRootQualifierTemplateProperty(Qualifiers.PROJECT), UUID_EXAMPLE_01);
+    settings.setProperty(defaultRootQualifierTemplateProperty(Qualifiers.VIEW), UUID_EXAMPLE_02);
+    settings.setProperty(defaultRootQualifierTemplateProperty("DEV"), UUID_EXAMPLE_03);
+
+    DefaultPermissionTemplateFinder defaultPermissionTemplateFinder = new DefaultPermissionTemplateFinder(settings, resourceTypes);
+
+    dataLoader = new SearchTemplatesDataLoader(dbClient, defaultPermissionTemplateFinder);
+    underTest = new SearchTemplatesAction(dbClient, userSession, i18n, dataLoader);
+
+    ws = new WsActionTester(underTest);
+
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+  }
+
+  @Test
+  public void search_project_permissions() {
+    PermissionTemplateDto projectTemplate = insertProjectTemplate();
+    PermissionTemplateDto viewsTemplate = insertViewsTemplate();
+    PermissionTemplateDto developerTemplate = insertDeveloperTemplate();
+
+    UserDto user1 = insertUser(newUserDto());
+    UserDto user2 = insertUser(newUserDto());
+    UserDto user3 = insertUser(newUserDto());
+
+    GroupDto group1 = insertGroup(newGroupDto());
+    GroupDto group2 = insertGroup(newGroupDto());
+    GroupDto group3 = insertGroup(newGroupDto());
+
+    addUserToTemplate(projectTemplate.getId(), user1.getId(), UserRole.ISSUE_ADMIN);
+    addUserToTemplate(projectTemplate.getId(), user2.getId(), UserRole.ISSUE_ADMIN);
+    addUserToTemplate(projectTemplate.getId(), user3.getId(), UserRole.ISSUE_ADMIN);
+    addUserToTemplate(projectTemplate.getId(), user1.getId(), UserRole.CODEVIEWER);
+    addGroupToTemplate(projectTemplate.getId(), group1.getId(), UserRole.ADMIN);
+
+    addUserToTemplate(viewsTemplate.getId(), user1.getId(), UserRole.USER);
+    addUserToTemplate(viewsTemplate.getId(), user2.getId(), UserRole.USER);
+    addGroupToTemplate(viewsTemplate.getId(), group1.getId(), UserRole.ISSUE_ADMIN);
+    addGroupToTemplate(viewsTemplate.getId(), group2.getId(), UserRole.ISSUE_ADMIN);
+    addGroupToTemplate(viewsTemplate.getId(), group3.getId(), UserRole.ISSUE_ADMIN);
+
+    addGroupToTemplate(developerTemplate.getId(), group1.getId(), UserRole.USER);
+
+    commit();
+
+    String result = newRequest();
+
+    assertJson(result)
+      .withStrictArrayOrder()
+      .isSimilarTo(getClass().getResource("search_templates-example.json"));
+  }
+
+  @Test
+  public void empty_result() {
+    String result = newRequest();
+
+    assertJson(result)
+      .withStrictArrayOrder()
+      .isSimilarTo(getClass().getResource("SearchTemplatesActionTest/empty.json"));
+  }
+
+  @Test
+  public void search_by_name() {
+    insertProjectTemplate();
+    insertViewsTemplate();
+    insertDeveloperTemplate();
+    commit();
+
+    String result = ws.newRequest()
+      .setParam(TEXT_QUERY, "views")
+      .execute().getInput();
+
+    assertThat(result).contains("Default template for Views")
+      .doesNotContain("projects")
+      .doesNotContain("developers");
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    ws.newRequest().execute();
+  }
+
+  @Test
+  public void fail_if_not_global_admin() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.login().setGlobalPermissions(QUALITY_PROFILE_ADMIN);
+
+    ws.newRequest().execute();
+  }
+
+  private String newRequest() {
+    return ws.newRequest().execute().getInput();
+  }
+
+  private PermissionTemplateDto insertProjectTemplate() {
+    return insertTemplate(newPermissionTemplateDto()
+      .setUuid(UUID_EXAMPLE_01)
+      .setName("Default template for Projects")
+      .setDescription("Template for new projects")
+      .setKeyPattern(null)
+      .setCreatedAt(new Date(1_000_000_000_000L))
+      .setUpdatedAt(new Date(1_000_000_000_000L)));
+  }
+
+  private PermissionTemplateDto insertViewsTemplate() {
+    return insertTemplate(newPermissionTemplateDto()
+      .setUuid(UUID_EXAMPLE_02)
+      .setName("Default template for Views")
+      .setDescription("Template for new views")
+      .setKeyPattern(".*sonar.views.*")
+      .setCreatedAt(new Date(1_000_000_000_000L))
+      .setUpdatedAt(new Date(1_100_000_000_000L)));
+  }
+
+  private PermissionTemplateDto insertDeveloperTemplate() {
+    return insertTemplate(newPermissionTemplateDto()
+      .setUuid(UUID_EXAMPLE_03)
+      .setName("Default template for Developers")
+      .setKeyPattern(".*sonar.developer.*")
+      .setDescription(null)
+      .setCreatedAt(new Date(1_100_500_000_000L))
+      .setUpdatedAt(new Date(1_100_900_000_000L)));
+  }
+
+  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
+    return dbClient.permissionTemplateDao().insert(dbSession, template);
+  }
+
+  private GroupDto insertGroup(GroupDto groupDto) {
+    return dbClient.groupDao().insert(dbSession, groupDto);
+  }
+
+  private UserDto insertUser(UserDto userDto) {
+    return dbClient.userDao().insert(dbSession, userDto.setActive(true));
+  }
+
+  private void addGroupToTemplate(long templateId, @Nullable Long groupId, String permission) {
+    dbClient.permissionTemplateDao().insertGroupPermission(dbSession, templateId, groupId, permission);
+  }
+
+  private void addUserToTemplate(long templateId, long userId, String permission) {
+    dbClient.permissionTemplateDao().insertUserPermission(dbSession, templateId, userId, permission);
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private static List<ResourceType> rootResourceTypes() {
+    ResourceType project = ResourceType.builder(Qualifiers.PROJECT).build();
+    ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
+    ResourceType dev = ResourceType.builder("DEV").build();
+
+    return asList(project, view, dev);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java
new file mode 100644 (file)
index 0000000..6031f41
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.List;
+import java.util.Properties;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.permission.PermissionTemplateTesting;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.i18n.I18nRule;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.permission.ws.template.SetDefaultTemplateAction;
+import org.sonar.server.platform.PersistentSettings;
+import org.sonar.server.platform.ServerSettings;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.api.resources.Qualifiers.VIEW;
+import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
+import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_QUALIFIER;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_TEMPLATE_NAME;
+
+@Category(DbTests.class)
+public class SetDefaultTemplateActionTest {
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  I18nRule i18n = new I18nRule();
+
+  WsActionTester ws;
+  PersistentSettings persistentSettings;
+  ResourceTypes resourceTypes = mock(ResourceTypes.class);
+
+  PermissionTemplateDto template;
+
+  @Before
+  public void setUp() {
+    DbClient dbClient = db.getDbClient();
+    persistentSettings = new PersistentSettings(dbClient.propertiesDao(), new ServerSettings(new PropertyDefinitions(), new Properties()));
+    persistentSettings.saveProperty(DEFAULT_TEMPLATE_PROPERTY, "any-template-uuid");
+    persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(PROJECT), "any-template-uuid");
+    persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(VIEW), "any-view-template-uuid");
+    persistentSettings.saveProperty(defaultRootQualifierTemplateProperty("DEV"), "any-dev-template-uuid");
+    when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    ws = new WsActionTester(new SetDefaultTemplateAction(
+      dbClient,
+      new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient)),
+      resourceTypes,
+      persistentSettings,
+      userSession, i18n));
+
+    template = dbClient.permissionTemplateDao().insert(db.getSession(), PermissionTemplateTesting.newPermissionTemplateDto().setUuid("permission-template-uuid"));
+  }
+
+  @Test
+  public void update_settings_for_project_qualifier() {
+    // default value is project qualifier's value
+    String result = newRequest(template.getUuid(), null);
+
+    assertThat(result).isEmpty();
+    assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo("any-template-uuid");
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo(template.getUuid());
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo("any-view-template-uuid");
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
+  }
+
+  @Test
+  public void update_settings_for_project_qualifier_by_template_name() {
+    ws.newRequest()
+      .setParam(PARAM_TEMPLATE_NAME, template.getName().toUpperCase())
+      .execute();
+    db.getSession().commit();
+
+    assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo("any-template-uuid");
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo(template.getUuid());
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo("any-view-template-uuid");
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
+  }
+
+  @Test
+  public void update_settings_of_views_property() {
+    newRequest(template.getUuid(), VIEW);
+
+    assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo("any-template-uuid");
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo("any-template-uuid");
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo(template.getUuid());
+    assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
+  }
+
+  @Test
+  public void fail_if_anonymous() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(template.getUuid(), PROJECT);
+  }
+
+  @Test
+  public void fail_if_not_admin() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.login().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest(template.getUuid(), PROJECT);
+  }
+
+  @Test
+  public void fail_if_template_not_provided() {
+    expectedException.expect(BadRequestException.class);
+
+    newRequest(null, PROJECT);
+  }
+
+  @Test
+  public void fail_if_template_does_not_exist() {
+    expectedException.expect(NotFoundException.class);
+
+    newRequest("unknown-template-uuid", PROJECT);
+  }
+
+  @Test
+  public void fail_if_qualifier_is_not_root() {
+    expectedException.expect(BadRequestException.class);
+    when(resourceTypes.getRoots()).thenReturn(singletonList(ResourceType.builder(PROJECT).build()));
+
+    newRequest(template.getUuid(), VIEW);
+  }
+
+  private String newRequest(@Nullable String templateUuid, @Nullable String qualifier) {
+    TestRequest request = ws.newRequest();
+    if (templateUuid != null) {
+      request.setParam(PARAM_TEMPLATE_ID, templateUuid);
+    }
+    if (qualifier != null) {
+      request.setParam(PARAM_QUALIFIER, qualifier);
+    }
+
+    return request.execute().getInput();
+  }
+
+  private static List<ResourceType> rootResourceTypes() {
+    ResourceType project = ResourceType.builder(PROJECT).build();
+    ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
+    ResourceType dev = ResourceType.builder("DEV").build();
+
+    return asList(project, view, dev);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/UpdateTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/UpdateTemplateActionTest.java
new file mode 100644 (file)
index 0000000..515fa91
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.permission.ws.template;
+
+import java.util.Date;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.permission.ws.PermissionDependenciesFinder;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_DESCRIPTION;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_ID;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_NAME;
+import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_PATTERN;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class UpdateTemplateActionTest {
+
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  WsActionTester ws;
+  DbClient dbClient;
+  DbSession dbSession;
+
+  PermissionTemplateDto templateDto;
+
+  @Before
+  public void setUp() {
+    userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    System2 system = mock(System2.class);
+    when(system.now()).thenReturn(1_440_512_328_743L);
+
+    dbClient = db.getDbClient();
+    dbSession = db.getSession();
+    PermissionDependenciesFinder finder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
+
+    ws = new WsActionTester(new UpdateTemplateAction(dbClient, userSession, system, finder));
+
+    templateDto = insertTemplate(newPermissionTemplateDto()
+      .setName("Permission Template Name")
+      .setDescription("Permission Template Description")
+      .setKeyPattern(".*\\.pattern\\..*")
+      .setCreatedAt(new Date(1_000_000_000_000L))
+      .setUpdatedAt(new Date(1_000_000_000_000L)));
+    commit();
+  }
+
+  @Test
+  public void update_all_permission_template_fields() {
+    TestResponse result = newRequest(templateDto.getKee(), "Finance", "Permissions for financially related projects", ".*\\.finance\\..*");
+
+    assertJson(result.getInput())
+      .ignoreFields("id")
+      .isSimilarTo(getClass().getResource("update_template-example.json"));
+    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
+    assertThat(finance.getName()).isEqualTo("Finance");
+    assertThat(finance.getDescription()).isEqualTo("Permissions for financially related projects");
+    assertThat(finance.getKeyPattern()).isEqualTo(".*\\.finance\\..*");
+    assertThat(finance.getKee()).isEqualTo(templateDto.getKee());
+    assertThat(finance.getCreatedAt()).isEqualTo(templateDto.getCreatedAt());
+    assertThat(finance.getUpdatedAt().getTime()).isEqualTo(1440512328743L);
+  }
+
+  @Test
+  public void update_with_the_same_values() {
+    newRequest(templateDto.getKee(), templateDto.getName(), templateDto.getDescription(), templateDto.getKeyPattern());
+
+    PermissionTemplateDto updatedTemplate = dbClient.permissionTemplateDao().selectByUuid(dbSession, templateDto.getKee());
+    assertThat(updatedTemplate.getName()).isEqualTo(templateDto.getName());
+    assertThat(updatedTemplate.getDescription()).isEqualTo(templateDto.getDescription());
+    assertThat(updatedTemplate.getKeyPattern()).isEqualTo(templateDto.getKeyPattern());
+  }
+
+  @Test
+  public void update_name_only() {
+    newRequest(templateDto.getKee(), "Finance", null, null);
+
+    PermissionTemplateDto finance = dbClient.permissionTemplateDao().selectByName(dbSession, "Finance");
+    assertThat(finance.getName()).isEqualTo("Finance");
+    assertThat(finance.getDescription()).isEqualTo(templateDto.getDescription());
+    assertThat(finance.getKeyPattern()).isEqualTo(templateDto.getKeyPattern());
+  }
+
+  @Test
+  public void fail_if_key_is_not_found() {
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Permission template with id 'unknown-key' is not found");
+
+    newRequest("unknown-key", null, null, null);
+  }
+
+  @Test
+  public void fail_if_name_already_exists_in_another_template() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("A template with the name 'My Template' already exists (case insensitive).");
+
+    insertTemplate(newPermissionTemplateDto()
+      .setName("My Template")
+      .setKee("my-key")
+      .setCreatedAt(new Date(12345789L))
+      .setUpdatedAt(new Date(12345789L)));
+    commit();
+
+    newRequest(templateDto.getKee(), "My Template", null, null);
+  }
+
+  @Test
+  public void fail_if_key_is_not_provided() {
+    expectedException.expect(IllegalArgumentException.class);
+
+    newRequest(null, "Finance", null, null);
+  }
+
+  @Test
+  public void fail_if_name_empty() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("The template name must not be blank");
+
+    newRequest(templateDto.getKee(), "", null, null);
+  }
+
+  @Test
+  public void fail_if_name_has_just_whitespaces() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("The template name must not be blank");
+
+    newRequest(templateDto.getKee(), "  \r\n", null, null);
+  }
+
+  @Test
+  public void fail_if_regexp_if_not_valid() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("The 'projectKeyPattern' parameter must be a valid Java regular expression. '[azerty' was passed");
+
+    newRequest(templateDto.getKee(), "Finance", null, "[azerty");
+  }
+
+  @Test
+  public void fail_if_name_already_exists_in_database_case_insensitive() {
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("A template with the name 'Finance' already exists (case insensitive).");
+    insertTemplate(newPermissionTemplateDto().setName("finance"));
+    commit();
+
+    newRequest(templateDto.getKee(), "Finance", null, null);
+  }
+
+  @Test
+  public void fail_if_not_logged_in() {
+    expectedException.expect(UnauthorizedException.class);
+    userSession.anonymous();
+
+    newRequest(templateDto.getKee(), "Finance", null, null);
+  }
+
+  @Test
+  public void fail_if_not_admin() {
+    expectedException.expect(ForbiddenException.class);
+    userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+    newRequest(templateDto.getKee(), "Finance", null, null);
+  }
+
+  private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
+    return dbClient.permissionTemplateDao().insert(dbSession, template);
+  }
+
+  private GroupDto insertGroup(GroupDto group) {
+    return dbClient.groupDao().insert(db.getSession(), group);
+  }
+
+  private void commit() {
+    dbSession.commit();
+  }
+
+  private TestResponse newRequest(@Nullable String key, @Nullable String name, @Nullable String description, @Nullable String projectPattern) {
+    TestRequest request = ws.newRequest();
+    if (key != null) {
+      request.setParam(PARAM_ID, key);
+    }
+    if (name != null) {
+      request.setParam(PARAM_NAME, name);
+    }
+    if (description != null) {
+      request.setParam(PARAM_DESCRIPTION, description);
+    }
+    if (projectPattern != null) {
+      request.setParam(PARAM_PATTERN, projectPattern);
+    }
+
+    return request.execute();
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/SearchTemplatesActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/SearchTemplatesActionTest/empty.json
deleted file mode 100644 (file)
index 985f39e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "permissionTemplates": [],
-  "defaultTemplates": [
-    {
-      "templateId": "AU-Tpxb--iU5OvuD2FLy",
-      "qualifier": "TRK"
-    },
-    {
-      "templateId": "AU-TpxcA-iU5OvuD2FLz",
-      "qualifier": "VW"
-    },
-    {
-      "templateId": "AU-TpxcA-iU5OvuD2FL0",
-      "qualifier": "DEV"
-    }
-  ],
-  "permissions": [
-    {
-      "key": "user",
-      "name": "Browse",
-      "description": "Ability to access a project, browse its measures, and create/edit issues for it."
-    },
-    {
-      "key": "admin",
-      "name": "Administer",
-      "description": "Ability to access project settings and perform administration tasks. (Users will also need \"Browse\" permission)"
-    },
-    {
-      "key": "issueadmin",
-      "name": "Administer Issues",
-      "description": "Grants the permission to perform advanced editing on issues: marking an issue False Positive / Won't Fix or changing an Issue's severity. (Users will also need \"Browse\" permission)"
-    },
-    {
-      "key": "codeviewer",
-      "name": "See Source Code",
-      "description": "Ability to view the project's source code. (Users will also need \"Browse\" permission)"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/template/SearchTemplatesActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/template/SearchTemplatesActionTest/empty.json
new file mode 100644 (file)
index 0000000..985f39e
--- /dev/null
@@ -0,0 +1,39 @@
+{
+  "permissionTemplates": [],
+  "defaultTemplates": [
+    {
+      "templateId": "AU-Tpxb--iU5OvuD2FLy",
+      "qualifier": "TRK"
+    },
+    {
+      "templateId": "AU-TpxcA-iU5OvuD2FLz",
+      "qualifier": "VW"
+    },
+    {
+      "templateId": "AU-TpxcA-iU5OvuD2FL0",
+      "qualifier": "DEV"
+    }
+  ],
+  "permissions": [
+    {
+      "key": "user",
+      "name": "Browse",
+      "description": "Ability to access a project, browse its measures, and create/edit issues for it."
+    },
+    {
+      "key": "admin",
+      "name": "Administer",
+      "description": "Ability to access project settings and perform administration tasks. (Users will also need \"Browse\" permission)"
+    },
+    {
+      "key": "issueadmin",
+      "name": "Administer Issues",
+      "description": "Grants the permission to perform advanced editing on issues: marking an issue False Positive / Won't Fix or changing an Issue's severity. (Users will also need \"Browse\" permission)"
+    },
+    {
+      "key": "codeviewer",
+      "name": "See Source Code",
+      "description": "Ability to view the project's source code. (Users will also need \"Browse\" permission)"
+    }
+  ]
+}