You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by bh...@apache.org on 2019/05/22 13:17:05 UTC

[incubator-dlab] branch feature/projects created (now 0c389f1)

This is an automated email from the ASF dual-hosted git repository.

bhliva pushed a change to branch feature/projects
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git.


      at 0c389f1  DLAB-000 added project + enpoint API

This branch includes the following new commits:

     new 0c389f1  DLAB-000 added project + enpoint API

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org


[incubator-dlab] 01/01: DLAB-000 added project + enpoint API

Posted by bh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bhliva pushed a commit to branch feature/projects
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git

commit 0c389f18f5cfd6d43f08b147994ad1ced6cd785a
Author: bhliva <bo...@epam.com>
AuthorDate: Wed May 22 14:56:40 2019 +0300

    DLAB-000 added project + enpoint API
---
 .../src/ssn/files/aws/mongo_roles.json             |   4 +-
 .../src/ssn/files/azure/mongo_roles.json           |   4 +-
 .../src/ssn/files/gcp/mongo_roles.json             |   4 +-
 services/self-service/pom.xml                      |  16 +++
 .../dlab/backendapi/SelfServiceApplication.java    |  34 +++++-
 .../com/epam/dlab/backendapi/dao/EndpointDAO.java  |  13 +++
 .../epam/dlab/backendapi/dao/EndpointDAOImpl.java  |  32 ++++++
 .../com/epam/dlab/backendapi/dao/ProjectDAO.java   |  15 +++
 .../epam/dlab/backendapi/dao/ProjectDAOImpl.java   |  39 +++++++
 .../epam/dlab/backendapi/domain/EndpointDTO.java   |  11 ++
 .../epam/dlab/backendapi/domain/ProjectDTO.java    |  14 +++
 .../epam/dlab/backendapi/modules/DevModule.java    |   4 +
 .../backendapi/resources/EndpointResource.java     |  96 +++++++++++++++++
 .../dlab/backendapi/resources/ProjectResource.java | 115 +++++++++++++++++++++
 .../dlab/backendapi/service/EndpointService.java   |  11 ++
 .../dlab/backendapi/service/ProjectService.java    |  13 +++
 .../service/impl/EndpointServiceImpl.java          |  37 +++++++
 .../service/impl/ProjectServiceImpl.java           |  51 +++++++++
 18 files changed, 506 insertions(+), 7 deletions(-)

diff --git a/infrastructure-provisioning/src/ssn/files/aws/mongo_roles.json b/infrastructure-provisioning/src/ssn/files/aws/mongo_roles.json
index 68b31b6..70eb16e 100644
--- a/infrastructure-provisioning/src/ssn/files/aws/mongo_roles.json
+++ b/infrastructure-provisioning/src/ssn/files/aws/mongo_roles.json
@@ -267,7 +267,9 @@
       "/api/infrastructure/backup",
       "/roleManagement",
       "/api/settings",
-      "/user/settings"
+      "/user/settings",
+      "/api/project",
+      "/api/endpoint"
     ],
     "groups": [
       "$anyuser"
diff --git a/infrastructure-provisioning/src/ssn/files/azure/mongo_roles.json b/infrastructure-provisioning/src/ssn/files/azure/mongo_roles.json
index fc11971..58cadb3 100644
--- a/infrastructure-provisioning/src/ssn/files/azure/mongo_roles.json
+++ b/infrastructure-provisioning/src/ssn/files/azure/mongo_roles.json
@@ -227,7 +227,9 @@
       "/api/infrastructure/backup",
       "/roleManagement",
       "/api/settings",
-      "/user/settings"
+      "/user/settings",
+      "/api/project",
+      "/api/endpoint"
     ],
     "groups": [
       "$anyuser"
diff --git a/infrastructure-provisioning/src/ssn/files/gcp/mongo_roles.json b/infrastructure-provisioning/src/ssn/files/gcp/mongo_roles.json
index 47ce720..0dceb3c 100644
--- a/infrastructure-provisioning/src/ssn/files/gcp/mongo_roles.json
+++ b/infrastructure-provisioning/src/ssn/files/gcp/mongo_roles.json
@@ -227,7 +227,9 @@
       "/api/infrastructure/backup",
       "/roleManagement",
       "/api/settings",
-      "/user/settings"
+      "/user/settings",
+      "/api/project",
+      "/api/endpoint"
     ],
     "groups": [
       "$anyuser"
diff --git a/services/self-service/pom.xml b/services/self-service/pom.xml
index 5521958..9ce6b72 100644
--- a/services/self-service/pom.xml
+++ b/services/self-service/pom.xml
@@ -91,6 +91,22 @@
         </dependency>
 
         <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-core</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-jaxrs2</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-integration</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+
+        <dependency>
             <groupId>com.jcraft</groupId>
             <artifactId>jsch</artifactId>
             <version>${com.jcraft.jsch.version}</version>
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
index 979464f..508b34f 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
@@ -51,8 +51,11 @@ import io.dropwizard.jersey.setup.JerseyEnvironment;
 import io.dropwizard.jetty.BiDiGzipHandler;
 import io.dropwizard.setup.Bootstrap;
 import io.dropwizard.setup.Environment;
-import io.federecio.dropwizard.swagger.SwaggerBundle;
-import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
+import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
+import io.swagger.v3.oas.integration.SwaggerConfiguration;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
 import lombok.extern.slf4j.Slf4j;
 import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.Server;
@@ -60,6 +63,8 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
 
 import javax.servlet.DispatcherType;
 import java.util.EnumSet;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Self Service based on Dropwizard application.
@@ -92,12 +97,13 @@ public class SelfServiceApplication extends Application<SelfServiceApplicationCo
 		bootstrap.addBundle(new TemplateConfigBundle(
 				new TemplateConfigBundleConfiguration().fileIncludePath(ServiceUtils.getConfPath())
 		));
-		bootstrap.addBundle(new SwaggerBundle<SelfServiceApplicationConfiguration>() {
+
+		/*bootstrap.addBundle(new SwaggerBundle<SelfServiceApplicationConfiguration>() {
 			@Override
 			protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(SelfServiceApplicationConfiguration configuration) {
 				return configuration.getSwaggerConfiguration();
 			}
-		});
+		});*/
 	}
 
 	@Override
@@ -173,6 +179,26 @@ public class SelfServiceApplication extends Application<SelfServiceApplicationCo
 		jersey.register(injector.getInstance(UserGroupResource.class));
 		jersey.register(injector.getInstance(UserRoleResource.class));
 		jersey.register(injector.getInstance(ApplicationSettingResource.class));
+		jersey.register(injector.getInstance(EndpointResource.class));
+		jersey.register(injector.getInstance(ProjectResource.class));
+		OpenAPI oas = new OpenAPI();
+		Info info = new Info()
+				.title("Hello World API")
+				.version("2.1")
+				.description("RESTful greetings for you.")
+				.termsOfService("http://example.com/terms")
+				.contact(new Contact().email("john@example.com"));
+
+		oas.info(info);
+		SwaggerConfiguration oasConfig = new SwaggerConfiguration()
+				.openAPI(oas)
+				.readAllResources(false)
+				.prettyPrint(true)
+				.resourceClasses(Stream.of(ProjectResource.class.getName(),
+						EndpointResource.class.getName())
+						.collect(Collectors.toSet()));
+		environment.jersey().register(new OpenApiResource()
+				.openApiConfiguration(oasConfig));
 	}
 
 	private void disableGzipHandlerForGuacamoleServlet(Server server) {
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EndpointDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EndpointDAO.java
new file mode 100644
index 0000000..27aa6d7
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EndpointDAO.java
@@ -0,0 +1,13 @@
+package com.epam.dlab.backendapi.dao;
+
+import com.epam.dlab.backendapi.domain.EndpointDTO;
+
+import java.util.Optional;
+
+public interface EndpointDAO {
+	Optional<EndpointDTO> get(String name);
+
+	void create(EndpointDTO endpointDTO);
+
+	void remove(String name);
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EndpointDAOImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EndpointDAOImpl.java
new file mode 100644
index 0000000..a7c0e70
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EndpointDAOImpl.java
@@ -0,0 +1,32 @@
+package com.epam.dlab.backendapi.dao;
+
+import com.epam.dlab.backendapi.domain.EndpointDTO;
+import org.bson.conversions.Bson;
+
+import java.util.Optional;
+
+import static com.mongodb.client.model.Filters.eq;
+
+public class EndpointDAOImpl extends BaseDAO implements EndpointDAO {
+
+	private static final String ENDPOINTS_COLLECTION = "endpoints";
+
+	@Override
+	public Optional<EndpointDTO> get(String name) {
+		return findOne(ENDPOINTS_COLLECTION, endpointCondition(name), EndpointDTO.class);
+	}
+
+	@Override
+	public void create(EndpointDTO endpointDTO) {
+		insertOne(ENDPOINTS_COLLECTION, endpointDTO);
+	}
+
+	@Override
+	public void remove(String name) {
+		deleteOne(ENDPOINTS_COLLECTION, endpointCondition(name));
+	}
+
+	private Bson endpointCondition(String name) {
+		return eq("name", name);
+	}
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
new file mode 100644
index 0000000..a8e18ea
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
@@ -0,0 +1,15 @@
+package com.epam.dlab.backendapi.dao;
+
+import com.epam.dlab.backendapi.domain.ProjectDTO;
+
+import java.util.Optional;
+
+public interface ProjectDAO {
+	void create(ProjectDTO projectDTO);
+
+	Optional<ProjectDTO> get(String name);
+
+	boolean update(ProjectDTO projectDTO);
+
+	void remove(String name);
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
new file mode 100644
index 0000000..0f6c6e7
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
@@ -0,0 +1,39 @@
+package com.epam.dlab.backendapi.dao;
+
+import com.epam.dlab.backendapi.domain.ProjectDTO;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+
+import java.util.Optional;
+
+import static com.mongodb.client.model.Filters.eq;
+
+public class ProjectDAOImpl extends BaseDAO implements ProjectDAO {
+
+	private static final String PROJECTS_COLLECTION = "Projects";
+
+	@Override
+	public void create(ProjectDTO projectDTO) {
+		insertOne(PROJECTS_COLLECTION, projectDTO);
+	}
+
+	@Override
+	public Optional<ProjectDTO> get(String name) {
+		return findOne(PROJECTS_COLLECTION, projectCondition(name), ProjectDTO.class);
+	}
+
+	@Override
+	public boolean update(ProjectDTO projectDTO) {
+		return updateOne(PROJECTS_COLLECTION, projectCondition(projectDTO.getName()),
+				new Document(SET, convertToBson(projectDTO))).getMatchedCount() > 0L;
+	}
+
+	@Override
+	public void remove(String name) {
+
+	}
+
+	private Bson projectCondition(String name) {
+		return eq("name", name);
+	}
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EndpointDTO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EndpointDTO.java
new file mode 100644
index 0000000..4e14f08
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EndpointDTO.java
@@ -0,0 +1,11 @@
+package com.epam.dlab.backendapi.domain;
+
+import lombok.Data;
+
+@Data
+public class EndpointDTO {
+
+	private final String name;
+	private final String url;
+	private final String account;
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
new file mode 100644
index 0000000..2799a2e
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
@@ -0,0 +1,14 @@
+package com.epam.dlab.backendapi.domain;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+import java.util.Set;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ProjectDTO {
+	private final String name;
+	private final Set<String> endpoints;
+	private final Set<String> groups;
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java
index bd4a5ab..2f6ae9b 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java
@@ -110,6 +110,10 @@ public class DevModule extends ModuleBase<SelfServiceApplicationConfiguration> i
 		bind(ApplicationSettingService.class).to(ApplicationSettingServiceImpl.class);
 		bind(UserSettingService.class).to(UserSettingServiceImpl.class);
 		bind(GuacamoleService.class).to(GuacamoleServiceImpl.class);
+		bind(EndpointService.class).to(EndpointServiceImpl.class);
+		bind(EndpointDAO.class).to(EndpointDAOImpl.class);
+		bind(ProjectService.class).to(ProjectServiceImpl.class);
+		bind(ProjectDAO.class).to(ProjectDAOImpl.class);
 	}
 
 	/**
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EndpointResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EndpointResource.java
new file mode 100644
index 0000000..af3426e
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EndpointResource.java
@@ -0,0 +1,96 @@
+package com.epam.dlab.backendapi.resources;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
+import com.epam.dlab.backendapi.service.EndpointService;
+import com.epam.dlab.rest.dto.ErrorDTO;
+import com.google.inject.Inject;
+import io.dropwizard.auth.Auth;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+
+@Path("endpoint")
+@RolesAllowed("/api/endpoint")
+public class EndpointResource {
+
+	private final EndpointService endpointService;
+	@Context
+	private UriInfo uriInfo;
+
+	@Inject
+	public EndpointResource(EndpointService endpointService) {
+		this.endpointService = endpointService;
+	}
+
+	@Operation(summary = "Create endpoint", tags = "endpoint")
+	@ApiResponses({
+			@ApiResponse(responseCode = "201", description = "Endpoint is successfully created",
+					headers =
+					@Header(required = true, name = "Location", description = "URI of created endpoint resource",
+							schema = @Schema(type = "string"))),
+			@ApiResponse(responseCode = "400", description = "Validation error", content = @Content(mediaType =
+					MediaType.APPLICATION_JSON,
+					schema = @Schema(implementation = ErrorDTO.class))),
+			@ApiResponse(responseCode = "409", description = "Endpoint with passed name already exist in system",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON,
+							schema = @Schema(implementation = ErrorDTO.class)))
+	})
+	@Consumes(MediaType.APPLICATION_JSON)
+	@POST
+	public Response createEndpoint(@Parameter(hidden = true) @Auth UserInfo userInfo, EndpointDTO endpointDTO) {
+		endpointService.create(endpointDTO);
+		final URI uri = uriInfo.getRequestUriBuilder().path(endpointDTO.getName()).build();
+		return Response
+				.ok()
+				.location(uri)
+				.build();
+	}
+
+	@Operation(summary = "Get endpoint info", tags = "endpoint")
+	@ApiResponses({
+			@ApiResponse(responseCode = "200", description = "Return information about endpoint",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON, schema =
+					@Schema(implementation = EndpointDTO.class))),
+			@ApiResponse(responseCode = "404", description = "Endpoint with passed name not found",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON,
+							schema = @Schema(implementation = ErrorDTO.class)))
+	})
+	@GET
+	@Path("{name}")
+	public Response getEndpoint(@Parameter(hidden = true) @Auth UserInfo userInfo,
+								@Parameter(description = "Endpoint name")
+								@PathParam("name") String name) {
+		endpointService.get(name);
+		return Response.ok().build();
+	}
+
+
+	@Operation(summary = "Remove endpoint", tags = "endpoint")
+	@ApiResponses({
+			@ApiResponse(responseCode = "200", description = "Endpoint is successfully removed"),
+			@ApiResponse(responseCode = "404", description = "Endpoint with passed name not found",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON,
+							schema = @Schema(implementation = ErrorDTO.class)))
+	})
+	@DELETE
+	@Path("{name}")
+	public Response removeEndpoint(@Parameter(hidden = true) @Auth UserInfo userInfo,
+								   @Parameter(description = "Endpoint name")
+								   @PathParam("name") String name) {
+		endpointService.remove(name);
+		return Response.ok().build();
+	}
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
new file mode 100644
index 0000000..4346601
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
@@ -0,0 +1,115 @@
+package com.epam.dlab.backendapi.resources;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.rest.dto.ErrorDTO;
+import com.google.inject.Inject;
+import io.dropwizard.auth.Auth;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+
+@Path("project")
+@RolesAllowed("/api/project")
+public class ProjectResource {
+	private final ProjectService projectService;
+	@Context
+	private UriInfo uriInfo;
+
+	@Inject
+	public ProjectResource(ProjectService projectService) {
+		this.projectService = projectService;
+	}
+
+
+	@Operation(summary = "Create project", tags = "project")
+	@ApiResponses({
+			@ApiResponse(responseCode = "201", description = "Project is successfully created",
+					headers =
+					@Header(required = true, name = "Location", description = "URI of created project resource",
+							schema = @Schema(type = "string"))),
+			@ApiResponse(responseCode = "400", description = "Validation error", content = @Content(mediaType =
+					MediaType.APPLICATION_JSON,
+					schema = @Schema(implementation = ErrorDTO.class))),
+			@ApiResponse(responseCode = "409", description = "Project with passed name already exist in system",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON,
+							schema = @Schema(implementation = ErrorDTO.class)))
+	})
+	@POST
+	@Consumes(MediaType.APPLICATION_JSON)
+	public Response createProject(@Parameter(hidden = true) @Auth UserInfo userInfo, ProjectDTO projectDTO) {
+		projectService.create(projectDTO);
+		final URI uri = uriInfo.getRequestUriBuilder().path(projectDTO.getName()).build();
+		return Response
+				.ok()
+				.location(uri)
+				.build();
+	}
+
+
+	@Operation(summary = "Get project info", tags = "project")
+	@ApiResponses({
+			@ApiResponse(responseCode = "200", description = "Return information about project",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON, schema =
+					@Schema(implementation = ProjectDTO.class))),
+			@ApiResponse(responseCode = "404", description = "Project with passed name not found",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON,
+							schema = @Schema(implementation = ErrorDTO.class)))
+	})
+	@GET
+	@Path("{name}")
+	@Produces(MediaType.APPLICATION_JSON)
+	public Response getProject(@Parameter(hidden = true) @Auth UserInfo userInfo,
+							   @Parameter(description = "Project name")
+							   @PathParam("name") String name) {
+		return Response
+				.ok(projectService.get(name))
+				.build();
+	}
+
+	@Operation(summary = "Update project", tags = "project")
+	@ApiResponses({
+			@ApiResponse(responseCode = "200", description = "Project is successfully updated"),
+			@ApiResponse(responseCode = "400", description = "Validation error", content = @Content(mediaType =
+					MediaType.APPLICATION_JSON,
+					schema = @Schema(implementation = ErrorDTO.class))),
+			@ApiResponse(responseCode = "404", description = "Project with passed name not found",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON,
+							schema = @Schema(implementation = ErrorDTO.class)))
+	})
+	@PUT
+	public Response updateProject(@Parameter(hidden = true) @Auth UserInfo userInfo, ProjectDTO projectDTO) {
+		projectService.update(projectDTO);
+		return Response.ok().build();
+	}
+
+	@Operation(summary = "Remove project", tags = "project")
+	@ApiResponses({
+			@ApiResponse(responseCode = "200", description = "Project is successfully removed"),
+			@ApiResponse(responseCode = "404", description = "Project with passed name not found",
+					content = @Content(mediaType = MediaType.APPLICATION_JSON,
+							schema = @Schema(implementation = ErrorDTO.class)))
+	})
+	@DELETE
+	@Path("{name}")
+	public Response removeProject(
+			@Parameter(hidden = true) @Auth UserInfo userInfo,
+			@Parameter(description = "Project name")
+			@PathParam("name") String name) {
+		projectService.remove(name);
+		return Response.ok().build();
+	}
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EndpointService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EndpointService.java
new file mode 100644
index 0000000..1f3161f
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EndpointService.java
@@ -0,0 +1,11 @@
+package com.epam.dlab.backendapi.service;
+
+import com.epam.dlab.backendapi.domain.EndpointDTO;
+
+public interface EndpointService {
+	EndpointDTO get(String name);
+
+	void create(EndpointDTO endpointDTO);
+
+	void remove(String name);
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
new file mode 100644
index 0000000..9619f87
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
@@ -0,0 +1,13 @@
+package com.epam.dlab.backendapi.service;
+
+import com.epam.dlab.backendapi.domain.ProjectDTO;
+
+public interface ProjectService {
+	void create(ProjectDTO projectDTO);
+
+	ProjectDTO get(String name);
+
+	void remove(String name);
+
+	void update(ProjectDTO projectDTO);
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EndpointServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EndpointServiceImpl.java
new file mode 100644
index 0000000..a4586a8
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EndpointServiceImpl.java
@@ -0,0 +1,37 @@
+package com.epam.dlab.backendapi.service.impl;
+
+import com.epam.dlab.backendapi.dao.EndpointDAO;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
+import com.epam.dlab.backendapi.service.EndpointService;
+import com.epam.dlab.exceptions.ResourceConflictException;
+import com.epam.dlab.exceptions.ResourceNotFoundException;
+import com.google.inject.Inject;
+
+public class EndpointServiceImpl implements EndpointService {
+	private final EndpointDAO endpointDAO;
+
+	@Inject
+	public EndpointServiceImpl(EndpointDAO endpointDAO) {
+		this.endpointDAO = endpointDAO;
+	}
+
+	@Override
+	public EndpointDTO get(String name) {
+		return endpointDAO.get(name)
+				.orElseThrow(() -> new ResourceNotFoundException("Endpoint with name " + name + " not found"));
+	}
+
+	@Override
+	public void create(EndpointDTO endpointDTO) {
+		if (!endpointDAO.get(endpointDTO.getName()).isPresent()) {
+			endpointDAO.create(endpointDTO);
+		} else {
+			throw new ResourceConflictException("Project with passed name already exist in system");
+		}
+	}
+
+	@Override
+	public void remove(String name) {
+		endpointDAO.remove(name);
+	}
+}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
new file mode 100644
index 0000000..5230674
--- /dev/null
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
@@ -0,0 +1,51 @@
+package com.epam.dlab.backendapi.service.impl;
+
+import com.epam.dlab.backendapi.dao.ProjectDAO;
+import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.exceptions.ResourceConflictException;
+import com.epam.dlab.exceptions.ResourceNotFoundException;
+import com.google.inject.Inject;
+
+import java.util.function.Supplier;
+
+public class ProjectServiceImpl implements ProjectService {
+
+	private final ProjectDAO projectDAO;
+
+	@Inject
+	public ProjectServiceImpl(ProjectDAO projectDAO) {
+		this.projectDAO = projectDAO;
+	}
+
+	@Override
+	public void create(ProjectDTO projectDTO) {
+		if (!projectDAO.get(projectDTO.getName()).isPresent()) {
+			projectDAO.create(projectDTO);
+		} else {
+			throw new ResourceConflictException("Project with passed name already exist in system");
+		}
+	}
+
+	@Override
+	public ProjectDTO get(String name) {
+		return projectDAO.get(name)
+				.orElseThrow(projectNotFound());
+	}
+
+	@Override
+	public void remove(String name) {
+		projectDAO.remove(name);
+	}
+
+	@Override
+	public void update(ProjectDTO projectDTO) {
+		if (!projectDAO.update(projectDTO)) {
+			throw projectNotFound().get();
+		}
+	}
+
+	private Supplier<ResourceNotFoundException> projectNotFound() {
+		return () -> new ResourceNotFoundException("Project with passed name not found");
+	}
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org