package sola.identity.boundary; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.*; import sola.identity.control.Access; import sola.identity.Requirement; import static sola.identity.Requirement.Rn.*; import sola.cell.boundary.Bearer; import java.util.Map; @Path("/") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @jakarta.enterprise.context.ApplicationScoped public class IdentityResource { @Inject Access access; public record Login(String label) {} public record Redemption(String challengeId) {} public record Proof(String subject, String proofId, Boolean approved) {} @POST @Path("api/auth/challenges") @Requirement({R5_2, R5_3}) public Map challenge(@HeaderParam("Authorization") String header, Login request) throws Exception { return access.challenge(Bearer.token(header), request == null ? null : request.label()); } @GET @Path("api/auth/challenges/pending") public Map pending(@HeaderParam("Authorization") String header) throws Exception { return Map.of("challenges", access.pending(Bearer.token(header))); } @POST @Path("api/auth/challenges/{id}/proof") @Requirement({R6_3, R6_4}) public void prove(@HeaderParam("Authorization") String header, @PathParam("id") String id, Proof proof) throws Exception { if (proof == null) throw new BadRequestException(); access.prove(Bearer.token(header), id, proof.subject(), proof.proofId(), proof.approved()); } @POST @Path("api/auth/token") @Requirement({R6_1, R6_2, R6_3, R6_5}) public Response redeem(@HeaderParam("Authorization") String header, Redemption request) throws Exception { var result = access.redeem(request == null ? null : request.challengeId(), Bearer.token(header)); return Response.status(result.containsKey("accessToken") ? 200 : 202).entity(result).build(); } @GET @Path("api/me") @Requirement({R5_1}) public Map owner(@HeaderParam("Authorization") String header) throws Exception { return Map.of("owner", access.requireOwner(Bearer.token(header)), "role", "owner"); } @POST @Path("auth/logout") @Consumes("*/*") @Requirement({R7_1}) public void logout(@HeaderParam("Authorization") String header) throws Exception { access.revoke(Bearer.token(header)); } }