Skip to content

Commit

Permalink
enhancements(app): added and fixes methods related to project app cre…
Browse files Browse the repository at this point in the history
…ation and updating
  • Loading branch information
zZHorizonZz committed Aug 3, 2023
1 parent 55a52e3 commit ca69d0c
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ public class ErrorMessage {
public static final ErrorMessage INVALID_GRANT_TYPE = new ErrorMessage("grant_type", "Invalid grant type");
public static final ErrorMessage INVALID_REFRESH_TOKEN = new ErrorMessage("refresh_token", "Invalid refresh token");
public static final ErrorMessage PROJECT_ALREADY_EXISTS = new ErrorMessage("project_name", "Project already exists");
public static final ErrorMessage PROJECT_NOT_MEMBER = new ErrorMessage("project_id", "You are not a member of this project");
public static final ErrorMessage PROJECT_NOT_FOUND = new ErrorMessage("project_id", "Project not found");
public static final ErrorMessage PROJECT_APP_ALREADY_EXISTS = new ErrorMessage("project_app_name", "Project app already exists");
public static final ErrorMessage PROJECT_APP_NOT_FOUND = new ErrorMessage("project_app_id", "Project app not found");
public static final ErrorMessage PROJECT_APP_RELEASE_NOT_FOUND = new ErrorMessage("project_app_release_id", "Project app release not found");
public static final ErrorMessage PROJECT_APP_UPLOAD_NOT_FOUND = new ErrorMessage("project_app_upload_id", "Project app upload not found");

private final String error;
private final String description;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
import dev.shiperist.entity.project.ProjectAppEntity;
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;

@WithSession
@ApplicationScoped
public class ProjectAppRepository implements PanacheRepositoryBase<ProjectAppEntity, Long> {

public Uni<ProjectAppEntity> findByName(String name) {
return find("name", name).firstResult();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package dev.shiperist.resource.project;

import dev.shiperist.exception.ErrorMessage;
import dev.shiperist.model.project.ProjectApp;
import dev.shiperist.service.project.ProjectAppService;
import dev.shiperist.service.project.ProjectMemberService;
import io.quarkus.security.Authenticated;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.RequestScoped;
Expand All @@ -19,16 +19,14 @@
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;

import java.util.function.Function;


@RequestScoped
@Authenticated
@Path("/projects/{projectId}/apps")
@Tag(name = "Project Apps")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProjectAppResource extends BaseProjectResource{
public class ProjectAppResource extends BaseProjectResource {

//TODO Add project member to have permission to create project app

Expand All @@ -39,6 +37,8 @@ public class ProjectAppResource extends BaseProjectResource{
@Claim(standard = Claims.sub)
String sub;

//TODO Is this is the correct way to do it I mean to work with entities possibly in here or move it to the service layer?

@PUT
@Operation(summary = "Create a project app")
@APIResponse(
Expand All @@ -47,9 +47,20 @@ public class ProjectAppResource extends BaseProjectResource{
content = @Content(schema = @Schema(implementation = ProjectApp.class))
)
public Uni<Response> createProjectApp(@Parameter(description = "Project ID") @PathParam("projectId") Long projectId, ProjectApp app) {
return ifMember(Long.parseLong(sub), projectId, isMember ->
projectAppService.createProjectApp(projectId, app.getName(), app.getDisplayName(), app.getDescription(), app.getImage(), app.getOs(), app.getReleaseType())
.onItem().ifNotNull().transform(projectApp -> Response.status(Response.Status.CREATED).entity(projectApp).build()));
return ifMember(Long.parseLong(sub), projectId, isMember -> {
if (isMember) {
return projectAppService.doesProjectAppExist(app.getName()).flatMap(exists -> {
if (!exists) {
return projectAppService.createProjectApp(projectId, app.getName(), app.getDisplayName(), app.getDescription(), app.getImage(), app.getOs(), app.getReleaseType())
.onItem().ifNotNull().transform(projectApp -> Response.status(Response.Status.CREATED).entity(projectApp).build());
} else {
return Uni.createFrom().item(Response.status(Response.Status.BAD_REQUEST).entity(ErrorMessage.PROJECT_APP_ALREADY_EXISTS).build());
}
});
} else {
return Uni.createFrom().item(Response.status(Response.Status.FORBIDDEN).entity(ErrorMessage.PROJECT_NOT_MEMBER).build());
}
});
}

@PATCH
Expand All @@ -61,9 +72,20 @@ public Uni<Response> createProjectApp(@Parameter(description = "Project ID") @Pa
content = @Content(schema = @Schema(implementation = ProjectApp.class))
)
public Uni<Response> updateProjectApp(@Parameter(description = "Project App ID") @PathParam("id") Long id, ProjectApp app) {
return ifMember(Long.parseLong(sub), app.getProjectId(), isMember ->
projectAppService.updateProjectApp(id, app.getName(), app.getDisplayName(), app.getDescription(), app.getImage())
.onItem().ifNotNull().transform(projectApp -> Response.status(Response.Status.OK).entity(projectApp).build()));
return ifMember(Long.parseLong(sub), app.getProjectId(), isMember -> {
if (isMember) {
return projectAppService.doesProjectAppExist(app.getName()).flatMap(exists -> {
if (!exists) {
return projectAppService.updateProjectApp(id, app.getName(), app.getDisplayName(), app.getDescription(), app.getImage())
.onItem().ifNotNull().transform(projectApp -> Response.status(Response.Status.OK).entity(projectApp).build());
} else {
return Uni.createFrom().item(Response.status(Response.Status.BAD_REQUEST).entity(ErrorMessage.PROJECT_APP_ALREADY_EXISTS).build());
}
});
} else {
return Uni.createFrom().item(Response.status(Response.Status.FORBIDDEN).entity(ErrorMessage.PROJECT_NOT_MEMBER).build());
}
});
}

@GET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import jakarta.inject.Inject;

import java.util.List;
import java.util.Objects;

@ApplicationScoped
public class ProjectAppService {
Expand All @@ -28,10 +29,10 @@ public class ProjectAppService {

public Uni<ProjectApp> createProjectApp(Long projectId, String name, String displayName, String description, String image, OsType os, ReleaseType releaseType) {
return projectService.findById(projectId)
.onItem().ifNull().failWith(() -> new RuntimeException("Project not found"))
.map(project -> {
String appName = project.getName() + "/" + name;
ProjectAppEntity projectApp = new ProjectAppEntity();
projectApp.setName(name);
projectApp.setName(appName);
projectApp.setDisplayName(displayName);
projectApp.setDescription(description);
projectApp.setImage(image);
Expand All @@ -46,9 +47,9 @@ public Uni<ProjectApp> createProjectApp(Long projectId, String name, String disp

public Uni<ProjectApp> updateProjectApp(Long id, String name, String displayName, String description, String image) {
return projectAppRepository.findById(id)
.onItem().ifNull().failWith(() -> new RuntimeException("Project App not found"))
.map(projectApp -> {
projectApp.setName(name);
String appName = projectApp.getProject().getName() + "/" + name;
projectApp.setName(appName);
projectApp.setDisplayName(displayName);
projectApp.setDescription(description);
projectApp.setImage(image);
Expand All @@ -66,6 +67,10 @@ public Uni<List<ProjectApp>> getProjectApps(Long projectId) {
return projectAppRepository.list("projectId", projectId).map(projectAppMapper::toDomainList);
}

public Uni<Boolean> doesProjectAppExist(String name) {
return projectAppRepository.findByName(name).map(Objects::nonNull);
}

public Uni<Boolean> deleteProjectApp(Long id) {
return projectAppRepository.deleteById(id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import dev.shiperist.entity.project.ProjectEntity;
import dev.shiperist.entity.project.ProjectMemberEntity;
import dev.shiperist.mapper.account.UserMapper;
import dev.shiperist.mapper.project.ProjectMapper;
import dev.shiperist.mapper.project.ProjectMemberMapper;
import dev.shiperist.model.project.Project;
import dev.shiperist.model.project.ProjectApp;
import dev.shiperist.model.project.ProjectMember;
import dev.shiperist.repository.account.UserRepository;
Expand Down Expand Up @@ -36,8 +38,11 @@ public abstract class BaseProjectAppResourceTest extends BaseTest {
@Inject
ProjectMemberRepository projectMemberRepository;

@Inject
ProjectMapper projectMapper;

protected ProjectApp app;
protected long projectId;
protected Project project;

@BeforeAll
public void beforeAll() throws Throwable {
Expand Down Expand Up @@ -81,7 +86,7 @@ public void beforeAll() throws Throwable {

VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() -> projectMemberRepository.persistAndFlush(projectMember)));

projectId = project.getId();
this.project = projectMapper.toDomain(project);
}

@BeforeEach
Expand Down
37 changes: 35 additions & 2 deletions server/src/test/java/dev/shiperist/app/CreateEndpointTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.shiperist.app;

import dev.shiperist.exception.ErrorMessage;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import io.quarkus.test.security.jwt.Claim;
Expand All @@ -24,13 +25,45 @@ public void testCreateApp() {
given()
.contentType(ContentType.JSON)
.body(app)
.when().put("/projects/{projectId}/apps", projectId)
.when().put("/projects/{projectId}/apps", project.getId())
.then().statusCode(201)
.body("name", equalTo(app.getName()),
.body("name", equalTo(project.getName() + "/" + app.getName()),
"displayName", equalTo(app.getDisplayName()),
"description", equalTo(app.getDescription()),
"image", equalTo(app.getImage()),
"os", equalTo(app.getOs().name()),
"releaseType", equalTo(app.getReleaseType().name()));
}

@Test
@DisplayName("PUT /projects/{projectId}/apps - create app - unauthorized")
public void testCreateAppUnauthorized() {
given()
.contentType(ContentType.JSON)
.body(app)
.when().put("/projects/{projectId}/apps", project.getId())
.then().statusCode(401);
}

@Test
@DisplayName("PUT /projects/{projectId}/apps - create app - already exists")
@TestSecurity(user = "app@test.com")
@JwtSecurity(claims = {
@Claim(key = "sub", value = "1")
})
public void testCreateAppAlreadyExists() {
given()
.contentType(ContentType.JSON)
.body(app)
.when().put("/projects/{projectId}/apps", project.getId())
.then().statusCode(201);

given()
.contentType(ContentType.JSON)
.body(app)
.when().put("/projects/{projectId}/apps", project.getId())
.then().statusCode(400)
.body("error", equalTo(ErrorMessage.PROJECT_APP_ALREADY_EXISTS.getError()),
"description", equalTo(ErrorMessage.PROJECT_APP_ALREADY_EXISTS.getDescription()));
}
}

0 comments on commit ca69d0c

Please sign in to comment.