Skip to content

Commit 846047f

Browse files
authored
Merge pull request #363 from CodeForPhilly/feat/account-creation-hook
Feat/account creation hook
2 parents 4b1e9c1 + 360f47b commit 846047f

File tree

10 files changed

+646
-17
lines changed

10 files changed

+646
-17
lines changed

builder-api/src/main/java/org/acme/api/error/JsonServerExceptionMappers.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,29 @@ public class JsonServerExceptionMappers {
1515
public Response map(MismatchedInputException e) {
1616
Log.warn(e);
1717
// e.g. screenerName is object but DTO expects String
18-
String field =
19-
e.getPath() != null && !e.getPath().isEmpty()
20-
? e.getPath().get(e.getPath().size() - 1).getFieldName()
21-
: "request body";
18+
String field = e.getPath() != null && !e.getPath().isEmpty()
19+
? e.getPath().get(e.getPath().size() - 1).getFieldName()
20+
: "request body";
2221

2322
return Response.status(Response.Status.BAD_REQUEST)
2423
.type(MediaType.APPLICATION_JSON)
25-
.entity(ApiError.of("Invalid type for field '" + field + "'."))
26-
.build();
24+
.entity(ApiError.of("Invalid type for field '" + field + "'.")).build();
2725
}
2826

2927
@ServerExceptionMapper
3028
public Response map(JsonParseException e) {
3129
Log.warn(e);
3230
// malformed JSON like { "schema": }
3331
return Response.status(Response.Status.BAD_REQUEST)
34-
.type(MediaType.APPLICATION_JSON)
35-
.entity(ApiError.of("Malformed JSON."))
32+
.type(MediaType.APPLICATION_JSON).entity(ApiError.of("Malformed JSON."))
3633
.build();
3734
}
3835

3936
@ServerExceptionMapper
4037
public Response map(WebApplicationException e) {
4138
Log.warn(e);
4239
return Response.status(Response.Status.BAD_REQUEST)
43-
.type(MediaType.APPLICATION_JSON)
44-
.entity(ApiError.of("Malformed JSON."))
40+
.type(MediaType.APPLICATION_JSON).entity(ApiError.of("Malformed JSON."))
4541
.build();
4642
}
4743

@@ -51,7 +47,6 @@ public Response map(JsonMappingException e) {
5147
// other mapping errors
5248
return Response.status(Response.Status.BAD_REQUEST)
5349
.type(MediaType.APPLICATION_JSON)
54-
.entity(ApiError.of("Invalid request body."))
55-
.build();
50+
.entity(ApiError.of("Invalid request body.")).build();
5651
}
5752
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.acme.controller;
2+
3+
import io.quarkus.security.identity.SecurityIdentity;
4+
import jakarta.inject.Inject;
5+
import jakarta.ws.rs.*;
6+
import jakarta.ws.rs.core.*;
7+
8+
import java.util.Map;
9+
import java.util.Set;
10+
import java.util.function.Predicate;
11+
import java.util.stream.Collectors;
12+
13+
import org.acme.api.error.ApiError;
14+
import org.acme.auth.AuthUtils;
15+
import org.acme.enums.AccountHookAction;
16+
import org.acme.functions.AccountHooks;
17+
import org.acme.model.dto.Auth.AccountHookRequest;
18+
import org.acme.model.dto.Auth.AccountHookResponse;
19+
20+
@Path("/api")
21+
public class AccountResource {
22+
23+
@Inject
24+
AccountHooks accountHooks;
25+
26+
@POST
27+
@Consumes(MediaType.APPLICATION_JSON)
28+
@Produces(MediaType.APPLICATION_JSON)
29+
@Path("/account-hooks")
30+
public Response accountHooks(@Context SecurityIdentity identity,
31+
AccountHookRequest request) {
32+
33+
Set<AccountHookAction> hooks = request.hooks();
34+
String userId = AuthUtils.getUserId(identity);
35+
36+
if (userId == null) {
37+
return Response.status(Response.Status.UNAUTHORIZED)
38+
.entity(new ApiError(true, "Unauthorized.")).build();
39+
}
40+
41+
// Map of AccountHookAction to a hook side-effect function
42+
// The function returns whether the side-effect was successful
43+
Map<AccountHookAction, Predicate<String>> hooksMap = Map.of(
44+
AccountHookAction.ADD_EXAMPLE_SCREENER,
45+
accountHooks::addExampleScreenerToAccount,
46+
AccountHookAction.UNABLE_TO_DETERMINE,
47+
(String uId) -> true);
48+
49+
// Run each action's function and determine whether successful
50+
Map<String, Boolean> hookResults = hooks.stream()
51+
.collect(Collectors.toMap(s -> s.getLabel(), s -> {
52+
Predicate<String> fn = hooksMap.get(s);
53+
return fn.test(userId);
54+
}));
55+
56+
Boolean allHooksSuccess = hookResults.values().stream()
57+
.allMatch(Boolean::booleanValue);
58+
59+
AccountHookResponse responseBody = new AccountHookResponse(
60+
allHooksSuccess, hookResults);
61+
62+
return Response.ok(responseBody).build();
63+
}
64+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.acme.enums;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonValue;
5+
6+
public enum AccountHookAction {
7+
ADD_EXAMPLE_SCREENER("add example screener"),
8+
UNABLE_TO_DETERMINE("UNABLE_TO_DETERMINE");
9+
10+
private final String label;
11+
12+
AccountHookAction(String label) {
13+
this.label = label;
14+
}
15+
16+
@JsonValue
17+
public String getLabel() {
18+
return label;
19+
}
20+
21+
@JsonCreator
22+
public static AccountHookAction fromValue(String value) {
23+
for (AccountHookAction action : values()) {
24+
if (action.label.equalsIgnoreCase(value)) {
25+
return action;
26+
}
27+
}
28+
return UNABLE_TO_DETERMINE;
29+
}
30+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.acme.functions;
2+
3+
import io.quarkus.logging.Log;
4+
import jakarta.enterprise.context.ApplicationScoped;
5+
import jakarta.inject.Inject;
6+
7+
import org.acme.service.ExampleScreenerImportService;
8+
9+
@ApplicationScoped
10+
public class AccountHooks {
11+
@Inject
12+
ExampleScreenerImportService exampleScreenerImportService;
13+
14+
public Boolean addExampleScreenerToAccount(String userId) {
15+
try {
16+
Log.info("Running ADD_EXAMPLE_SCREENER hook for user: " + userId);
17+
String screenerId = exampleScreenerImportService.importForUser(userId);
18+
Log.info("Imported example screener " + screenerId + " for user " + userId);
19+
return true;
20+
} catch (Exception e) {
21+
Log.error(
22+
"Failed to run ADD_EXAMPLE_SCREENER hook for user: "
23+
+ userId,
24+
e);
25+
return false;
26+
}
27+
}
28+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.acme.model.dto.Auth;
2+
3+
import java.util.Set;
4+
5+
import org.acme.enums.AccountHookAction;
6+
7+
public record AccountHookRequest(Set<AccountHookAction> hooks) {
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.acme.model.dto.Auth;
2+
3+
import java.util.Map;
4+
5+
public record AccountHookResponse(Boolean success,
6+
Map<String, Boolean> actions) {
7+
};

0 commit comments

Comments
 (0)