]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6496 WS permissions/create_template create a permission template
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Tue, 25 Aug 2015 15:29:19 +0000 (17:29 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 27 Aug 2015 07:45:49 +0000 (09:45 +0200)
25 files changed:
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionRequestValidator.java
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/CreateTemplateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/Parameters.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionTemplateDtoBuilder.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
server/sonar-server/src/main/java/org/sonar/server/startup/RegisterPermissionTemplates.java
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/create_template-example.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/CreateTemplateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupFromTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/startup/RegisterPermissionTemplatesTest.java
server/sonar-server/src/test/resources/org/sonar/server/permission/ws/CreateTemplateActionTest/create_template.json [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java
sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml
sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java
sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateTesting.java
sonar-ws/src/main/gen-java/org/sonarqube/ws/Permissions.java
sonar-ws/src/main/protobuf/ws-permissions.proto

index 9ce5d35934b835024342c3a2bcb3ec9f02cd1cdc..66292b48b24ba3fdd428eed4873a2ebc84315716 100644 (file)
 
 package org.sonar.server.permission;
 
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 import javax.annotation.Nullable;
 import org.sonar.core.permission.GlobalPermissions;
 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.exceptions.BadRequestException;
 
+import static com.google.common.base.Strings.isNullOrEmpty;
 import static java.lang.String.format;
 import static org.sonar.api.security.DefaultGroups.isAnyone;
 import static org.sonar.server.ws.WsUtils.checkRequest;
 
 public class PermissionRequestValidator {
+  public static final String MSG_TEMPLATE_WITH_SAME_NAME = "A template with the name '%s' already exists (case insensitive).";
+  public static final String MSG_TEMPLATE_NAME_NOT_BLANK = "The template name must not be blank";
+
   private PermissionRequestValidator() {
     // static methods only
   }
@@ -45,6 +55,26 @@ public class PermissionRequestValidator {
 
   public static void validateNotAnyoneAndAdminPermission(String permission, @Nullable String groupName) {
     checkRequest(!GlobalPermissions.SYSTEM_ADMIN.equals(permission) || !isAnyone(groupName),
-      String.format("It is not possible to add the '%s' permission to the '%s' group.", permission, groupName));
+      format("It is not possible to add the '%s' permission to the '%s' group.", permission, groupName));
+  }
+
+  public static void validateProjectPattern(@Nullable String projectPattern) {
+    if (isNullOrEmpty(projectPattern)) {
+      return;
+    }
+
+    try {
+      Pattern.compile(projectPattern);
+    } catch (PatternSyntaxException e) {
+      throw new BadRequestException(format("The 'projectPattern' parameter must be a valid Java regular expression. '%s' was passed", projectPattern));
+    }
+  }
+
+  public static void validateTemplateNameForUpdate(DbSession dbSession, DbClient dbClient, String templateName, long templateId) {
+    checkRequest(!templateName.isEmpty(), MSG_TEMPLATE_NAME_NOT_BLANK);
+
+    PermissionTemplateDto permissionTemplateWithSameName = dbClient.permissionTemplateDao().selectByName(dbSession, templateName);
+    checkRequest(permissionTemplateWithSameName == null || permissionTemplateWithSameName.getId() == templateId,
+      format(MSG_TEMPLATE_WITH_SAME_NAME, templateName));
   }
 }
index b5e9aec8fb39f25298d432655bc38456f6a2707a..6962215643aecf2730fc2c34044b514fbd07a905 100644 (file)
 package org.sonar.server.permission;
 
 import com.google.common.collect.Lists;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
 import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.Uuids;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.permission.PermissionTemplateDao;
 import org.sonar.db.permission.PermissionTemplateDto;
 import org.sonar.db.user.GroupDto;
-import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UserSession;
 
+import static java.lang.String.format;
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
 import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentKey;
+import static org.sonar.server.permission.PermissionRequestValidator.MSG_TEMPLATE_NAME_NOT_BLANK;
+import static org.sonar.server.permission.PermissionRequestValidator.MSG_TEMPLATE_WITH_SAME_NAME;
+import static org.sonar.server.permission.PermissionRequestValidator.validateProjectPattern;
+import static org.sonar.server.permission.PermissionRequestValidator.validateTemplateNameForUpdate;
+import static org.sonar.server.ws.WsUtils.checkRequest;
 
 /**
  * Used by ruby code <pre>Internal.permission_templates</pre>
@@ -91,19 +96,39 @@ public class PermissionTemplateService {
     return permissionTemplates;
   }
 
-  public PermissionTemplate createPermissionTemplate(String name, @Nullable String description, @Nullable String keyPattern) {
-    checkGlobalAdminUser(userSession);
-    validateTemplateName(null, name);
-    validateKeyPattern(keyPattern);
-    PermissionTemplateDto permissionTemplateDto = permissionTemplateDao.insertPermissionTemplate(name, description, keyPattern);
-    return PermissionTemplate.create(permissionTemplateDto);
+  public PermissionTemplate createPermissionTemplate(String name, @Nullable String description, @Nullable String projectKeyPattern) {
+    DbSession dbSession = dbClient.openSession(false);
+
+    try {
+      checkGlobalAdminUser(userSession);
+      validateTemplateNameForCreation(dbSession, name);
+      validateProjectPattern(projectKeyPattern);
+      Date now = new Date(System2.INSTANCE.now());
+      PermissionTemplateDto permissionTemplateDto = permissionTemplateDao.insert(dbSession, new PermissionTemplateDto()
+        .setKee(Uuids.create())
+        .setName(name)
+        .setKeyPattern(projectKeyPattern)
+        .setDescription(description)
+        .setCreatedAt(now)
+        .setUpdatedAt(now));
+      dbSession.commit();
+      return PermissionTemplate.create(permissionTemplateDto);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
   }
 
-  public void updatePermissionTemplate(Long templateId, String newName, @Nullable String newDescription, @Nullable String newKeyPattern) {
-    checkGlobalAdminUser(userSession);
-    validateTemplateName(templateId, newName);
-    validateKeyPattern(newKeyPattern);
-    permissionTemplateDao.updatePermissionTemplate(templateId, newName, newDescription, newKeyPattern);
+  public void updatePermissionTemplate(Long templateId, String newName, @Nullable String newDescription, @Nullable String projectPattern) {
+    DbSession dbSession = dbClient.openSession(false);
+
+    try {
+      checkGlobalAdminUser(userSession);
+      validateTemplateNameForUpdate(dbSession, dbClient, newName, templateId);
+      validateProjectPattern(projectPattern);
+      permissionTemplateDao.update(templateId, newName, newDescription, projectPattern);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
   }
 
   public void deletePermissionTemplate(Long templateId) {
@@ -186,32 +211,14 @@ public class PermissionTemplateService {
     }
   }
 
-  private void validateTemplateName(@Nullable Long templateId, String templateName) {
-    if (StringUtils.isEmpty(templateName)) {
-      String errorMsg = "Name can't be blank";
-      throw new BadRequestException(errorMsg);
-    }
-    List<PermissionTemplateDto> existingTemplates = permissionTemplateDao.selectAllPermissionTemplates();
-    if (existingTemplates != null) {
-      for (PermissionTemplateDto existingTemplate : existingTemplates) {
-        if ((templateId == null || !existingTemplate.getId().equals(templateId)) && (existingTemplate.getName().equals(templateName))) {
-          String errorMsg = "A template with that name already exists";
-          throw new BadRequestException(errorMsg);
-        }
-      }
-    }
-  }
+  /**
+   * @deprecated since 5.2
+   */
+  @Deprecated
+  private void validateTemplateNameForCreation(DbSession dbSession, String templateName) {
+    checkRequest(!templateName.isEmpty(), MSG_TEMPLATE_NAME_NOT_BLANK);
 
-  private static void validateKeyPattern(@Nullable String keyPattern) {
-    if (StringUtils.isEmpty(keyPattern)) {
-      return;
-    }
-    try {
-      Pattern.compile(keyPattern);
-    } catch (PatternSyntaxException e) {
-      String errorMsg = "Invalid pattern: " + keyPattern + ". Should be a valid Java regular expression.";
-      throw new BadRequestException(errorMsg);
-    }
+    PermissionTemplateDto permissionTemplateWithSameName = dbClient.permissionTemplateDao().selectByName(dbSession, templateName);
+    checkRequest(permissionTemplateWithSameName == null, format(MSG_TEMPLATE_WITH_SAME_NAME, templateName));
   }
-
 }
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
new file mode 100644 (file)
index 0000000..1036ad9
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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.Permissions;
+import org.sonarqube.ws.Permissions.PermissionTemplate;
+
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.PermissionRequestValidator.MSG_TEMPLATE_NAME_NOT_BLANK;
+import static org.sonar.server.permission.PermissionRequestValidator.MSG_TEMPLATE_WITH_SAME_NAME;
+import static org.sonar.server.permission.PermissionRequestValidator.validateProjectPattern;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_DESCRIPTION;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_NAME;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_PATTERN;
+import static org.sonar.server.permission.ws.PermissionTemplateDtoBuilder.create;
+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_TEMPLATE_NAME)
+      .setRequired(true)
+      .setDescription("Name")
+      .setExampleValue("Financial Service Permissions");
+
+    action.createParam(PARAM_TEMPLATE_PATTERN)
+      .setDescription("Project key pattern. Must be a valid Java regular expression")
+      .setExampleValue(".*\\.finance\\..*");
+
+    action.createParam(PARAM_TEMPLATE_DESCRIPTION)
+      .setDescription("Description")
+      .setExampleValue("Permissions for all projects related to the financial service");
+  }
+
+  @Override
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
+    String name = wsRequest.mandatoryParam(PARAM_TEMPLATE_NAME);
+    String description = wsRequest.param(PARAM_TEMPLATE_DESCRIPTION);
+    String projectPattern = wsRequest.param(PARAM_TEMPLATE_PATTERN);
+
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      checkGlobalAdminUser(userSession);
+      validateTemplateNameForCreation(dbSession, name);
+      validateProjectPattern(projectPattern);
+
+      PermissionTemplateDto permissionTemplate = insertTemplate(dbSession, name, description, projectPattern);
+
+      Permissions.CreatePermissionTemplateResponse response = buildResponse(permissionTemplate);
+      writeProtobuf(response, wsRequest, wsResponse);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private void validateTemplateNameForCreation(DbSession dbSession, String templateName) {
+    checkRequest(!templateName.isEmpty(), MSG_TEMPLATE_NAME_NOT_BLANK);
+
+    PermissionTemplateDto permissionTemplateWithSameName = dbClient.permissionTemplateDao().selectByName(dbSession, templateName);
+    checkRequest(permissionTemplateWithSameName == null, String.format
+      (MSG_TEMPLATE_WITH_SAME_NAME, templateName));
+  }
+
+  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 Permissions.CreatePermissionTemplateResponse buildResponse(PermissionTemplateDto permissionTemplate) {
+    PermissionTemplate.Builder permissionTemplateBuilder = PermissionTemplate.newBuilder()
+      .setKey(permissionTemplate.getKee())
+      .setName(permissionTemplate.getName())
+      .setCreatedAt(formatDateTime(permissionTemplate.getCreatedAt()))
+      .setUpdatedAt(formatDateTime(permissionTemplate.getUpdatedAt()));
+    if (permissionTemplate.getDescription() != null) {
+      permissionTemplateBuilder.setDescription(permissionTemplate.getDescription());
+    }
+    if (permissionTemplate.getKeyPattern() != null) {
+      permissionTemplateBuilder.setProjectPattern(permissionTemplate.getKeyPattern());
+    }
+    return Permissions.CreatePermissionTemplateResponse.newBuilder().setPermissionTemplate(permissionTemplateBuilder).build();
+  }
+}
index e15cd93a0798897df766916a40fd588b804d9b3b..a06aa8e19abb5a5fd13551c6fdebd008390a97d6 100644 (file)
@@ -33,6 +33,9 @@ class Parameters {
   static final String PARAM_PROJECT_KEY = "projectKey";
   static final String PARAM_USER_LOGIN = "login";
   static final String PARAM_TEMPLATE_KEY = "templateKey";
+  static final String PARAM_TEMPLATE_NAME = "name";
+  static final String PARAM_TEMPLATE_DESCRIPTION = "description";
+  static final String PARAM_TEMPLATE_PATTERN = "projectPattern";
 
   private static final String PERMISSION_PARAM_DESCRIPTION = String.format("Permission" +
     "<ul>" +
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
new file mode 100644 (file)
index 0000000..157d1aa
--- /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;
+
+import java.util.Date;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.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));
+  }
+}
index 3dd5be9d5d478e1541fad6d5460b8b773537b828..48b3b12a7338790da32454b93f489a97024583fc 100644 (file)
@@ -41,6 +41,7 @@ public class PermissionsWsModule extends Module {
       AddUserToTemplateAction.class,
       RemoveUserFromTemplateAction.class,
       AddGroupToTemplateAction.class,
-      RemoveGroupFromTemplateAction.class);
+      RemoveGroupFromTemplateAction.class,
+      CreateTemplateAction.class);
   }
 }
index 6a24cf2520f4b8dbb9b731c4dd7dc36bbe8d7bd6..3a4b3f976eb51d872fb5c7421ff0e6fc72b3722a 100644 (file)
@@ -73,7 +73,7 @@ public class RegisterPermissionTemplates {
 
   private void insertDefaultTemplate(String templateName) {
     PermissionTemplateDto defaultPermissionTemplate = dbClient.permissionTemplateDao()
-      .insertPermissionTemplate(templateName, PermissionTemplateDto.DEFAULT.getDescription(), null);
+      .insert(templateName, PermissionTemplateDto.DEFAULT.getDescription(), null);
     addGroupPermission(defaultPermissionTemplate, UserRole.ADMIN, DefaultGroups.ADMINISTRATORS);
     addGroupPermission(defaultPermissionTemplate, UserRole.ISSUE_ADMIN, DefaultGroups.ADMINISTRATORS);
     addGroupPermission(defaultPermissionTemplate, UserRole.USER, DefaultGroups.ANYONE);
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
new file mode 100644 (file)
index 0000000..51c1491
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "permissionTemplate": {
+    "key": "af8cb8cc-1e78-4c4e-8c00-ee8e814009a5",
+    "name": "Finance",
+    "description": "Permissions for financial related projects",
+    "createdAt": "2015-08-25T16:18:48+0200",
+    "updatedAt": "2015-08-25T16:18:48+0200"
+  }
+}
index de439cab5c1c774ed456e342206f8eb0d5d1b5e0..9e848d82944002197be73a78c880f19620fe18a0 100644 (file)
@@ -105,7 +105,7 @@ public class ApplyPermissionsStepTest extends BaseStepTest {
     dbClient.componentDao().insert(dbSession, projectDto);
 
     // Create a permission template containing browse permission for anonymous group
-    PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().insertPermissionTemplate("Default", null, null);
+    PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().insert("Default", null, null);
     settings.setProperty("sonar.permission.template.default", permissionTemplateDto.getKee());
     dbClient.permissionTemplateDao().insertGroupPermission(permissionTemplateDto.getId(), null, UserRole.USER);
     dbSession.commit();
index 8c8bda49bcf18d4f37ecf9a8bca41e3dc18a626f..a3cff58ecb756cc24310f9ca3a6fb0b8a2800c3d 100644 (file)
@@ -44,6 +44,7 @@ import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.tester.UserSessionRule;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
@@ -108,7 +109,7 @@ public class PermissionTemplateServiceTest {
 
   @Test
   public void should_create_permission_template() {
-    when(permissionTemplateDao.insertPermissionTemplate(DEFAULT_KEY, DEFAULT_DESC, DEFAULT_PATTERN)).thenReturn(DEFAULT_TEMPLATE);
+    when(permissionTemplateDao.insert(any(DbSession.class), any(PermissionTemplateDto.class))).thenReturn(DEFAULT_TEMPLATE);
 
     PermissionTemplate permissionTemplate = underTest.createPermissionTemplate(DEFAULT_KEY, DEFAULT_DESC, DEFAULT_PATTERN);
 
@@ -121,9 +122,9 @@ public class PermissionTemplateServiceTest {
   @Test
   public void should_enforce_unique_template_name() {
     expected.expect(BadRequestException.class);
-    expected.expectMessage("A template with that name already exists");
+    expected.expectMessage("A template with the name 'my_template' already exists (case insensitive).");
 
-    when(permissionTemplateDao.selectAllPermissionTemplates()).thenReturn(Lists.newArrayList(DEFAULT_TEMPLATE));
+    when(permissionTemplateDao.selectByName(any(DbSession.class), anyString())).thenReturn(DEFAULT_TEMPLATE);
 
     underTest.createPermissionTemplate(DEFAULT_KEY, DEFAULT_DESC, null);
   }
@@ -131,7 +132,7 @@ public class PermissionTemplateServiceTest {
   @Test
   public void should_reject_empty_name_on_creation() {
     expected.expect(BadRequestException.class);
-    expected.expectMessage("Name can't be blank");
+    expected.expectMessage("The template name must not be blank");
 
     underTest.createPermissionTemplate("", DEFAULT_DESC, null);
   }
@@ -139,7 +140,7 @@ public class PermissionTemplateServiceTest {
   @Test
   public void should_reject_invalid_key_pattern_on_creation() {
     expected.expect(BadRequestException.class);
-    expected.expectMessage("Invalid pattern: [azerty. Should be a valid Java regular expression.");
+    expected.expectMessage("The 'projectPattern' parameter must be a valid Java regular expression. '[azerty' was passed");
 
     underTest.createPermissionTemplate(DEFAULT_KEY, DEFAULT_DESC, "[azerty");
   }
@@ -227,27 +228,25 @@ public class PermissionTemplateServiceTest {
 
     underTest.updatePermissionTemplate(1L, "new_name", "new_description", null);
 
-    verify(permissionTemplateDao).updatePermissionTemplate(1L, "new_name", "new_description", null);
+    verify(permissionTemplateDao).update(1L, "new_name", "new_description", null);
   }
 
   @Test
   public void should_validate_template_name_on_update_if_applicable() {
     expected.expect(BadRequestException.class);
-    expected.expectMessage("A template with that name already exists");
+    expected.expectMessage("A template with the name 'template2' already exists (case insensitive).");
 
-    PermissionTemplateDto template1 =
-      new PermissionTemplateDto().setId(1L).setName("template1").setDescription("template1");
     PermissionTemplateDto template2 =
       new PermissionTemplateDto().setId(2L).setName("template2").setDescription("template2");
-    when(permissionTemplateDao.selectAllPermissionTemplates()).thenReturn(Lists.newArrayList(template1, template2));
+    when(permissionTemplateDao.selectByName(any(DbSession.class), eq("template2"))).thenReturn(template2);
 
-    underTest.updatePermissionTemplate(1L, "template2", "template1", null);
+    underTest.updatePermissionTemplate(1L, "template2", "template2", null);
   }
 
   @Test
   public void should_validate_template_key_pattern_on_update_if_applicable() {
     expected.expect(BadRequestException.class);
-    expected.expectMessage("Invalid pattern: [azerty. Should be a valid Java regular expression.");
+    expected.expectMessage("The 'projectPattern' parameter must be a valid Java regular expression. '[azerty' was passed");
 
     PermissionTemplateDto template1 = new PermissionTemplateDto().setId(1L).setName("template1").setDescription("template1");
     when(permissionTemplateDao.selectAllPermissionTemplates()).thenReturn(Lists.newArrayList(template1));
@@ -265,7 +264,7 @@ public class PermissionTemplateServiceTest {
 
     underTest.updatePermissionTemplate(1L, "template1", "new_description", null);
 
-    verify(permissionTemplateDao).updatePermissionTemplate(1L, "template1", "new_description", null);
+    verify(permissionTemplateDao).update(1L, "template1", "new_description", null);
   }
 
   @Test
index 221fbfcf76e972a07e1b8af5310def14d4af9bd4..ba439ba42bf90d0aed4a8a5e8f3966aeb5d40256 100644 (file)
@@ -218,7 +218,7 @@ public class AddGroupToTemplateActionTest {
   }
 
   private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insertPermissionTemplate(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
+    return dbClient.permissionTemplateDao().insert(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
   }
 
   private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
index a4fdf5f09cc175d00e2f76aea08244246b0205b2..4cb43afecb8ad85208e9554059b787a38cb7d1cc 100644 (file)
@@ -186,7 +186,7 @@ public class AddUserToTemplateActionTest {
   }
 
   private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insertPermissionTemplate(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
+    return dbClient.permissionTemplateDao().insert(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
   }
 
   private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
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
new file mode 100644 (file)
index 0000000..e4208ea
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * 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.Parameters.PARAM_TEMPLATE_DESCRIPTION;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_NAME;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_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()).isSimilarTo(getClass().getResource("CreateTemplateActionTest/create_template.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 'projectPattern' 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_TEMPLATE_NAME, name);
+    }
+    if (description != null) {
+      request.setParam(PARAM_TEMPLATE_DESCRIPTION, description);
+    }
+    if (projectPattern != null) {
+      request.setParam(PARAM_TEMPLATE_PATTERN, projectPattern);
+    }
+
+    return request.execute();
+  }
+}
index 62ec8fa0ec52ea9b30a6d6d63324bd3806894e40..fe1c69d13678bd0842648e8f5798f5250e9a3735 100644 (file)
@@ -30,6 +30,6 @@ public class PermissionsWsModuleTest {
   public void verify_count_of_added_components() {
     ComponentContainer container = new ComponentContainer();
     new PermissionsWsModule().configure(container);
-    assertThat(container.size()).isEqualTo(18);
+    assertThat(container.size()).isEqualTo(19);
   }
 }
index dee4ad3cb1634c1ed72eb418ddac9ce012fe2fcc..5ac574c8752be06d60549da2fd99a3f773f282b5 100644 (file)
@@ -218,7 +218,7 @@ public class RemoveGroupFromTemplateActionTest {
   }
 
   private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insertPermissionTemplate(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
+    return dbClient.permissionTemplateDao().insert(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
   }
 
   private void addGroupToPermissionTemplate(long permissionTemplateId, @Nullable Long groupId, String permission) {
index 93bb60e77af293e8536edb4914e936c54d3cf99e..aa18125597729137e852ea851207eb383e0c97ea 100644 (file)
@@ -210,7 +210,7 @@ public class RemoveUserFromTemplateActionTest {
   }
 
   private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
-    return dbClient.permissionTemplateDao().insertPermissionTemplate(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
+    return dbClient.permissionTemplateDao().insert(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
   }
 
   private List<String> getLoginsInTemplateAndPermission(long templateId, String permission) {
index be4a46205c9d872510276595c18fea03deb6bba9..5637d9c0c6e8a4b215dd21f8fe12f34398f94739 100644 (file)
@@ -79,7 +79,7 @@ public class RegisterPermissionTemplatesTest {
 
     when(loadedTemplateDao.countByTypeAndKey(LoadedTemplateDto.PERMISSION_TEMPLATE_TYPE, PermissionTemplateDto.DEFAULT.getKee()))
       .thenReturn(0);
-    when(permissionTemplateDao.insertPermissionTemplate(PermissionTemplateDto.DEFAULT.getName(), PermissionTemplateDto.DEFAULT.getDescription(), null))
+    when(permissionTemplateDao.insert(PermissionTemplateDto.DEFAULT.getName(), PermissionTemplateDto.DEFAULT.getDescription(), null))
       .thenReturn(permissionTemplate);
     when(groupDao.selectByName(any(DbSession.class), eq(DefaultGroups.ADMINISTRATORS))).thenReturn(new GroupDto().setId(1L));
     when(groupDao.selectByName(any(DbSession.class), eq(DefaultGroups.USERS))).thenReturn(new GroupDto().setId(2L));
@@ -88,7 +88,7 @@ public class RegisterPermissionTemplatesTest {
     initializer.start();
 
     verify(loadedTemplateDao).insert(argThat(Matches.template(expectedTemplate)));
-    verify(permissionTemplateDao).insertPermissionTemplate(PermissionTemplateDto.DEFAULT.getName(), PermissionTemplateDto.DEFAULT.getDescription(), null);
+    verify(permissionTemplateDao).insert(PermissionTemplateDto.DEFAULT.getName(), PermissionTemplateDto.DEFAULT.getDescription(), null);
     verify(permissionTemplateDao).insertGroupPermission(1L, 1L, UserRole.ADMIN);
     verify(permissionTemplateDao).insertGroupPermission(1L, 1L, UserRole.ISSUE_ADMIN);
     verify(permissionTemplateDao).insertGroupPermission(1L, null, UserRole.USER);
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/CreateTemplateActionTest/create_template.json b/server/sonar-server/src/test/resources/org/sonar/server/permission/ws/CreateTemplateActionTest/create_template.json
new file mode 100644 (file)
index 0000000..064d02f
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "permissionTemplate": {
+    "name": "Finance",
+    "description": "Permissions for financially related projects",
+    "createdAt": "2015-08-25T16:18:48+0200",
+    "updatedAt": "2015-08-25T16:18:48+0200"
+  }
+}
index e7a3941ab8194de2c350d4be7c427d438084c44d..23164c14160b4e5d9657841e762e82c47567855d 100644 (file)
 package org.sonar.db.permission;
 
 import com.google.common.annotations.VisibleForTesting;
-import java.text.Normalizer;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.apache.commons.lang.time.DateFormatUtils;
 import org.apache.ibatis.session.RowBounds;
 import org.apache.ibatis.session.SqlSession;
 import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.Uuids;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
 import org.sonar.db.MyBatis;
@@ -181,22 +180,33 @@ public class PermissionTemplateDao implements Dao {
     }
   }
 
-  public PermissionTemplateDto insertPermissionTemplate(String templateName, @Nullable String description, @Nullable String keyPattern) {
+  /**
+   * @deprecated since 5.2 use {@link #insert(DbSession, PermissionTemplateDto)}
+   */
+  @Deprecated
+  public PermissionTemplateDto insert(String templateName, @Nullable String description, @Nullable String projectPattern) {
     Date creationDate = now();
+
     PermissionTemplateDto permissionTemplate = new PermissionTemplateDto()
       .setName(templateName)
-      .setKee(generateTemplateKee(templateName, creationDate))
+      .setKee(generateTemplateKey(templateName))
       .setDescription(description)
-      .setKeyPattern(keyPattern)
+      .setKeyPattern(projectPattern)
       .setCreatedAt(creationDate)
       .setUpdatedAt(creationDate);
-    SqlSession session = myBatis.openSession(false);
+
+    DbSession session = myBatis.openSession(false);
     try {
-      mapper(session).insert(permissionTemplate);
-      session.commit();
+      return insert(session, permissionTemplate);
     } finally {
       MyBatis.closeQuietly(session);
     }
+  }
+
+  public PermissionTemplateDto insert(DbSession session, PermissionTemplateDto permissionTemplate) {
+    mapper(session).insert(permissionTemplate);
+    session.commit();
+
     return permissionTemplate;
   }
 
@@ -213,22 +223,31 @@ public class PermissionTemplateDao implements Dao {
     }
   }
 
-  public void updatePermissionTemplate(Long templateId, String templateName, @Nullable String description, @Nullable String keyPattern) {
+  /**
+   * @deprecated since 5.2 use {@link #update(DbSession, PermissionTemplateDto)}
+   */
+  @Deprecated
+  public void update(Long templateId, String templateName, @Nullable String description, @Nullable String projectPattern) {
     PermissionTemplateDto permissionTemplate = new PermissionTemplateDto()
       .setId(templateId)
       .setName(templateName)
       .setDescription(description)
-      .setKeyPattern(keyPattern)
+      .setKeyPattern(projectPattern)
       .setUpdatedAt(now());
-    SqlSession session = myBatis.openSession(false);
+
+    DbSession session = myBatis.openSession(false);
     try {
-      mapper(session).update(permissionTemplate);
-      session.commit();
+      update(session, permissionTemplate);
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
+  public void update(DbSession session, PermissionTemplateDto permissionTemplate) {
+    mapper(session).update(permissionTemplate);
+    session.commit();
+  }
+
   /**
    * @deprecated since 5.2 {@link #insertUserPermission(DbSession, Long, Long, String)}
    */
@@ -334,6 +353,11 @@ public class PermissionTemplateDao implements Dao {
     return templateWithPermissions;
   }
 
+  public PermissionTemplateDto selectByName(DbSession dbSession, String templateName) {
+    char wildcard = '%';
+    return mapper(dbSession).selectByName(wildcard + templateName.toUpperCase() + wildcard);
+  }
+
   /**
    * Remove a group from all templates (used when removing a group)
    */
@@ -341,12 +365,12 @@ public class PermissionTemplateDao implements Dao {
     session.getMapper(PermissionTemplateMapper.class).deleteByGroupId(groupId);
   }
 
-  private String generateTemplateKee(String name, Date timeStamp) {
+  private String generateTemplateKey(String name) {
     if (PermissionTemplateDto.DEFAULT.getName().equals(name)) {
       return PermissionTemplateDto.DEFAULT.getKee();
     }
-    String normalizedName = Normalizer.normalize(name, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "").replace(" ", "_");
-    return normalizedName.toLowerCase() + "_" + DateFormatUtils.format(timeStamp, "yyyyMMdd_HHmmss");
+
+    return Uuids.create();
   }
 
   private Date now() {
index bd3aaeb3afa9a329dee4cde876b4dd2a9663fef8..49ac13fdb1296abcb204885e7e50eb8852fac3db 100644 (file)
@@ -59,6 +59,8 @@ public interface PermissionTemplateMapper {
 
   List<UserWithPermissionDto> selectUsers(Map<String, Object> params, RowBounds rowBounds);
 
+  PermissionTemplateDto selectByName(String name);
+
   int countUsers(Map<String, Object> params);
 
   int countGroups(Map<String, Object> parameters);
index ce3496d303f80f4e274cc65d01d074d0d0e18c5d..4ab1ae42006365cdd36a4243054f22b7f1683853 100644 (file)
     </where>
   </select>
 
+  <sql id="templateColumns">
+    id, name, kee, description, key_pattern AS keyPattern, created_at AS createdAt, updated_at AS updatedAt
+  </sql>
+
   <select id="selectByKey" parameterType="String" resultType="PermissionTemplate">
-    SELECT id, name, kee, description, key_pattern AS keyPattern, created_at AS createdAt, updated_at AS updatedAt
+    SELECT
+    <include refid="templateColumns"/>
     FROM permission_templates
     WHERE kee = #{kee}
   </select>
 
   <select id="selectAllPermissionTemplates" resultType="PermissionTemplate">
-    SELECT id, name, kee, description, key_pattern AS keyPattern, created_at AS createdAt, updated_at AS updatedAt
+    SELECT
+    <include refid="templateColumns"/>
+    FROM permission_templates
+  </select>
+
+  <select id="selectByName" parameterType="String" resultType="PermissionTemplate">
+    SELECT
+    <include refid="templateColumns"/>
     FROM permission_templates
+    WHERE UPPER(name) LIKE #{templateName} ESCAPE '/'
   </select>
 
   <select id="selectTemplateUsersPermissions" parameterType="String" resultMap="fullPermissionsTemplateResult">
index 2a39dd98ed0b5e78a02a20a13a7fe9f189fbdd64..0a301480170ce7748f9aefcb363b744a95fa2249 100644 (file)
@@ -58,25 +58,11 @@ public class PermissionTemplateDaoTest {
     Date now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2013-01-02 01:04:05");
     when(system.now()).thenReturn(now.getTime());
 
-    PermissionTemplateDto permissionTemplate = underTest.insertPermissionTemplate("my template", "my description", "myregexp");
+    PermissionTemplateDto permissionTemplate = underTest.insert("my template", "my description", "myregexp");
     assertThat(permissionTemplate).isNotNull();
     assertThat(permissionTemplate.getId()).isEqualTo(1L);
 
-    dbTester.assertDbUnitTable(getClass(), "createPermissionTemplate-result.xml", "permission_templates", "id", "name", "kee", "description");
-  }
-
-  @Test
-  public void should_normalize_kee_on_template_creation() throws ParseException {
-    dbTester.prepareDbUnit(getClass(), "createNonAsciiPermissionTemplate.xml");
-
-    Date now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2013-01-02 01:04:05");
-    when(system.now()).thenReturn(now.getTime());
-
-    PermissionTemplateDto permissionTemplate = underTest.insertPermissionTemplate("Môü Gnô Gnèçàß", "my description", null);
-    assertThat(permissionTemplate).isNotNull();
-    assertThat(permissionTemplate.getId()).isEqualTo(1L);
-
-    dbTester.assertDbUnitTable(getClass(), "createNonAsciiPermissionTemplate-result.xml", "permission_templates", "id", "name", "kee", "description");
+    dbTester.assertDbUnitTable(getClass(), "createPermissionTemplate-result.xml", "permission_templates", "id", "name", "description");
   }
 
   @Test
@@ -92,7 +78,7 @@ public class PermissionTemplateDaoTest {
     when(myBatis.openSession(false)).thenReturn(session);
 
     underTest = new PermissionTemplateDao(myBatis, system);
-    PermissionTemplateDto permissionTemplate = underTest.insertPermissionTemplate(PermissionTemplateDto.DEFAULT.getName(), null, null);
+    PermissionTemplateDto permissionTemplate = underTest.insert(PermissionTemplateDto.DEFAULT.getName(), null, null);
 
     verify(mapper).insert(permissionTemplate);
     verify(session).commit();
@@ -164,7 +150,7 @@ public class PermissionTemplateDaoTest {
   public void should_update_permission_template() {
     dbTester.prepareDbUnit(getClass(), "updatePermissionTemplate.xml");
 
-    underTest.updatePermissionTemplate(1L, "new_name", "new_description", "new_regexp");
+    underTest.update(1L, "new_name", "new_description", "new_regexp");
 
     dbTester.assertDbUnitTable(getClass(), "updatePermissionTemplate-result.xml", "permission_templates", "id", "name", "kee", "description");
   }
index 412537ded1382e694bd61e28c9e90e083cc9e160..fc6db6de75c53b796de95b8d268130a3f293954e 100644 (file)
 package org.sonar.db.permission;
 
 import java.util.Date;
+import org.sonar.api.utils.internal.Uuids;
 
 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.apache.commons.lang.RandomStringUtils.randomAscii;
-import static org.apache.commons.lang.math.RandomUtils.nextLong;
 
 public class PermissionTemplateTesting {
   public static PermissionTemplateDto newPermissionTemplateDto() {
     return new PermissionTemplateDto()
       .setName(randomAlphanumeric(60))
       .setDescription(randomAscii(500))
-      .setCreatedAt(new Date(nextLong()))
-      .setUpdatedAt(new Date(nextLong()));
+      .setKee(Uuids.create())
+      .setCreatedAt(new Date())
+      .setUpdatedAt(new Date());
   }
 }
index b7770cc2929b44e070b2ed85926c570cc64a0ceb..6dbd19e54b2344d587683097358b95fa51d29acd 100644 (file)
@@ -7653,6 +7653,1775 @@ public final class Permissions {
     // @@protoc_insertion_point(class_scope:sonarqube.ws.permissions.SearchProjectPermissionsResponse)
   }
 
+  public interface PermissionTemplateOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:sonarqube.ws.permissions.PermissionTemplate)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional string key = 1;</code>
+     */
+    boolean hasKey();
+    /**
+     * <code>optional string key = 1;</code>
+     */
+    java.lang.String getKey();
+    /**
+     * <code>optional string key = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getKeyBytes();
+
+    /**
+     * <code>optional string name = 2;</code>
+     */
+    boolean hasName();
+    /**
+     * <code>optional string name = 2;</code>
+     */
+    java.lang.String getName();
+    /**
+     * <code>optional string name = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getNameBytes();
+
+    /**
+     * <code>optional string description = 3;</code>
+     */
+    boolean hasDescription();
+    /**
+     * <code>optional string description = 3;</code>
+     */
+    java.lang.String getDescription();
+    /**
+     * <code>optional string description = 3;</code>
+     */
+    com.google.protobuf.ByteString
+        getDescriptionBytes();
+
+    /**
+     * <code>optional string projectPattern = 4;</code>
+     */
+    boolean hasProjectPattern();
+    /**
+     * <code>optional string projectPattern = 4;</code>
+     */
+    java.lang.String getProjectPattern();
+    /**
+     * <code>optional string projectPattern = 4;</code>
+     */
+    com.google.protobuf.ByteString
+        getProjectPatternBytes();
+
+    /**
+     * <code>optional string createdAt = 5;</code>
+     */
+    boolean hasCreatedAt();
+    /**
+     * <code>optional string createdAt = 5;</code>
+     */
+    java.lang.String getCreatedAt();
+    /**
+     * <code>optional string createdAt = 5;</code>
+     */
+    com.google.protobuf.ByteString
+        getCreatedAtBytes();
+
+    /**
+     * <code>optional string updatedAt = 6;</code>
+     */
+    boolean hasUpdatedAt();
+    /**
+     * <code>optional string updatedAt = 6;</code>
+     */
+    java.lang.String getUpdatedAt();
+    /**
+     * <code>optional string updatedAt = 6;</code>
+     */
+    com.google.protobuf.ByteString
+        getUpdatedAtBytes();
+  }
+  /**
+   * Protobuf type {@code sonarqube.ws.permissions.PermissionTemplate}
+   */
+  public static final class PermissionTemplate extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:sonarqube.ws.permissions.PermissionTemplate)
+      PermissionTemplateOrBuilder {
+    // Use PermissionTemplate.newBuilder() to construct.
+    private PermissionTemplate(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private PermissionTemplate(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final PermissionTemplate defaultInstance;
+    public static PermissionTemplate getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public PermissionTemplate getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private PermissionTemplate(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000001;
+              key_ = bs;
+              break;
+            }
+            case 18: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000002;
+              name_ = bs;
+              break;
+            }
+            case 26: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000004;
+              description_ = bs;
+              break;
+            }
+            case 34: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000008;
+              projectPattern_ = bs;
+              break;
+            }
+            case 42: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000010;
+              createdAt_ = bs;
+              break;
+            }
+            case 50: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000020;
+              updatedAt_ = bs;
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_PermissionTemplate_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_PermissionTemplate_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonarqube.ws.Permissions.PermissionTemplate.class, org.sonarqube.ws.Permissions.PermissionTemplate.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<PermissionTemplate> PARSER =
+        new com.google.protobuf.AbstractParser<PermissionTemplate>() {
+      public PermissionTemplate parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new PermissionTemplate(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<PermissionTemplate> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int KEY_FIELD_NUMBER = 1;
+    private java.lang.Object key_;
+    /**
+     * <code>optional string key = 1;</code>
+     */
+    public boolean hasKey() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional string key = 1;</code>
+     */
+    public java.lang.String getKey() {
+      java.lang.Object ref = key_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          key_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string key = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getKeyBytes() {
+      java.lang.Object ref = key_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        key_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int NAME_FIELD_NUMBER = 2;
+    private java.lang.Object name_;
+    /**
+     * <code>optional string name = 2;</code>
+     */
+    public boolean hasName() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional string name = 2;</code>
+     */
+    public java.lang.String getName() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          name_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string name = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getNameBytes() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        name_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int DESCRIPTION_FIELD_NUMBER = 3;
+    private java.lang.Object description_;
+    /**
+     * <code>optional string description = 3;</code>
+     */
+    public boolean hasDescription() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional string description = 3;</code>
+     */
+    public java.lang.String getDescription() {
+      java.lang.Object ref = description_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          description_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string description = 3;</code>
+     */
+    public com.google.protobuf.ByteString
+        getDescriptionBytes() {
+      java.lang.Object ref = description_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        description_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int PROJECTPATTERN_FIELD_NUMBER = 4;
+    private java.lang.Object projectPattern_;
+    /**
+     * <code>optional string projectPattern = 4;</code>
+     */
+    public boolean hasProjectPattern() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional string projectPattern = 4;</code>
+     */
+    public java.lang.String getProjectPattern() {
+      java.lang.Object ref = projectPattern_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          projectPattern_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string projectPattern = 4;</code>
+     */
+    public com.google.protobuf.ByteString
+        getProjectPatternBytes() {
+      java.lang.Object ref = projectPattern_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        projectPattern_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int CREATEDAT_FIELD_NUMBER = 5;
+    private java.lang.Object createdAt_;
+    /**
+     * <code>optional string createdAt = 5;</code>
+     */
+    public boolean hasCreatedAt() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>optional string createdAt = 5;</code>
+     */
+    public java.lang.String getCreatedAt() {
+      java.lang.Object ref = createdAt_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          createdAt_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string createdAt = 5;</code>
+     */
+    public com.google.protobuf.ByteString
+        getCreatedAtBytes() {
+      java.lang.Object ref = createdAt_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        createdAt_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int UPDATEDAT_FIELD_NUMBER = 6;
+    private java.lang.Object updatedAt_;
+    /**
+     * <code>optional string updatedAt = 6;</code>
+     */
+    public boolean hasUpdatedAt() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional string updatedAt = 6;</code>
+     */
+    public java.lang.String getUpdatedAt() {
+      java.lang.Object ref = updatedAt_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          updatedAt_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string updatedAt = 6;</code>
+     */
+    public com.google.protobuf.ByteString
+        getUpdatedAtBytes() {
+      java.lang.Object ref = updatedAt_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        updatedAt_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      key_ = "";
+      name_ = "";
+      description_ = "";
+      projectPattern_ = "";
+      createdAt_ = "";
+      updatedAt_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getKeyBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getNameBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, getDescriptionBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, getProjectPatternBytes());
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeBytes(5, getCreatedAtBytes());
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeBytes(6, getUpdatedAtBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getKeyBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getNameBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, getDescriptionBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, getProjectPatternBytes());
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(5, getCreatedAtBytes());
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(6, getUpdatedAtBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.PermissionTemplate parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.sonarqube.ws.Permissions.PermissionTemplate prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.permissions.PermissionTemplate}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:sonarqube.ws.permissions.PermissionTemplate)
+        org.sonarqube.ws.Permissions.PermissionTemplateOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_PermissionTemplate_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_PermissionTemplate_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.Permissions.PermissionTemplate.class, org.sonarqube.ws.Permissions.PermissionTemplate.Builder.class);
+      }
+
+      // Construct using org.sonarqube.ws.Permissions.PermissionTemplate.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        key_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        name_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        description_ = "";
+        bitField0_ = (bitField0_ & ~0x00000004);
+        projectPattern_ = "";
+        bitField0_ = (bitField0_ & ~0x00000008);
+        createdAt_ = "";
+        bitField0_ = (bitField0_ & ~0x00000010);
+        updatedAt_ = "";
+        bitField0_ = (bitField0_ & ~0x00000020);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_PermissionTemplate_descriptor;
+      }
+
+      public org.sonarqube.ws.Permissions.PermissionTemplate getDefaultInstanceForType() {
+        return org.sonarqube.ws.Permissions.PermissionTemplate.getDefaultInstance();
+      }
+
+      public org.sonarqube.ws.Permissions.PermissionTemplate build() {
+        org.sonarqube.ws.Permissions.PermissionTemplate result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonarqube.ws.Permissions.PermissionTemplate buildPartial() {
+        org.sonarqube.ws.Permissions.PermissionTemplate result = new org.sonarqube.ws.Permissions.PermissionTemplate(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.key_ = key_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.name_ = name_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.description_ = description_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.projectPattern_ = projectPattern_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        result.createdAt_ = createdAt_;
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        result.updatedAt_ = updatedAt_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonarqube.ws.Permissions.PermissionTemplate) {
+          return mergeFrom((org.sonarqube.ws.Permissions.PermissionTemplate)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonarqube.ws.Permissions.PermissionTemplate other) {
+        if (other == org.sonarqube.ws.Permissions.PermissionTemplate.getDefaultInstance()) return this;
+        if (other.hasKey()) {
+          bitField0_ |= 0x00000001;
+          key_ = other.key_;
+          onChanged();
+        }
+        if (other.hasName()) {
+          bitField0_ |= 0x00000002;
+          name_ = other.name_;
+          onChanged();
+        }
+        if (other.hasDescription()) {
+          bitField0_ |= 0x00000004;
+          description_ = other.description_;
+          onChanged();
+        }
+        if (other.hasProjectPattern()) {
+          bitField0_ |= 0x00000008;
+          projectPattern_ = other.projectPattern_;
+          onChanged();
+        }
+        if (other.hasCreatedAt()) {
+          bitField0_ |= 0x00000010;
+          createdAt_ = other.createdAt_;
+          onChanged();
+        }
+        if (other.hasUpdatedAt()) {
+          bitField0_ |= 0x00000020;
+          updatedAt_ = other.updatedAt_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonarqube.ws.Permissions.PermissionTemplate parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonarqube.ws.Permissions.PermissionTemplate) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private java.lang.Object key_ = "";
+      /**
+       * <code>optional string key = 1;</code>
+       */
+      public boolean hasKey() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional string key = 1;</code>
+       */
+      public java.lang.String getKey() {
+        java.lang.Object ref = key_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            key_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string key = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getKeyBytes() {
+        java.lang.Object ref = key_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          key_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string key = 1;</code>
+       */
+      public Builder setKey(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        key_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string key = 1;</code>
+       */
+      public Builder clearKey() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        key_ = getDefaultInstance().getKey();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string key = 1;</code>
+       */
+      public Builder setKeyBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        key_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object name_ = "";
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public boolean hasName() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public java.lang.String getName() {
+        java.lang.Object ref = name_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            name_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getNameBytes() {
+        java.lang.Object ref = name_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          name_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public Builder setName(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        name_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public Builder clearName() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        name_ = getDefaultInstance().getName();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string name = 2;</code>
+       */
+      public Builder setNameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        name_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object description_ = "";
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public boolean hasDescription() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public java.lang.String getDescription() {
+        java.lang.Object ref = description_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            description_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public com.google.protobuf.ByteString
+          getDescriptionBytes() {
+        java.lang.Object ref = description_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          description_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public Builder setDescription(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        description_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public Builder clearDescription() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        description_ = getDefaultInstance().getDescription();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string description = 3;</code>
+       */
+      public Builder setDescriptionBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        description_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object projectPattern_ = "";
+      /**
+       * <code>optional string projectPattern = 4;</code>
+       */
+      public boolean hasProjectPattern() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional string projectPattern = 4;</code>
+       */
+      public java.lang.String getProjectPattern() {
+        java.lang.Object ref = projectPattern_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            projectPattern_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string projectPattern = 4;</code>
+       */
+      public com.google.protobuf.ByteString
+          getProjectPatternBytes() {
+        java.lang.Object ref = projectPattern_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          projectPattern_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string projectPattern = 4;</code>
+       */
+      public Builder setProjectPattern(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        projectPattern_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string projectPattern = 4;</code>
+       */
+      public Builder clearProjectPattern() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        projectPattern_ = getDefaultInstance().getProjectPattern();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string projectPattern = 4;</code>
+       */
+      public Builder setProjectPatternBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        projectPattern_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object createdAt_ = "";
+      /**
+       * <code>optional string createdAt = 5;</code>
+       */
+      public boolean hasCreatedAt() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>optional string createdAt = 5;</code>
+       */
+      public java.lang.String getCreatedAt() {
+        java.lang.Object ref = createdAt_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            createdAt_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string createdAt = 5;</code>
+       */
+      public com.google.protobuf.ByteString
+          getCreatedAtBytes() {
+        java.lang.Object ref = createdAt_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          createdAt_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string createdAt = 5;</code>
+       */
+      public Builder setCreatedAt(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000010;
+        createdAt_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string createdAt = 5;</code>
+       */
+      public Builder clearCreatedAt() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        createdAt_ = getDefaultInstance().getCreatedAt();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string createdAt = 5;</code>
+       */
+      public Builder setCreatedAtBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000010;
+        createdAt_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object updatedAt_ = "";
+      /**
+       * <code>optional string updatedAt = 6;</code>
+       */
+      public boolean hasUpdatedAt() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>optional string updatedAt = 6;</code>
+       */
+      public java.lang.String getUpdatedAt() {
+        java.lang.Object ref = updatedAt_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            updatedAt_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string updatedAt = 6;</code>
+       */
+      public com.google.protobuf.ByteString
+          getUpdatedAtBytes() {
+        java.lang.Object ref = updatedAt_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          updatedAt_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string updatedAt = 6;</code>
+       */
+      public Builder setUpdatedAt(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        updatedAt_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string updatedAt = 6;</code>
+       */
+      public Builder clearUpdatedAt() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        updatedAt_ = getDefaultInstance().getUpdatedAt();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string updatedAt = 6;</code>
+       */
+      public Builder setUpdatedAtBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        updatedAt_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:sonarqube.ws.permissions.PermissionTemplate)
+    }
+
+    static {
+      defaultInstance = new PermissionTemplate(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:sonarqube.ws.permissions.PermissionTemplate)
+  }
+
+  public interface CreatePermissionTemplateResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:sonarqube.ws.permissions.CreatePermissionTemplateResponse)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+     */
+    boolean hasPermissionTemplate();
+    /**
+     * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+     */
+    org.sonarqube.ws.Permissions.PermissionTemplate getPermissionTemplate();
+    /**
+     * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+     */
+    org.sonarqube.ws.Permissions.PermissionTemplateOrBuilder getPermissionTemplateOrBuilder();
+  }
+  /**
+   * Protobuf type {@code sonarqube.ws.permissions.CreatePermissionTemplateResponse}
+   */
+  public static final class CreatePermissionTemplateResponse extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:sonarqube.ws.permissions.CreatePermissionTemplateResponse)
+      CreatePermissionTemplateResponseOrBuilder {
+    // Use CreatePermissionTemplateResponse.newBuilder() to construct.
+    private CreatePermissionTemplateResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private CreatePermissionTemplateResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final CreatePermissionTemplateResponse defaultInstance;
+    public static CreatePermissionTemplateResponse getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public CreatePermissionTemplateResponse getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private CreatePermissionTemplateResponse(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              org.sonarqube.ws.Permissions.PermissionTemplate.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                subBuilder = permissionTemplate_.toBuilder();
+              }
+              permissionTemplate_ = input.readMessage(org.sonarqube.ws.Permissions.PermissionTemplate.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(permissionTemplate_);
+                permissionTemplate_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000001;
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse.class, org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<CreatePermissionTemplateResponse> PARSER =
+        new com.google.protobuf.AbstractParser<CreatePermissionTemplateResponse>() {
+      public CreatePermissionTemplateResponse parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new CreatePermissionTemplateResponse(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<CreatePermissionTemplateResponse> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int PERMISSIONTEMPLATE_FIELD_NUMBER = 1;
+    private org.sonarqube.ws.Permissions.PermissionTemplate permissionTemplate_;
+    /**
+     * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+     */
+    public boolean hasPermissionTemplate() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+     */
+    public org.sonarqube.ws.Permissions.PermissionTemplate getPermissionTemplate() {
+      return permissionTemplate_;
+    }
+    /**
+     * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+     */
+    public org.sonarqube.ws.Permissions.PermissionTemplateOrBuilder getPermissionTemplateOrBuilder() {
+      return permissionTemplate_;
+    }
+
+    private void initFields() {
+      permissionTemplate_ = org.sonarqube.ws.Permissions.PermissionTemplate.getDefaultInstance();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeMessage(1, permissionTemplate_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, permissionTemplate_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.permissions.CreatePermissionTemplateResponse}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:sonarqube.ws.permissions.CreatePermissionTemplateResponse)
+        org.sonarqube.ws.Permissions.CreatePermissionTemplateResponseOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse.class, org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse.Builder.class);
+      }
+
+      // Construct using org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getPermissionTemplateFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        if (permissionTemplateBuilder_ == null) {
+          permissionTemplate_ = org.sonarqube.ws.Permissions.PermissionTemplate.getDefaultInstance();
+        } else {
+          permissionTemplateBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonarqube.ws.Permissions.internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_descriptor;
+      }
+
+      public org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse getDefaultInstanceForType() {
+        return org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse.getDefaultInstance();
+      }
+
+      public org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse build() {
+        org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse buildPartial() {
+        org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse result = new org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        if (permissionTemplateBuilder_ == null) {
+          result.permissionTemplate_ = permissionTemplate_;
+        } else {
+          result.permissionTemplate_ = permissionTemplateBuilder_.build();
+        }
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse) {
+          return mergeFrom((org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse other) {
+        if (other == org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse.getDefaultInstance()) return this;
+        if (other.hasPermissionTemplate()) {
+          mergePermissionTemplate(other.getPermissionTemplate());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonarqube.ws.Permissions.CreatePermissionTemplateResponse) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private org.sonarqube.ws.Permissions.PermissionTemplate permissionTemplate_ = org.sonarqube.ws.Permissions.PermissionTemplate.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.sonarqube.ws.Permissions.PermissionTemplate, org.sonarqube.ws.Permissions.PermissionTemplate.Builder, org.sonarqube.ws.Permissions.PermissionTemplateOrBuilder> permissionTemplateBuilder_;
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public boolean hasPermissionTemplate() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.PermissionTemplate getPermissionTemplate() {
+        if (permissionTemplateBuilder_ == null) {
+          return permissionTemplate_;
+        } else {
+          return permissionTemplateBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public Builder setPermissionTemplate(org.sonarqube.ws.Permissions.PermissionTemplate value) {
+        if (permissionTemplateBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          permissionTemplate_ = value;
+          onChanged();
+        } else {
+          permissionTemplateBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public Builder setPermissionTemplate(
+          org.sonarqube.ws.Permissions.PermissionTemplate.Builder builderForValue) {
+        if (permissionTemplateBuilder_ == null) {
+          permissionTemplate_ = builderForValue.build();
+          onChanged();
+        } else {
+          permissionTemplateBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public Builder mergePermissionTemplate(org.sonarqube.ws.Permissions.PermissionTemplate value) {
+        if (permissionTemplateBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001) &&
+              permissionTemplate_ != org.sonarqube.ws.Permissions.PermissionTemplate.getDefaultInstance()) {
+            permissionTemplate_ =
+              org.sonarqube.ws.Permissions.PermissionTemplate.newBuilder(permissionTemplate_).mergeFrom(value).buildPartial();
+          } else {
+            permissionTemplate_ = value;
+          }
+          onChanged();
+        } else {
+          permissionTemplateBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public Builder clearPermissionTemplate() {
+        if (permissionTemplateBuilder_ == null) {
+          permissionTemplate_ = org.sonarqube.ws.Permissions.PermissionTemplate.getDefaultInstance();
+          onChanged();
+        } else {
+          permissionTemplateBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.PermissionTemplate.Builder getPermissionTemplateBuilder() {
+        bitField0_ |= 0x00000001;
+        onChanged();
+        return getPermissionTemplateFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      public org.sonarqube.ws.Permissions.PermissionTemplateOrBuilder getPermissionTemplateOrBuilder() {
+        if (permissionTemplateBuilder_ != null) {
+          return permissionTemplateBuilder_.getMessageOrBuilder();
+        } else {
+          return permissionTemplate_;
+        }
+      }
+      /**
+       * <code>optional .sonarqube.ws.permissions.PermissionTemplate permissionTemplate = 1;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.sonarqube.ws.Permissions.PermissionTemplate, org.sonarqube.ws.Permissions.PermissionTemplate.Builder, org.sonarqube.ws.Permissions.PermissionTemplateOrBuilder> 
+          getPermissionTemplateFieldBuilder() {
+        if (permissionTemplateBuilder_ == null) {
+          permissionTemplateBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.sonarqube.ws.Permissions.PermissionTemplate, org.sonarqube.ws.Permissions.PermissionTemplate.Builder, org.sonarqube.ws.Permissions.PermissionTemplateOrBuilder>(
+                  getPermissionTemplate(),
+                  getParentForChildren(),
+                  isClean());
+          permissionTemplate_ = null;
+        }
+        return permissionTemplateBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:sonarqube.ws.permissions.CreatePermissionTemplateResponse)
+    }
+
+    static {
+      defaultInstance = new CreatePermissionTemplateResponse(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:sonarqube.ws.permissions.CreatePermissionTemplateResponse)
+  }
+
   private static final com.google.protobuf.Descriptors.Descriptor
     internal_static_sonarqube_ws_permissions_UsersResponse_descriptor;
   private static
@@ -7693,6 +9462,16 @@ public final class Permissions {
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_sonarqube_ws_permissions_SearchProjectPermissionsResponse_Project_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_permissions_PermissionTemplate_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_permissions_PermissionTemplate_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_fieldAccessorTable;
 
   public static com.google.protobuf.Descriptors.FileDescriptor
       getDescriptor() {
@@ -7727,8 +9506,14 @@ public final class Permissions {
       "ns.Paging\032\200\001\n\007Project\022\014\n\004uuid\030\001 \001(\t\022\013\n\003k" +
       "ey\030\002 \001(\t\022\021\n\tqualifier\030\003 \001(\t\022\014\n\004name\030\004 \001(" +
       "\t\0229\n\013permissions\030\005 \003(\0132$.sonarqube.ws.pe" +
-      "rmissions.PermissionB!\n\020org.sonarqube.ws" +
-      "B\013PermissionsH\001"
+      "rmissions.Permission\"\202\001\n\022PermissionTempl" +
+      "ate\022\013\n\003key\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\023\n\013descri" +
+      "ption\030\003 \001(\t\022\026\n\016projectPattern\030\004 \001(\t\022\021\n\tc" +
+      "reatedAt\030\005 \001(\t\022\021\n\tupdatedAt\030\006 \001(\t\"l\n Cre" +
+      "atePermissionTemplateResponse\022H\n\022permiss",
+      "ionTemplate\030\001 \001(\0132,.sonarqube.ws.permiss" +
+      "ions.PermissionTemplateB!\n\020org.sonarqube" +
+      ".wsB\013PermissionsH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
         new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
@@ -7791,6 +9576,18 @@ public final class Permissions {
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_sonarqube_ws_permissions_SearchProjectPermissionsResponse_Project_descriptor,
         new java.lang.String[] { "Uuid", "Key", "Qualifier", "Name", "Permissions", });
+    internal_static_sonarqube_ws_permissions_PermissionTemplate_descriptor =
+      getDescriptor().getMessageTypes().get(5);
+    internal_static_sonarqube_ws_permissions_PermissionTemplate_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_permissions_PermissionTemplate_descriptor,
+        new java.lang.String[] { "Key", "Name", "Description", "ProjectPattern", "CreatedAt", "UpdatedAt", });
+    internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_descriptor =
+      getDescriptor().getMessageTypes().get(6);
+    internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_permissions_CreatePermissionTemplateResponse_descriptor,
+        new java.lang.String[] { "PermissionTemplate", });
     org.sonarqube.ws.Common.getDescriptor();
   }
 
index 90a1559231b5e4c70238205e6ee7217f46c869d5..411c8473ad9272a32f28b77bbec83bc80b709d37 100644 (file)
@@ -81,3 +81,18 @@ message SearchProjectPermissionsResponse {
   repeated Permission permissions = 2;
   optional sonarqube.ws.commons.Paging paging = 3;
 }
+
+message PermissionTemplate {
+  optional string key = 1;
+  optional string name = 2;
+  optional string description = 3;
+  optional string projectPattern = 4;
+  // ex: 2015-08-25T16:18:48+0200
+  optional string createdAt = 5;
+  // ex: 2015-08-25T16:18:48+0200
+  optional string updatedAt = 6;
+}
+
+message CreatePermissionTemplateResponse {
+  optional PermissionTemplate permissionTemplate = 1;
+}