diff --git a/CHANGELOG.md b/CHANGELOG.md index 3733f78776..8efc0f1595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Lookup command which provides further repository information ([#1415](https://github.com/scm-manager/scm-manager/pull/1415)) - Include messages from scm protocol in modification or merge errors ([#1420](https://github.com/scm-manager/scm-manager/pull/1420)) - Enhance trace api to accepted status codes ([#1430](https://github.com/scm-manager/scm-manager/pull/1430)) +- Add examples to core resources to simplify usage of rest api ([#1434](https://github.com/scm-manager/scm-manager/pull/1434)) ### Changed - Send mercurial hook callbacks over separate tcp socket instead of http ([#1416](https://github.com/scm-manager/scm-manager/pull/1416)) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigDto.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigDto.java index 893de773da..99ac469166 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigDto.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigDto.java @@ -39,7 +39,7 @@ import static sonia.scm.repository.Branch.VALID_BRANCH_NAMES; @NoArgsConstructor @Getter @Setter -public class GitConfigDto extends HalRepresentation { +public class GitConfigDto extends HalRepresentation implements UpdateGitConfigDto { private boolean disabled = false; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java index 71d97f27be..e366a35abb 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java @@ -27,7 +27,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import sonia.scm.config.ConfigurationPermissions; @@ -116,7 +118,23 @@ public class GitConfigResource { @PUT @Path("") @Consumes(GitVndMediaType.GIT_CONFIG) - @Operation(summary = "Modify git configuration", description = "Modifies the global git configuration.", tags = "Git", operationId = "git_put_config") + @Operation( + summary = "Modify git configuration", + description = "Modifies the global git configuration.", + tags = "Git", + operationId = "git_put_config", + requestBody = @RequestBody( + content = @Content( + mediaType = GitVndMediaType.GIT_CONFIG, + schema = @Schema(implementation = UpdateGitConfigDto.class), + examples = @ExampleObject( + name = "Overwrites current configuration with this one.", + value = "{\n \"disabled\":false,\n \"gcExpression\":null,\n \"nonFastForwardDisallowed\":false,\n \"defaultBranch\":\"main\"\n}", + summary = "Simple update configuration" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"configuration:write:git\" privilege") diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigDto.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigDto.java index 92a495669b..46eb671d5c 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigDto.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigDto.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import de.otto.edison.hal.HalRepresentation; @@ -36,7 +36,7 @@ import lombok.Setter; @AllArgsConstructor @NoArgsConstructor @SuppressWarnings("squid:S2160") // there is no proper semantic for equals on this dto -public class GitRepositoryConfigDto extends HalRepresentation { +public class GitRepositoryConfigDto extends HalRepresentation implements UpdateGitRepositoryConfigDto { private String defaultBranch; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigResource.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigResource.java index 3aa348d13a..559dfddae8 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigResource.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigResource.java @@ -21,13 +21,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; +import lombok.Getter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.repository.GitRepositoryConfig; @@ -106,7 +109,22 @@ public class GitRepositoryConfigResource { @PUT @Path("/") @Consumes(GitVndMediaType.GIT_REPOSITORY_CONFIG) - @Operation(summary = "Modifies git repository configuration", description = "Modifies the repository related git configuration.", tags = "Git") + @Operation( + summary = "Modifies git repository configuration", + description = "Modifies the repository related git configuration.", + tags = "Git", + requestBody = @RequestBody( + content = @Content( + mediaType = GitVndMediaType.GIT_REPOSITORY_CONFIG, + schema = @Schema(implementation = UpdateGitRepositoryConfigDto.class), + examples = @ExampleObject( + name = "Overwrites current configuration with this one.", + value = "{\n \"defaultBranch\":\"main\"\n}", + summary = "Simple update configuration" + ) + ) + ) + ) @ApiResponse( responseCode = "204", description = "update success" diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateGitConfigDto.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateGitConfigDto.java new file mode 100644 index 0000000000..66bdcd7278 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateGitConfigDto.java @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +import static sonia.scm.repository.Branch.VALID_BRANCH_NAMES; + +interface UpdateGitConfigDto { + + boolean isDisabled(); + + String getGcExpression(); + + boolean isNonFastForwardDisallowed(); + + @NotEmpty + @Length(min = 1, max = 100) + @Pattern(regexp = VALID_BRANCH_NAMES) + String getDefaultBranch(); +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateGitRepositoryConfigDto.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateGitRepositoryConfigDto.java new file mode 100644 index 0000000000..0da843e1af --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateGitRepositoryConfigDto.java @@ -0,0 +1,29 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +interface UpdateGitRepositoryConfigDto { + String getDefaultBranch(); +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResource.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResource.java index 2d8c385128..70eb367d3c 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResource.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResource.java @@ -27,7 +27,9 @@ package sonia.scm.api.v2.resources; import com.google.inject.Inject; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.config.ConfigurationPermissions; import sonia.scm.repository.HgConfig; @@ -83,7 +85,22 @@ public class HgConfigAutoConfigurationResource { @PUT @Path("") @Consumes(HgVndMediaType.CONFIG) - @Operation(summary = "Modifies hg configuration and installs hg binary", description = "Modifies the mercurial config and installs the mercurial binary.", tags = "Mercurial") + @Operation( + summary = "Modifies hg configuration and installs hg binary", + description = "Modifies the mercurial config and installs the mercurial binary.", + tags = "Mercurial", + requestBody = @RequestBody( + content = @Content( + mediaType = HgVndMediaType.CONFIG, + schema = @Schema(implementation = UpdateHgConfigDto.class), + examples = @ExampleObject( + name = "Overwrites current configuration with this one and installs the mercurial binary.", + value = "{\n \"disabled\":false,\n \"hgBinary\":\"hg\",\n \"pythonBinary\":\"python\",\n \"pythonPath\":\"\",\n \"encoding\":\"UTF-8\",\n \"useOptimizedBytecode\":false,\n \"showRevisionInId\":false,\n \"disableHookSSLValidation\":false,\n \"enableHttpPostArgs\":false\n}", + summary = "Simple update configuration and installs binary" + ) + ) + ) + ) @ApiResponse( responseCode = "204", description = "update success" diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigDto.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigDto.java index 464e896767..3ddb33052f 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigDto.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigDto.java @@ -34,7 +34,8 @@ import lombok.Setter; @Setter @NoArgsConstructor @SuppressWarnings("java:S2160") // we don't need equals for dto -public class HgConfigDto extends HalRepresentation { +public class HgConfigDto extends HalRepresentation implements UpdateHgConfigDto { + private boolean disabled; diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigResource.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigResource.java index cb2ac532ab..0c715ce8c3 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigResource.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigResource.java @@ -27,7 +27,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import sonia.scm.config.ConfigurationPermissions; @@ -121,7 +123,23 @@ public class HgConfigResource { @PUT @Path("") @Consumes(HgVndMediaType.CONFIG) - @Operation(summary = "Modify hg configuration", description = "Modifies the global mercurial configuration.", tags = "Mercurial", operationId = "hg_put_config") + @Operation( + summary = "Modify hg configuration", + description = "Modifies the global mercurial configuration.", + tags = "Mercurial", + operationId = "hg_put_config", + requestBody = @RequestBody( + content = @Content( + mediaType = HgVndMediaType.CONFIG, + schema = @Schema(implementation = UpdateHgConfigDto.class), + examples = @ExampleObject( + name = "Overwrites current configuration with this one.", + value = "{\n \"disabled\":false,\n \"hgBinary\":\"hg\",\n \"pythonBinary\":\"python\",\n \"pythonPath\":\"\",\n \"encoding\":\"UTF-8\",\n \"useOptimizedBytecode\":false,\n \"showRevisionInId\":false,\n \"disableHookSSLValidation\":false,\n \"enableHttpPostArgs\":false\n}", + summary = "Simple update configuration" + ) + ) + ) + ) @ApiResponse( responseCode = "204", description = "update success" diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateHgConfigDto.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateHgConfigDto.java new file mode 100644 index 0000000000..743cd2cfaf --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateHgConfigDto.java @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +interface UpdateHgConfigDto { + boolean isDisabled(); + + String getHgBinary(); + + String getPythonBinary(); + + String getPythonPath(); + + String getEncoding(); + + boolean isUseOptimizedBytecode(); + + boolean isShowRevisionInId(); + + boolean isDisableHookSSLValidation(); + + boolean isEnableHttpPostArgs(); +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java index 72f7513bb8..9be64e6a3b 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import de.otto.edison.hal.HalRepresentation; @@ -34,7 +34,7 @@ import sonia.scm.repository.Compatibility; @NoArgsConstructor @Getter @Setter -public class SvnConfigDto extends HalRepresentation { +public class SvnConfigDto extends HalRepresentation implements UpdateSvnConfigDto { private boolean disabled; diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java index 3e45bb6c43..394000c48a 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java @@ -21,13 +21,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import sonia.scm.config.ConfigurationPermissions; @@ -112,7 +114,23 @@ public class SvnConfigResource { @PUT @Path("") @Consumes(SvnVndMediaType.SVN_CONFIG) - @Operation(summary = "Modify svn configuration", description = "Modifies the global subversion configuration.", tags = "Subversion", operationId = "svn_put_config") + @Operation( + summary = "Modify svn configuration", + description = "Modifies the global subversion configuration.", + tags = "Subversion", + operationId = "svn_put_config", + requestBody = @RequestBody( + content = @Content( + mediaType = SvnVndMediaType.SVN_CONFIG, + schema = @Schema(implementation = UpdateSvnConfigDto.class), + examples = @ExampleObject( + name = "Overwrites current configuration with this one.", + value = "{\n \"disabled\":false,\n \"compatibility\":\"NONE\",\n \"enabledGZip\":false\n}", + summary = "Simple update configuration" + ) + ) + ) + ) @ApiResponse( responseCode = "204", description = "update success" diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateSvnConfigDto.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateSvnConfigDto.java new file mode 100644 index 0000000000..87de7d5ec8 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/UpdateSvnConfigDto.java @@ -0,0 +1,36 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import sonia.scm.repository.Compatibility; + +interface UpdateSvnConfigDto { + + boolean isDisabled(); + + Compatibility getCompatibility(); + + boolean isEnabledGZip(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyDto.java index b07e329a8a..40cc0feaa0 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyDto.java @@ -36,7 +36,7 @@ import java.time.Instant; @Getter @Setter @NoArgsConstructor -public class ApiKeyDto extends HalRepresentation { +public class ApiKeyDto extends HalRepresentation implements CreateApiKeyDto { @NotEmpty private String displayName; @NotEmpty diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyResource.java index e2faac3e37..04dd186b2a 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ApiKeyResource.java @@ -28,7 +28,9 @@ import de.otto.edison.hal.HalRepresentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.ContextEntry; import sonia.scm.security.ApiKey; @@ -131,7 +133,22 @@ public class ApiKeyResource { @Path("") @Consumes(VndMediaType.API_KEY) @Produces(MediaType.TEXT_PLAIN) - @Operation(summary = "Create new api key for the current user", description = "Creates a new api key for the given user with the role specified in the given key.", tags = "User") + @Operation( + summary = "Create new api key for the current user", + description = "Creates a new api key for the given user with the role specified in the given key.", + tags = "User", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.API_KEY, + schema = @Schema(implementation = CreateApiKeyDto.class), + examples = @ExampleObject( + name = "Create a new api key named readKey with READ permission role.", + value = "{\n \"displayName\":\"readKey\",\n \"permissionRole\":\"READ\"\n}", + summary = "Create new api key" + ) + ) + ) + ) @ApiResponse( responseCode = "201", description = "create success", @@ -170,4 +187,5 @@ public class ApiKeyResource { public void delete(@PathParam("id") String id) { apiKeyService.remove(id); } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java index a5ce4d951e..258dd1e3e5 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchRootResource.java @@ -28,7 +28,9 @@ import com.google.common.base.Strings; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.PageResult; import sonia.scm.repository.Branch; @@ -209,7 +211,22 @@ public class BranchRootResource { @POST @Path("") @Consumes(VndMediaType.BRANCH_REQUEST) - @Operation(summary = "Create branch", description = "Creates a new branch.", tags = "Repository") + @Operation( + summary = "Create branch", + description = "Creates a new branch.", + tags = "Repository", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.BRANCH_REQUEST, + schema = @Schema(implementation = BranchRequestDto.class), + examples = @ExampleObject( + name = "Branch a new develop branch from main.", + value = "{\n \"parent\":\"main\",\n \"name\":\"develop\"\n}", + summary = "Create a branch" + ) + ) + ) + ) @ApiResponse( responseCode = "201", description = "create success", diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java index 2b7249c7e7..48b90c9175 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java @@ -36,7 +36,7 @@ import java.util.Set; @NoArgsConstructor @Getter @Setter -public class ConfigDto extends HalRepresentation { +public class ConfigDto extends HalRepresentation implements UpdateConfigDto { private String proxyPassword; private int proxyPort; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java index 5575af06fb..13dec7d44e 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java @@ -27,9 +27,10 @@ package sonia.scm.api.v2.resources; import com.google.common.annotations.VisibleForTesting; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import sonia.scm.config.ConfigurationPermissions; @@ -122,7 +123,22 @@ public class ConfigResource { @PUT @Path("") @Consumes(VndMediaType.CONFIG) - @Operation(summary = "Update instance configuration", description = "Modifies the instance configuration.", tags = "Instance configuration") + @Operation( + summary = "Update instance configuration", + description = "Modifies the instance configuration.", + tags = "Instance configuration", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.CONFIG, + schema = @Schema(implementation = UpdateConfigDto.class), + examples = @ExampleObject( + name = "Overwrites current configuration with this one.", + value = "{\n \"realmDescription\":\"SONIA :: SCM-Manager\",\n \"dateFormat\":\"YYYY-MM-DD HH:mm:ss\",\n \"baseUrl\":\"http://localhost:8081/scm\",\n \"loginAttemptLimit\":-1,\n \"pluginUrl\":\"https://plugin-center-api.scm-manager.org/api/v1/plugins/{version}?os={os}&arch={arch}\",\n \"loginAttemptLimitTimeout\":500,\n \"namespaceStrategy\":\"CustomNamespaceStrategy\",\n \"loginInfoUrl\":\"https://login-info.scm-manager.org/api/v1/login-info\",\n \"releaseFeedUrl\":\"https://scm-manager.org/download/rss.xml\",\n \"mailDomainName\":\"scm-manager.local\"\n}", + summary = "Simple update configuration" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"configuration:write\" privilege") @@ -151,4 +167,5 @@ public class ConfigResource { return Response.noContent().build(); } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateApiKeyDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateApiKeyDto.java new file mode 100644 index 0000000000..cd7588ffb1 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateApiKeyDto.java @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import javax.validation.constraints.NotEmpty; + +interface CreateApiKeyDto { + @NotEmpty + String getDisplayName(); + + @NotEmpty + String getPermissionRole(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateGroupDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateGroupDto.java index bc1324e0f1..82ed359010 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateGroupDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateGroupDto.java @@ -24,26 +24,19 @@ package sonia.scm.api.v2.resources; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; import sonia.scm.util.ValidationUtil; import javax.validation.constraints.Pattern; import java.util.List; -/** - * This class is currently only used in the openapi scheme - */ -@Getter -@Setter -@NoArgsConstructor -public class CreateGroupDto { +interface CreateGroupDto { @Pattern(regexp = ValidationUtil.REGEX_NAME) - private String name; - private String description; - private String type; - private List members; - private boolean external; + String getName(); + + String getDescription(); + + List getMembers(); + + boolean isExternal(); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateRepositoryDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateRepositoryDto.java new file mode 100644 index 0000000000..29d41bc075 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateRepositoryDto.java @@ -0,0 +1,53 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import sonia.scm.util.ValidationUtil; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; +import java.time.Instant; +import java.util.List; + +interface CreateRepositoryDto { + + String getNamespace(); + + @Pattern(regexp = ValidationUtil.REGEX_REPOSITORYNAME) + String getName(); + + @NotEmpty + String getType(); + + @Email + String getContact(); + + String getDescription(); + + List getHealthCheckFailures(); + + Instant getLastModified(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateRepositoryRoleDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateRepositoryRoleDto.java new file mode 100644 index 0000000000..0f524d39f2 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateRepositoryRoleDto.java @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import javax.validation.constraints.NotEmpty; +import java.util.Collection; + +interface CreateRepositoryRoleDto { + + @NotEmpty + String getName(); + + @NoBlankStrings + @NotEmpty + Collection getVerbs(); + + String getType(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateUserDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateUserDto.java new file mode 100644 index 0000000000..ff0b36b404 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CreateUserDto.java @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import sonia.scm.util.ValidationUtil; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +interface CreateUserDto { + @Pattern(regexp = ValidationUtil.REGEX_NAME) + String getName(); + + @NotEmpty + String getDisplayName(); + + @Email + String getMail(); + + boolean isExternal(); + + String getPassword(); + + boolean isActive(); + + String getType(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupDto.java index 24939609b3..8881470216 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupDto.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import com.fasterxml.jackson.annotation.JsonInclude; @@ -40,7 +40,7 @@ import java.util.List; @Getter @Setter @NoArgsConstructor -public class GroupDto extends HalRepresentation { +public class GroupDto extends HalRepresentation implements UpdateGroupDto, CreateGroupDto { private Instant creationDate; private String description; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupResource.java index f3fea99bff..00a41d7526 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/GroupResource.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; @@ -181,4 +181,5 @@ public class GroupResource { public GroupPermissionResource permissions() { return groupPermissionResource; } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MeResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MeResource.java index d93acf0159..1aad2f3d34 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MeResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/MeResource.java @@ -27,7 +27,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import org.apache.shiro.authc.credential.PasswordService; @@ -105,7 +107,22 @@ public class MeResource { @PUT @Path("password") @Consumes(VndMediaType.PASSWORD_CHANGE) - @Operation(summary = "Change password", description = "Change password of the current user.", tags = "Current user") + @Operation( + summary = "Change password", + description = "Change password of the current user.", + tags = "Current user", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.PASSWORD_CHANGE, + schema = @Schema(implementation = PasswordChangeDto.class), + examples = @ExampleObject( + name = "Change password to a more difficult one.", + value = "{ \"oldPassword\":\"scmadmin\",\n \"newPassword\":\"5cm4dm1n\"\n}", + summary = "Simple change password" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @ApiResponse( diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NamespacePermissionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NamespacePermissionResource.java index 3fbb2a6a13..68ead6ec60 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NamespacePermissionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NamespacePermissionResource.java @@ -28,7 +28,9 @@ import de.otto.edison.hal.HalRepresentation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.slf4j.Slf4j; import sonia.scm.NotFoundException; @@ -89,7 +91,22 @@ public class NamespacePermissionResource { @POST @Path("") @Consumes(VndMediaType.REPOSITORY_PERMISSION) - @Operation(summary = "Create namespace-specific permission", description = "Adds a new permission to the namespace for the user or group.", tags = {"Namespace", "Permissions"}) + @Operation( + summary = "Create namespace-specific permission", + description = "Adds a new permission to the namespace for the user or group.", + tags = {"Namespace", "Permissions"}, + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY_PERMISSION, + schema = @Schema(implementation = UpdateRepositoryPermissionDto.class), + examples = @ExampleObject( + name = "Add read permissions for repositories and pull requests to manager group.", + value = "{\n \"name\":\"manager\",\n \"verbs\":[\"read\",\"readPullRequest\"],\n \"groupPermission\":true\n}", + summary = "Add a permission" + ) + ) + ) + ) @ApiResponse( responseCode = "201", description = "creates", @@ -135,7 +152,7 @@ public class NamespacePermissionResource { @GET @Path("{permission-name}") @Produces(VndMediaType.REPOSITORY_PERMISSION) - @Operation(summary = "Get single repository-specific permission", description = "Get the searched permission with permission name related to a repository.", tags = {"Repository", "Permissions"}) + @Operation(summary = "Get single namespace-specific permission", description = "Get the searched permission with permission name related to a repository.", tags = {"Namespace", "Permissions"}) @ApiResponse( responseCode = "200", description = "success", @@ -180,7 +197,7 @@ public class NamespacePermissionResource { @GET @Path("") @Produces(VndMediaType.REPOSITORY_PERMISSION) - @Operation(summary = "List of namespace-specific permissions", description = "Get all permissions related to a namespace.", tags = {"Repository", "Permissions"}) + @Operation(summary = "List of namespace-specific permissions", description = "Get all permissions related to a namespace.", tags = {"Namespace", "Permissions"}) @ApiResponse( responseCode = "200", description = "success", @@ -220,7 +237,22 @@ public class NamespacePermissionResource { @PUT @Path("{permission-name}") @Consumes(VndMediaType.REPOSITORY_PERMISSION) - @Operation(summary = "Update repository-specific permission", description = "Update a permission to the user or group managed by the repository.", tags = {"Repository", "Permissions"}) + @Operation( + summary = "Update namespace-specific permission", + description = "Update a permission to the user or group managed by the repository.", + tags = {"Namespace", "Permissions"}, + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY_PERMISSION, + schema = @Schema(implementation = UpdateRepositoryPermissionDto.class), + examples = @ExampleObject( + name = "Update permissions of manager group.", + value = "{\n \"name\":\"manager\",\n \"verbs\":[\"read\",\"permissionRead\",\"readPullRequest\"],\n \"groupPermission\":true\n}", + summary = "Update a permission" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @ApiResponse( @@ -266,7 +298,7 @@ public class NamespacePermissionResource { */ @DELETE @Path("{permission-name}") - @Operation(summary = "Delete repository-specific permission", description = "Delete a permission with the given name.", tags = {"Repository", "Permissions"}) + @Operation(summary = "Delete namespace-specific permission", description = "Delete a permission with the given name.", tags = {"Namespace", "Permissions"}) @ApiResponse(responseCode = "204", description = "delete success or nothing to delete") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @ApiResponse(responseCode = "403", description = "not authorized") @@ -325,6 +357,5 @@ public class NamespacePermissionResource { .stream() .anyMatch(p -> p.getName().equals(permission.getName()) && p.isGroupPermission() == permission.isGroupPermission()); } + } - - diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionListDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionListDto.java index 0a4ae5a1a5..1cfd13d3ad 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionListDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PermissionListDto.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import de.otto.edison.hal.HalRepresentation; @@ -37,7 +37,7 @@ import javax.validation.constraints.NotNull; @Setter @AllArgsConstructor @NoArgsConstructor -public class PermissionListDto extends HalRepresentation { +public class PermissionListDto extends HalRepresentation implements UpdatePermissionListDto { @NotNull private String[] permissions; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java index 72330587ee..19d2daf8bd 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java @@ -27,7 +27,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.apache.shiro.SecurityUtils; import sonia.scm.repository.Repository; @@ -160,7 +162,22 @@ public class RepositoryCollectionResource { @POST @Path("") @Consumes(VndMediaType.REPOSITORY) - @Operation(summary = "Create repository", description = "Creates a new repository.", tags = "Repository") + @Operation( + summary = "Create repository", + description = "Creates a new repository.", + tags = "Repository", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY, + schema = @Schema(implementation = CreateRepositoryDto.class), + examples = @ExampleObject( + name = "Create a new git repository named scm-manager in scmadmin namespace.", + value = "{\n \"namespace\":\"scmadmin\",\n \"name\":\"scm-manager\",\n \"type\":\"git\"\n}", + summary = "Create a git repository" + ) + ) + ) + ) @ApiResponse( responseCode = "201", description = "create success", @@ -220,4 +237,5 @@ public class RepositoryCollectionResource { SearchRequest searchRequest = new SearchRequest(search, true); return repository -> SearchUtil.matchesOne(searchRequest, repository.getName(), repository.getNamespace(), repository.getDescription()); } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java index 2bb457e029..951470a98c 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryDto.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import com.fasterxml.jackson.annotation.JsonInclude; @@ -42,7 +42,7 @@ import java.util.List; @Getter @Setter @NoArgsConstructor -public class RepositoryDto extends HalRepresentation { +public class RepositoryDto extends HalRepresentation implements CreateRepositoryDto, UpdateRepositoryDto { @Email private String contact; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionDto.java index 4c533722b9..05c23f0d73 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionDto.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import de.otto.edison.hal.HalRepresentation; @@ -39,7 +39,7 @@ import java.util.Collection; @Getter @Setter @ToString @NoArgsConstructor @EitherRoleOrVerbs -public class RepositoryPermissionDto extends HalRepresentation { +public class RepositoryPermissionDto extends HalRepresentation implements UpdateRepositoryPermissionDto { public static final String GROUP_PREFIX = "@"; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResource.java index 185ed8df07..e0bfda0824 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResource.java @@ -21,13 +21,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.slf4j.Slf4j; import sonia.scm.AlreadyExistsException; @@ -91,7 +93,22 @@ public class RepositoryPermissionRootResource { @POST @Path("") @Consumes(VndMediaType.REPOSITORY_PERMISSION) - @Operation(summary = "Create repository-specific permission", description = "Adds a new permission to the user or group managed by the repository.", tags = {"Repository", "Permissions"}) + @Operation( + summary = "Create repository-specific permission", + description = "Adds a new permission to the user or group managed by the repository.", + tags = {"Repository", "Permissions"}, + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY_PERMISSION, + schema = @Schema(implementation = UpdateRepositoryPermissionDto.class), + examples = @ExampleObject( + name = "Add read permissions for repository and pull requests to manager group.", + value = "{\n \"name\":\"manager\",\n \"verbs\":[\"read\",\"readPullRequest\"],\n \"groupPermission\":true\n}", + summary = "Add permissions" + ) + ) + ) + ) @ApiResponse( responseCode = "201", description = "creates", @@ -228,7 +245,21 @@ public class RepositoryPermissionRootResource { @PUT @Path("{permission-name}") @Consumes(VndMediaType.REPOSITORY_PERMISSION) - @Operation(summary = "Update repository-specific permission", description = "Update a permission to the user or group managed by the repository.", tags = {"Repository", "Permissions"}) + @Operation( + summary = "Update repository-specific permission", + description = "Update a permission to the user or group managed by the repository.", + tags = {"Repository", "Permissions"}, + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY_PERMISSION, + schema = @Schema(implementation = UpdateRepositoryPermissionDto.class), + examples = @ExampleObject( + name = "Update permissions of manager group.", + value = "{\n \"name\":\"manager\",\n \"verbs\":[\"read\",\"permissionRead\",\"readPullRequest\"],\n \"groupPermission\":true\n}", + summary = "Update a permission" + ) + ) + )) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @ApiResponse( diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRenameDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRenameDto.java index 67848db3fe..6f082a0b88 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRenameDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRenameDto.java @@ -33,7 +33,7 @@ import javax.validation.constraints.Pattern; @Getter @NoArgsConstructor public class RepositoryRenameDto { + private String namespace; @Pattern(regexp = ValidationUtil.REGEX_REPOSITORYNAME) private String name; - private String namespace; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java index 12cc362517..17f82d06b7 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java @@ -26,7 +26,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; @@ -151,7 +153,22 @@ public class RepositoryResource { @PUT @Path("") @Consumes(VndMediaType.REPOSITORY) - @Operation(summary = "Update repository", description = "Modifies the repository for the given namespace and name.", tags = "Repository") + @Operation( + summary = "Update repository", + description = "Modifies the repository for the given namespace and name.", + tags = "Repository", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY, + schema = @Schema(implementation = UpdateRepositoryDto.class), + examples = @ExampleObject( + name = "Update repository description.", + value = "{\n \"namespace\":\"scmadmin\",\n \"name\":\"scm-manager\",\n \"description\":\"The easiest way to share and manage your Git, Mercurial and Subversion repositories.\",\n \"type\":\"git\",\n \"lastModified\":\"2020-06-05T14:42:49.000Z\"\n}", + summary = "Update a repository" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "400", description = "invalid body, e.g. illegal change of namespace or name") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @@ -273,4 +290,5 @@ public class RepositoryResource { private Predicate nameAndNamespaceStaysTheSame(String namespace, String name) { return changed -> name.equals(changed.getName()) && namespace.equals(changed.getNamespace()); } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleCollectionResource.java index 2d65720ca2..bd82ac4210 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleCollectionResource.java @@ -21,13 +21,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.repository.RepositoryRole; import sonia.scm.repository.RepositoryRoleManager; @@ -114,7 +116,22 @@ public class RepositoryRoleCollectionResource { @POST @Path("") @Consumes(VndMediaType.REPOSITORY_ROLE) - @Operation(summary = "Create repository role", description = "Creates a new repository role.", tags = "Repository role") + @Operation( + summary = "Create repository role", + description = "Creates a new repository role.", + tags = "Repository role", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY_ROLE, + schema = @Schema(implementation = CreateRepositoryRoleDto.class), + examples = @ExampleObject( + name = "Create repository role named hero with read and delete repository permission.", + value = "{\n \"name\":\"hero\",\n \"system\":false,\n \"verbs\":[\"read\",\"delete\"]\n}", + summary = "Add a repository role" + ) + ) + ) + ) @ApiResponse( responseCode = "201", description = "create success", @@ -137,4 +154,5 @@ public class RepositoryRoleCollectionResource { public Response create(@Valid RepositoryRoleDto repositoryRole) { return adapter.create(repositoryRole, () -> dtoToRepositoryRoleMapper.map(repositoryRole), u -> resourceLinks.repositoryRole().self(u.getName())); } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleDto.java index 7efef72826..1174ea48af 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleDto.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import de.otto.edison.hal.Embedded; @@ -38,7 +38,7 @@ import java.util.Collection; @Getter @Setter @NoArgsConstructor -public class RepositoryRoleDto extends HalRepresentation { +public class RepositoryRoleDto extends HalRepresentation implements CreateRepositoryRoleDto, UpdateRepositoryRoleDto { @NotEmpty private String name; @NoBlankStrings @NotEmpty diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleResource.java index c76e8b4aa6..c9367cf655 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRoleResource.java @@ -21,12 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.repository.RepositoryRole; import sonia.scm.repository.RepositoryRoleManager; @@ -128,7 +130,22 @@ public class RepositoryRoleResource { @PUT @Path("") @Consumes(VndMediaType.REPOSITORY_ROLE) - @Operation(summary = "Update repository role", description = "Modifies the repository role for the given name.", tags = "Repository role") + @Operation( + summary = "Update repository role", + description = "Modifies the repository role for the given name.", + tags = "Repository role", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.REPOSITORY_ROLE, + schema = @Schema(implementation = UpdateRepositoryRoleDto.class), + examples = @ExampleObject( + name = "Update repository role named hero with this verbs.", + value = "{\n \"name\":\"hero\",\n \"system\":false,\n \"verbs\":[\"read\",\"pull\",\"write\",\"push\",\"delete\"],\n \"lastModified\":\"2020-06-05T14:42:49.000Z\"\n}", + summary = "Update a repository role" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "400", description = "invalid body, e.g. illegal change of repository role name") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @@ -144,4 +161,5 @@ public class RepositoryRoleResource { public Response update(@PathParam("name") String name, @Valid RepositoryRoleDto repositoryRole) { return adapter.update(name, existing -> dtoToRepositoryRoleMapper.map(repositoryRole)); } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateConfigDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateConfigDto.java new file mode 100644 index 0000000000..dbe07a2620 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateConfigDto.java @@ -0,0 +1,77 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import sonia.scm.security.AnonymousMode; + +import java.util.Set; + +interface UpdateConfigDto { + String getProxyPassword(); + + int getProxyPort(); + + String getProxyServer(); + + String getProxyUser(); + + boolean isEnableProxy(); + + String getRealmDescription(); + + boolean isDisableGroupingGrid(); + + String getDateFormat(); + + boolean isAnonymousAccessEnabled(); + + AnonymousMode getAnonymousMode(); + + String getBaseUrl(); + + boolean isForceBaseUrl(); + + int getLoginAttemptLimit(); + + Set getProxyExcludes(); + + boolean isSkipFailedAuthenticators(); + + String getPluginUrl(); + + long getLoginAttemptLimitTimeout(); + + boolean isEnabledXsrfProtection(); + + boolean isEnabledUserConverter(); + + String getNamespaceStrategy(); + + String getLoginInfoUrl(); + + String getReleaseFeedUrl(); + + String getMailDomainName(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateGroupDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateGroupDto.java index d9f06eb88b..ba91365c3c 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateGroupDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateGroupDto.java @@ -25,29 +25,26 @@ package sonia.scm.api.v2.resources; import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; import sonia.scm.util.ValidationUtil; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; import java.time.Instant; import java.util.List; -/** - * This class is currently only used in the openapi scheme - */ -@Getter -@Setter -@NoArgsConstructor -public class UpdateGroupDto { +interface UpdateGroupDto { @Pattern(regexp = ValidationUtil.REGEX_NAME) - private String name; - private String description; + String getName(); + + String getDescription(); + @JsonInclude(JsonInclude.Include.NON_NULL) - private Instant lastModified; - private String type; - private List members; - private boolean external; + Instant getLastModified(); + + String getType(); + + List getMembers(); + + boolean isExternal(); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdatePermissionListDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdatePermissionListDto.java new file mode 100644 index 0000000000..90fb81a34a --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdatePermissionListDto.java @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import javax.validation.constraints.NotNull; + +interface UpdatePermissionListDto { + + @NotNull + String[] getPermissions(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryDto.java new file mode 100644 index 0000000000..9b50ba04df --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryDto.java @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import com.fasterxml.jackson.annotation.JsonInclude; +import sonia.scm.util.ValidationUtil; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; +import java.time.Instant; +import java.util.List; + +interface UpdateRepositoryDto { + + String getNamespace(); + + @Pattern(regexp = ValidationUtil.REGEX_REPOSITORYNAME) + String getName(); + + @NotEmpty + String getType(); + + @Email + String getContact(); + + String getDescription(); + + List getHealthCheckFailures(); + + @JsonInclude(JsonInclude.Include.NON_NULL) + Instant getLastModified(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryPermissionDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryPermissionDto.java new file mode 100644 index 0000000000..c726ad5ca5 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryPermissionDto.java @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import sonia.scm.util.ValidationUtil; + +import javax.validation.constraints.Pattern; +import java.util.Collection; + +interface UpdateRepositoryPermissionDto { + + @Pattern(regexp = ValidationUtil.REGEX_NAME) + String getName(); + + @NoBlankStrings + Collection getVerbs(); + + String getRole(); + + boolean isGroupPermission(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryRoleDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryRoleDto.java new file mode 100644 index 0000000000..499c0da7dd --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateRepositoryRoleDto.java @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import javax.validation.constraints.NotEmpty; +import java.time.Instant; +import java.util.Collection; + +interface UpdateRepositoryRoleDto { + + @NotEmpty + String getName(); + + @NoBlankStrings + @NotEmpty + Collection getVerbs(); + + String getType(); + + Instant getLastModified(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateUserDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateUserDto.java new file mode 100644 index 0000000000..a4b359c005 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UpdateUserDto.java @@ -0,0 +1,54 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api.v2.resources; + +import sonia.scm.util.ValidationUtil; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; +import java.time.Instant; + +interface UpdateUserDto { + + @Pattern(regexp = ValidationUtil.REGEX_NAME) + String getName(); + + @NotEmpty + String getDisplayName(); + + @Email + String getMail(); + + boolean isExternal(); + + String getPassword(); + + boolean isActive(); + + String getType(); + + Instant getLastModified(); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java index 1b604a11f2..12d5294769 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java @@ -27,7 +27,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.apache.shiro.authc.credential.PasswordService; import sonia.scm.search.SearchRequest; @@ -125,7 +127,22 @@ public class UserCollectionResource { @POST @Path("") @Consumes(VndMediaType.USER) - @Operation(summary = "Create user", description = "Creates a new user.", tags = "User") + @Operation( + summary = "Create user", + description = "Creates a new user.", + tags = "User", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.USER, + schema = @Schema(implementation = CreateUserDto.class), + examples = @ExampleObject( + name = "Create an internal user.", + value = "{\n \"name\":\"mustermann\",\n \"displayName\":\"Max Mustermann\",\n \"mail\":\"m.mustermann@scm-manager.org\",\n \"external\":false,\n \"password\":\"muster42*\",\n \"active\":true\n}", + summary = "Create a simple user" + ) + ) + ) + ) @ApiResponse( responseCode = "201", description = "create success", @@ -156,4 +173,5 @@ public class UserCollectionResource { SearchRequest searchRequest = new SearchRequest(search, true); return user -> SearchUtil.matchesOne(searchRequest, user.getName(), user.getDisplayName(), user.getMail()); } + } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java index b1eaa1d7a6..26f120b870 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserDto.java @@ -39,7 +39,7 @@ import javax.validation.constraints.Pattern; import java.time.Instant; @NoArgsConstructor @Getter @Setter -public class UserDto extends HalRepresentation { +public class UserDto extends HalRepresentation implements CreateUserDto, UpdateUserDto { private boolean active; private boolean external; private Instant creationDate; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserPermissionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserPermissionResource.java index fe2b5d3596..773d344937 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserPermissionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserPermissionResource.java @@ -26,7 +26,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.security.PermissionAssigner; import sonia.scm.security.PermissionDescriptor; @@ -106,7 +108,22 @@ public class UserPermissionResource { @PUT @Path("") @Consumes(VndMediaType.PERMISSION_COLLECTION) - @Operation(summary = "Update user permissions", description = "Sets permissions for a user. Overwrites all existing permissions.", tags = {"User", "Permissions"}) + @Operation( + summary = "Update user permissions", + description = "Sets permissions for a user. Overwrites all existing permissions.", + tags = {"User", "Permissions"}, + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.PERMISSION_COLLECTION, + schema = @Schema(implementation = UpdatePermissionListDto.class), + examples = @ExampleObject( + name = "Add read permissions for all repositories and pull requests.", + value = "{\n \"permissions\":[\"repository:read,pull:*\",\"repository:readPullRequest:*\"]\n}", + summary = "Simple update user permissions" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "400", description = "invalid body") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java index 679224cde8..76902505d7 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserResource.java @@ -26,7 +26,9 @@ package sonia.scm.api.v2.resources; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.apache.shiro.authc.credential.PasswordService; import sonia.scm.user.User; @@ -137,7 +139,22 @@ public class UserResource { @PUT @Path("") @Consumes(VndMediaType.USER) - @Operation(summary = "Update user", description = "Modifies the user for the given id.", tags = "User") + @Operation( + summary = "Update user", + description = "Modifies the user for the given id.", + tags = "User", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.USER, + schema = @Schema(implementation = UpdateUserDto.class), + examples = @ExampleObject( + name = "Update the email address of user mustermann.", + value = "{\n \"name\":\"mustermann\",\n \"displayName\":\"Max Mustermann\",\n \"mail\":\"maxmustermann@scm-manager.org\",\n \"external\":false,\n \"active\":true,\n \"lastModified\":\"2020-06-05T14:42:49.000Z\"\n}", + summary = "Update a user" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "400", description = "invalid body, e.g. illegal change of id/user name") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @@ -168,7 +185,22 @@ public class UserResource { @PUT @Path("password") @Consumes(VndMediaType.PASSWORD_OVERWRITE) - @Operation(summary = "Modifies a user password", description = "Lets admins modifies the user password for the given id.", tags = "User") + @Operation( + summary = "Modifies a user password", + description = "Lets admins modifies the user password for the given id.", + tags = "User", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.PASSWORD_OVERWRITE, + schema = @Schema(implementation = PasswordOverwriteDto.class), + examples = @ExampleObject( + name = "Overwrites current password with a more difficult one.", + value = "{ \"newPassword\":\"5cm4dm1n\"\n}", + summary = "Set new password" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "400", description = "invalid body, e.g. the user type is not xml or the given oldPassword do not match the stored one") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @@ -199,7 +231,22 @@ public class UserResource { @PUT @Path("convert-to-internal") @Consumes(VndMediaType.USER) - @Operation(summary = "Converts an external user to internal", description = "Converts an external user to an internal one and set the new password.", tags = "User") + @Operation( + summary = "Converts an external user to internal", + description = "Converts an external user to an internal one and set the new password.", + tags = "User", + requestBody = @RequestBody( + content = @Content( + mediaType = VndMediaType.USER, + schema = @Schema(implementation = PasswordOverwriteDto.class), + examples = @ExampleObject( + name = "Converts an external user to an internal one and set the new password.", + value = "{ \"newPassword\":\"5cm4dm1n\"\n}", + summary = "Simple converts an user" + ) + ) + ) + ) @ApiResponse(responseCode = "204", description = "update success") @ApiResponse(responseCode = "400", description = "invalid body, e.g. the new password is missing") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @@ -255,4 +302,5 @@ public class UserResource { public UserPermissionResource permissions() { return userPermissionResource; } + } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeDtoFactoryTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeDtoFactoryTest.java index ea539c4631..76d37bbc78 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeDtoFactoryTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeDtoFactoryTest.java @@ -156,19 +156,7 @@ class MeDtoFactoryTest { } @Test - void shouldGetPasswordLinkOnlyForDefaultUserType() { - User user = UserTestData.createTrillian(); - prepareSubject(user); - - when(subject.isPermitted("user:changePassword:trillian")).thenReturn(true); - when(userManager.isTypeDefault(user)).thenReturn(true); - - MeDto dto = meDtoFactory.create(); - assertThat(dto.getLinks().getLinkBy("password").get().getHref()).isEqualTo("https://scm.hitchhiker.com/scm/v2/me/password"); - } - - @Test - void shouldNotGetPasswordLinkWithoutPermision() { + void shouldNotGetPasswordLinkWithoutPermission() { User user = UserTestData.createTrillian(); prepareSubject(user); @@ -178,17 +166,6 @@ class MeDtoFactoryTest { assertThat(dto.getLinks().getLinkBy("password")).isNotPresent(); } - @Test - void shouldNotGetPasswordLinkForNonDefaultUsers() { - User user = UserTestData.createTrillian(); - prepareSubject(user); - - when(subject.isPermitted("user:changePassword:trillian")).thenReturn(true); - - MeDto dto = meDtoFactory.create(); - assertThat(dto.getLinks().getLinkBy("password")).isNotPresent(); - } - @Test void shouldAppendOnlySelfLinkIfAnonymousUser() { User user = SCMContext.ANONYMOUS;