Skip to content

Commit

Permalink
More Rollback of #27 (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
pilhuhn committed Oct 2, 2020
1 parent 2b2d233 commit 1387e07
Show file tree
Hide file tree
Showing 6 changed files with 776 additions and 0 deletions.
91 changes: 91 additions & 0 deletions src/main/java/com/redhat/cloud/notifications/oapi/OASModifier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.redhat.cloud.notifications.oapi;

import org.eclipse.microprofile.openapi.OASFilter;
import org.eclipse.microprofile.openapi.models.Components;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import org.eclipse.microprofile.openapi.models.Operation;
import org.eclipse.microprofile.openapi.models.PathItem;
import org.eclipse.microprofile.openapi.models.Paths;
import org.eclipse.microprofile.openapi.models.media.Schema;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* Modify the path in the openapi document to not
* have the prefix, which is already in the
* servers part of the document. See POL-358
* This also allows to do more filtering and
* rewriting of the document.
*
* Also provides an operationId for all operations.
*/
public class OASModifier implements OASFilter {

@Override
public void filterOpenAPI(OpenAPI openAPI) {
Paths paths = openAPI.getPaths();
Set<String> keySet = paths.getPathItems().keySet();
Map<String, PathItem> replacementItems = new HashMap<>();
for (String key : keySet) {
PathItem p = paths.getPathItem(key);
String mangledName = mangleName(key);
replacementItems.put(mangledName, p);

Map<PathItem.HttpMethod, Operation> operations = p.getOperations();
for (Map.Entry<PathItem.HttpMethod, Operation> entry : operations.entrySet()) {
Operation op = entry.getValue();

if (op.getOperationId() == null || op.getOperationId().isEmpty()) {

String id = toCamelCase(mangledName);
id = entry.getKey().toString().toLowerCase() + id;
op.setOperationId(id);
}
}
}
paths.setPathItems(replacementItems);

// Settings values should not be shown in openapi export
Components components = openAPI.getComponents();
Map<String, Schema> existingSchemas = components.getSchemas();
Map<String, Schema> modifiedSchemas = new HashMap<>(existingSchemas);
// TODO Add modifications here
components.setSchemas(modifiedSchemas);
}

private String toCamelCase(String mangledName) {
StringBuilder sb = new StringBuilder();
boolean needsUpper = false;
for (char c : mangledName.toCharArray()) {
if (c == '/') {
needsUpper = true;
continue;
}
if (c == '}') {
continue;
}
if (c == '{') {
sb.append("By");
needsUpper = true;
continue;
}
if (needsUpper) {
sb.append(Character.toUpperCase(c));
needsUpper = false;
} else {
sb.append(c);
}
}
return sb.toString();
}

private String mangleName(String key) {
// Base Filler - would report as empty otherwise
if (key.equals("/api/notifications/v1.0")) {
return "/";
}
return key.replace("/api/notifications/v1.0", "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package com.redhat.cloud.notifications.routers;

import com.redhat.cloud.notifications.auth.RhIdPrincipal;
import com.redhat.cloud.notifications.db.EndpointResources;
import com.redhat.cloud.notifications.db.NotificationResources;
import com.redhat.cloud.notifications.models.Endpoint;
import com.redhat.cloud.notifications.models.NotificationHistory;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import org.eclipse.microprofile.openapi.annotations.enums.ParameterIn;
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameters;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;

import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import java.util.UUID;

@Path("/endpoints")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
// Email endpoints are not added at this point
// TODO Needs documentation annotations
public class EndpointService {

@Inject
EndpointResources resources;

@Inject
NotificationResources notifResources;

@GET
@RolesAllowed("read")
@Parameters({
@Parameter(
name = "pageSize",
in = ParameterIn.QUERY,
description = "Number of items per page, if not specified or 0 is used, returns all elements",
schema = @Schema(type = SchemaType.INTEGER)
),
@Parameter(
name = "pageNumber",
in = ParameterIn.QUERY,
description = "Page number. Starts at first page (0), if not specified starts at first page.",
schema = @Schema(type = SchemaType.INTEGER)
)
})
public Multi<Endpoint> getEndpoints(@Context SecurityContext sec, @Context UriInfo uriInfo) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
return resources.getEndpoints(principal.getAccount(), ParamUtils.parseQueryParams(uriInfo));
}

@POST
@RolesAllowed("write")
public Uni<Endpoint> createEndpoint(@Context SecurityContext sec, @NotNull @Valid Endpoint endpoint) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
endpoint.setTenant(principal.getAccount());
return resources.createEndpoint(endpoint);
}

@GET
@Path("/{id}")
@RolesAllowed("read")
public Uni<Endpoint> getEndpoint(@Context SecurityContext sec, @PathParam("id") UUID id) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
return resources.getEndpoint(principal.getAccount(), id)
.onItem().ifNull().failWith(new NotFoundException());
}

@DELETE
@Path("/{id}")
@RolesAllowed("write")
@APIResponse(responseCode = "200", content = @Content(schema = @Schema(type = SchemaType.STRING)))
public Uni<Response> deleteEndpoint(@Context SecurityContext sec, @PathParam("id") UUID id) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
return resources.deleteEndpoint(principal.getAccount(), id)
// onFailure() ?
.onItem().transform(ignored -> Response.ok().build());
}

@PUT
@Path("/{id}/enable")
@RolesAllowed("write")
@APIResponse(responseCode = "200", content = @Content(schema = @Schema(type = SchemaType.STRING)))
public Uni<Response> enableEndpoint(@Context SecurityContext sec, @PathParam("id") UUID id) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
return resources.enableEndpoint(principal.getAccount(), id)
.onItem().transform(ignored -> Response.ok().build());
}

@DELETE
@Path("/{id}/enable")
@RolesAllowed("write")
@APIResponse(responseCode = "200", content = @Content(schema = @Schema(type = SchemaType.STRING)))
public Uni<Response> disableEndpoint(@Context SecurityContext sec, @PathParam("id") UUID id) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
return resources.disableEndpoint(principal.getAccount(), id)
.onItem().transform(ignored -> Response.ok().build());
}

@PUT
@Path("/{id}")
@RolesAllowed("write")
@APIResponse(responseCode = "200", content = @Content(schema = @Schema(type = SchemaType.STRING)))
public Uni<Response> updateEndpoint(@Context SecurityContext sec, @PathParam("id") UUID id, @NotNull @Valid Endpoint endpoint) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
endpoint.setTenant(principal.getAccount());
endpoint.setId(id);
return resources.updateEndpoint(endpoint)
.onItem().transform(ignored -> Response.ok().build());
}

@GET
@Path("/{id}/history")
@RolesAllowed("read")
public Multi<NotificationHistory> getEndpointHistory(@Context SecurityContext sec, @PathParam("id") UUID id) {
// TODO We need globally limitations (Paging support and limits etc)
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
return notifResources.getNotificationHistory(principal.getAccount(), id);
}

@GET
@Path("/{id}/history/{history_id}/details")
@RolesAllowed("read")
@Parameters({
@Parameter(
name = "pageSize",
in = ParameterIn.QUERY,
description = "Number of items per page, if not specified or 0 is used, returns all elements",
schema = @Schema(type = SchemaType.INTEGER)
),
@Parameter(
name = "pageNumber",
in = ParameterIn.QUERY,
description = "Page number. Starts at first page (0), if not specified starts at first page.",
schema = @Schema(type = SchemaType.INTEGER)
)
})
@APIResponse(responseCode = "200", content = @Content(schema = @Schema(type = SchemaType.STRING)))
public Uni<Response> getDetailedEndpointHistory(@Context SecurityContext sec, @PathParam("id") UUID id, @PathParam("history_id") Integer historyId, @Context UriInfo uriInfo) {
RhIdPrincipal principal = (RhIdPrincipal) sec.getUserPrincipal();
return notifResources.getNotificationDetails(principal.getAccount(), ParamUtils.parseQueryParams(uriInfo), id, historyId)
// Maybe 404 should only be returned if history_id matches nothing? Otherwise 204
.onItem().ifNull().failWith(new NotFoundException())
.onItem().transform(json -> {
if (json.isEmpty()) {
return Response.noContent().build();
}
return Response.ok(json).build();
});
}
}
31 changes: 31 additions & 0 deletions src/main/resources/META-INF/openapi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"openapi": "3.0.3",
"info" : {
"description": "The API for Notifications",
"version": "1.0",
"title": "Notifications"
},
"servers": [
{
"url": "https://cloud.redhat.com",
"description": "Production Server",
"variables": {
"basePath": {
"default": "/api/notifications/v1.0"
}
}
},
{
"url": "http://localhost:{port}",
"description": "Development Server",
"variables": {
"port": {
"default": "8080"
},
"basePath": {
"default": "/api/notifications/v1.0"
}
}
}
]
}
2 changes: 2 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ quarkus.smallrye-openapi.path=/openapi.json
mp.openapi.filter=com.redhat.cloud.notifications.oapi.OASModifier

quarkus.http.root-path=/api/notifications/v1.0
quarkus.http.access-log.enabled=true
quarkus.http.access-log.category=info

# Reactive config

Expand Down

0 comments on commit 1387e07

Please sign in to comment.