1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.linecorp.centraldogma.server.internal.api;
18
19 import static com.google.common.collect.ImmutableList.toImmutableList;
20 import static com.linecorp.centraldogma.server.internal.api.HttpApiUtil.checkStatusArgument;
21 import static com.linecorp.centraldogma.server.internal.api.HttpApiUtil.checkUnremoveArgument;
22 import static com.linecorp.centraldogma.server.internal.api.HttpApiUtil.returnOrThrow;
23 import static java.util.Objects.requireNonNull;
24
25 import java.util.List;
26 import java.util.concurrent.CompletableFuture;
27
28 import javax.annotation.Nullable;
29
30 import com.fasterxml.jackson.databind.JsonNode;
31
32 import com.linecorp.armeria.common.ContextAwareBlockingTaskExecutor;
33 import com.linecorp.armeria.server.ServiceRequestContext;
34 import com.linecorp.armeria.server.annotation.Consumes;
35 import com.linecorp.armeria.server.annotation.Default;
36 import com.linecorp.armeria.server.annotation.Delete;
37 import com.linecorp.armeria.server.annotation.ExceptionHandler;
38 import com.linecorp.armeria.server.annotation.Get;
39 import com.linecorp.armeria.server.annotation.Param;
40 import com.linecorp.armeria.server.annotation.Patch;
41 import com.linecorp.armeria.server.annotation.Post;
42 import com.linecorp.armeria.server.annotation.ProducesJson;
43 import com.linecorp.armeria.server.annotation.ResponseConverter;
44 import com.linecorp.armeria.server.annotation.StatusCode;
45 import com.linecorp.centraldogma.common.Author;
46 import com.linecorp.centraldogma.internal.api.v1.CreateProjectRequest;
47 import com.linecorp.centraldogma.internal.api.v1.ProjectDto;
48 import com.linecorp.centraldogma.server.internal.api.auth.RequiresAdministrator;
49 import com.linecorp.centraldogma.server.internal.api.auth.RequiresRole;
50 import com.linecorp.centraldogma.server.internal.api.converter.CreateApiResponseConverter;
51 import com.linecorp.centraldogma.server.internal.storage.project.ProjectApiManager;
52 import com.linecorp.centraldogma.server.metadata.ProjectMetadata;
53 import com.linecorp.centraldogma.server.metadata.ProjectRole;
54 import com.linecorp.centraldogma.server.storage.project.Project;
55
56
57
58
59 @ProducesJson
60 @ExceptionHandler(HttpApiExceptionHandler.class)
61 public class ProjectServiceV1 {
62
63 private final ProjectApiManager projectApiManager;
64
65 public ProjectServiceV1(ProjectApiManager projectApiManager) {
66 this.projectApiManager = requireNonNull(projectApiManager, "projectApiManager");
67 }
68
69
70
71
72
73
74 @Get("/projects")
75 public CompletableFuture<List<ProjectDto>> listProjects(@Param @Nullable String status) {
76 final ContextAwareBlockingTaskExecutor executor =
77 ServiceRequestContext.current().blockingTaskExecutor();
78 if (status != null) {
79 checkStatusArgument(status);
80 return CompletableFuture.supplyAsync(() -> projectApiManager.listRemovedProjects().keySet()
81 .stream()
82 .map(ProjectDto::new)
83 .collect(toImmutableList()), executor);
84 }
85
86 return CompletableFuture.supplyAsync(() -> projectApiManager.listProjects().values().stream()
87 .map(DtoConverter::convert)
88 .collect(toImmutableList()), executor);
89 }
90
91
92
93
94
95
96 @Post("/projects")
97 @StatusCode(201)
98 @ResponseConverter(CreateApiResponseConverter.class)
99 public CompletableFuture<ProjectDto> createProject(CreateProjectRequest request, Author author) {
100 return projectApiManager.createProject(request.name(), author)
101 .handle(returnOrThrow(() -> DtoConverter.convert(
102 projectApiManager.getProject(request.name()))));
103 }
104
105
106
107
108
109
110
111
112 @Get("/projects/{projectName}")
113 @RequiresRole(roles = { ProjectRole.OWNER, ProjectRole.MEMBER })
114 public CompletableFuture<ProjectMetadata> getProjectMetadata(
115 @Param String projectName,
116 @Param("checkPermissionOnly") @Default("false") boolean isCheckPermissionOnly) {
117 if (isCheckPermissionOnly) {
118 return CompletableFuture.completedFuture(null);
119 }
120 return projectApiManager.getProjectMetadata(projectName);
121 }
122
123
124
125
126
127
128 @Delete("/projects/{projectName}")
129 @RequiresRole(roles = ProjectRole.OWNER)
130 public CompletableFuture<Void> removeProject(Project project, Author author) {
131 return projectApiManager.removeProject(project.name(), author);
132 }
133
134
135
136
137
138
139 @Delete("/projects/{projectName}/removed")
140 @RequiresRole(roles = ProjectRole.OWNER)
141 public CompletableFuture<Void> purgeProject(@Param String projectName, Author author) {
142 return projectApiManager.purgeProject(projectName, author);
143 }
144
145
146
147
148
149
150 @Consumes("application/json-patch+json")
151 @Patch("/projects/{projectName}")
152 @RequiresAdministrator
153 public CompletableFuture<ProjectDto> patchProject(@Param String projectName, JsonNode node, Author author) {
154 checkUnremoveArgument(node);
155 return projectApiManager.unremoveProject(projectName, author)
156 .handle(returnOrThrow(() -> DtoConverter.convert(
157 projectApiManager.getProject(projectName))));
158 }
159 }