Skip to content

Commit fbf2696

Browse files
updated check crud operations to be user scoped
1 parent 13e333f commit fbf2696

File tree

12 files changed

+386
-128
lines changed

12 files changed

+386
-128
lines changed

builder-api/src/main/java/org/acme/constants/CollectionNames.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ public class CollectionNames {
44
public static final String SCREENER_COLLECTION = "screener";
55
public static final String DMN_MODEL_COLLECTION = "dmn_model";
66
public static final String ELIGIBILITY_CHECK_COLLECTION = "eligibilityCheck";
7+
public static final String CUSTOM_CHECK_COLLECTION = "customCheck";
78
public static final String BENEFIT_COLLECTION = "benefit";
89
}

builder-api/src/main/java/org/acme/controller/EligibilityCheckResource.java

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public Response updateCheckDmn(@Context SecurityIdentity identity, SaveDmnReques
114114
}
115115

116116
String userId = AuthUtils.getUserId(identity);
117-
Optional<EligibilityCheck> checkOpt = eligibilityCheckRepository.getCheck(checkId);
117+
Optional<EligibilityCheck> checkOpt = eligibilityCheckRepository.getCustomCheck(userId, checkId);
118118
if (checkOpt.isEmpty()){
119119
return Response.status(Response.Status.NOT_FOUND).build();
120120
}
@@ -132,7 +132,7 @@ public Response updateCheckDmn(@Context SecurityIdentity identity, SaveDmnReques
132132
.build();
133133
}
134134
try {
135-
String filePath = storageService.getCheckDmnModelPath(check.getModule(), check.getId(), check.getVersion());
135+
String filePath = storageService.getCheckDmnModelPath(userId, check.getModule(), check.getId(), check.getVersion());
136136
storageService.writeStringToStorage(filePath, dmnModel, "application/xml");
137137
Log.info("Saved DMN model of check " + checkId + " to storage");
138138

@@ -145,4 +145,80 @@ public Response updateCheckDmn(@Context SecurityIdentity identity, SaveDmnReques
145145
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
146146
}
147147
}
148+
149+
@GET
150+
@Path("/account/check")
151+
public Response getCustomChecks(@Context SecurityIdentity identity) {
152+
String userId = AuthUtils.getUserId(identity);
153+
if (userId == null) {
154+
return Response.status(Response.Status.UNAUTHORIZED).build();
155+
}
156+
157+
Log.info("Fetching all eligibility checks. User: " + userId);
158+
List<EligibilityCheck> checks = eligibilityCheckRepository.getCustomChecks(userId);
159+
160+
return Response.ok(checks, MediaType.APPLICATION_JSON).build();
161+
}
162+
163+
@GET
164+
@Path("/account/check/{checkId}")
165+
public Response getCustomCheck(@Context SecurityIdentity identity) {
166+
String userId = AuthUtils.getUserId(identity);
167+
if (userId == null) {
168+
return Response.status(Response.Status.UNAUTHORIZED).build();
169+
}
170+
171+
Log.info("Fetching all eligibility checks. User: " + userId);
172+
Optional<EligibilityCheck> checkOpt = eligibilityCheckRepository.getCustomCheck(userId, userId);
173+
174+
175+
if (checkOpt.isEmpty()){
176+
return Response.status(Response.Status.NOT_FOUND).build();
177+
}
178+
179+
EligibilityCheck check = checkOpt.get();
180+
181+
if (!check.getPublic() && !check.getOwnerId().equals(userId)){
182+
return Response.status(Response.Status.UNAUTHORIZED).build();
183+
}
184+
return Response.ok(check, MediaType.APPLICATION_JSON).build();
185+
}
186+
187+
@POST
188+
@Path("/account/check")
189+
public Response createCustomCheck(@Context SecurityIdentity identity,
190+
EligibilityCheck newCheck) {
191+
String userId = AuthUtils.getUserId(identity);
192+
193+
//TODO: Add validations for user provided data
194+
newCheck.setOwnerId(userId);
195+
newCheck.setPublic(false);
196+
newCheck.setVersion("1");
197+
try {
198+
String checkId = eligibilityCheckRepository.saveNewCustomCheck(newCheck);
199+
newCheck.setId(checkId);
200+
return Response.ok(newCheck, MediaType.APPLICATION_JSON).build();
201+
} catch (Exception e){
202+
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
203+
.entity(Map.of("error", "Could not save Check"))
204+
.build();
205+
}
206+
}
207+
208+
@PUT
209+
@Path("/account/check")
210+
public Response updateCustomCheck(@Context SecurityIdentity identity,
211+
EligibilityCheck updateCheck){
212+
String userId = AuthUtils.getUserId(identity);
213+
214+
// TODO: Add authorization to update check
215+
try {
216+
eligibilityCheckRepository.updateCustomCheck(updateCheck);
217+
return Response.ok().entity(updateCheck).build();
218+
} catch (Exception e){
219+
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
220+
.entity(Map.of("error", "could not update Check"))
221+
.build();
222+
}
223+
}
148224
}

builder-api/src/main/java/org/acme/persistence/EligibilityCheckRepository.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ public interface EligibilityCheckRepository {
1414

1515
List<EligibilityCheck> getChecksInBenefit(Benefit benefit);
1616

17+
List<EligibilityCheck> getCustomChecks(String userId);
18+
19+
Optional<EligibilityCheck> getCustomCheck(String userId, String checkId);
20+
1721
String saveNewCheck(EligibilityCheck check) throws Exception;
1822

23+
String saveNewCustomCheck(EligibilityCheck check) throws Exception;
24+
1925
void updateCheck(EligibilityCheck check) throws Exception;
26+
27+
void updateCustomCheck(EligibilityCheck check) throws Exception;
2028
}

builder-api/src/main/java/org/acme/persistence/EligibilityCheckRepositoryImpl.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ public Optional<EligibilityCheck> getCheck(String checkId){
4343

4444
ObjectMapper mapper = new ObjectMapper();
4545
EligibilityCheck check = mapper.convertValue(data, EligibilityCheck.class);
46-
47-
String dmnPath = storageService.getCheckDmnModelPath(check.getModule(), checkId, check.getVersion());
48-
Optional<String> dmnModel = storageService.getStringFromStorage(dmnPath);
49-
dmnModel.ifPresent(check::setDmnModel);
50-
5146
return Optional.of(check);
5247
}
5348

@@ -72,4 +67,41 @@ public void updateCheck(EligibilityCheck check) throws Exception{
7267
Map<String, Object> data = mapper.convertValue(check, Map.class);
7368
FirestoreUtils.updateDocument(CollectionNames.ELIGIBILITY_CHECK_COLLECTION, data, check.getId());
7469
}
70+
71+
public List<EligibilityCheck> getCustomChecks(String userId){
72+
List<Map<String, Object>> checkMaps = FirestoreUtils.getFirestoreDocsByField(CollectionNames.CUSTOM_CHECK_COLLECTION, FieldNames.OWNER_ID, userId);
73+
ObjectMapper mapper = new ObjectMapper();
74+
return checkMaps.stream().map(checkMap -> mapper.convertValue(checkMap, EligibilityCheck.class)).toList();
75+
}
76+
77+
public Optional<EligibilityCheck> getCustomCheck(String userId, String checkId){
78+
79+
List<Map<String, Object>> checkMaps = FirestoreUtils.getFirestoreDocsByField(CollectionNames.CUSTOM_CHECK_COLLECTION, FieldNames.ID, checkId);
80+
if (checkMaps.isEmpty()){
81+
return Optional.empty();
82+
}
83+
Map<String, Object> data = checkMaps.getFirst();
84+
85+
ObjectMapper mapper = new ObjectMapper();
86+
EligibilityCheck check = mapper.convertValue(data, EligibilityCheck.class);
87+
88+
String dmnPath = storageService.getCheckDmnModelPath(userId, check.getModule(), checkId, check.getVersion());
89+
Optional<String> dmnModel = storageService.getStringFromStorage(dmnPath);
90+
dmnModel.ifPresent(check::setDmnModel);
91+
92+
return Optional.of(check);
93+
}
94+
95+
public String saveNewCustomCheck(EligibilityCheck check) throws Exception{
96+
ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
97+
Map<String, Object> data = mapper.convertValue(check, Map.class);
98+
String checkDocId = check.getId();
99+
return FirestoreUtils.persistDocumentWithId(CollectionNames.CUSTOM_CHECK_COLLECTION, checkDocId, data);
100+
}
101+
102+
public void updateCustomCheck(EligibilityCheck check) throws Exception{
103+
ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
104+
Map<String, Object> data = mapper.convertValue(check, Map.class);
105+
FirestoreUtils.updateDocument(CollectionNames.CUSTOM_CHECK_COLLECTION, data, check.getId());
106+
}
75107
}

builder-api/src/main/java/org/acme/persistence/GoogleStorageService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ public String getScreenerPublishedFormSchemaPath(String screenerId){
140140
}
141141

142142
@Override
143-
public String getCheckDmnModelPath(String module, String checkId, String version){
144-
return "check/" + module + "/" + checkId + "/" + version + "/" + checkId + ".dmn";
143+
public String getCheckDmnModelPath(String userId, String module, String checkId, String version){
144+
return "check/" + userId + "/" + module + "/" + checkId + "/" + version + "/" + checkId + ".dmn";
145145
}
146146

147147
@Override

builder-api/src/main/java/org/acme/persistence/StorageService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public interface StorageService {
2323

2424
String getScreenerPublishedFormSchemaPath(String screenerId);
2525

26-
String getCheckDmnModelPath(String module, String checkId, String version);
26+
String getCheckDmnModelPath(String userId, String module, String checkId, String version);
2727

2828
Map<String, Object> getFormSchemaFromStorage(String filePath);
2929

builder-frontend/src/api/check.ts

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { EligibilityCheck } from "@/types";
44

55
const apiUrl = import.meta.env.VITE_API_URL;
66

7-
87
export const fetchPublicChecks = async (): Promise<EligibilityCheck[]> => {
98
const url = apiUrl + "/check";
109
try {
@@ -26,7 +25,9 @@ export const fetchPublicChecks = async (): Promise<EligibilityCheck[]> => {
2625
}
2726
};
2827

29-
export const fetchCheck = async (checkId: string): Promise<EligibilityCheck> => {
28+
export const fetchCheck = async (
29+
checkId: string
30+
): Promise<EligibilityCheck> => {
3031
const url = apiUrl + `/check/${checkId}`;
3132
try {
3233
const response = await authFetch(url, {
@@ -48,9 +49,32 @@ export const fetchCheck = async (checkId: string): Promise<EligibilityCheck> =>
4849
}
4950
};
5051

52+
export const fetchCustomCheck = async (
53+
checkId: string
54+
): Promise<EligibilityCheck> => {
55+
const url = apiUrl + `/account/check/${checkId}`;
56+
try {
57+
const response = await authFetch(url, {
58+
method: "GET",
59+
headers: {
60+
Accept: "application/json",
61+
},
62+
});
63+
64+
if (!response.ok) {
65+
throw new Error(`Fetch failed with status: ${response.status}`);
66+
}
67+
const data = await response.json();
68+
console.log("Fetched custom check:", data);
69+
return data;
70+
} catch (error) {
71+
console.error("Error fetching custom check:", error);
72+
throw error; // rethrow so you can handle it in your component if needed
73+
}
74+
};
5175

5276
export const addCheck = async (check: EligibilityCheck) => {
53-
const url = apiUrl + "/check";
77+
const url = apiUrl + "/account/check";
5478
try {
5579
const response = await authFetch(url, {
5680
method: "POST",
@@ -73,7 +97,7 @@ export const addCheck = async (check: EligibilityCheck) => {
7397
};
7498

7599
export const updateCheck = async (check: EligibilityCheck) => {
76-
const url = apiUrl + "/check";
100+
const url = apiUrl + "/account/check";
77101
try {
78102
const response = await authFetch(url, {
79103
method: "PUT",
@@ -119,8 +143,22 @@ export const saveCheckDmn = async (checkId: string, dmnModel: string) => {
119143
};
120144

121145
export const fetchUserDefinedChecks = async (): Promise<EligibilityCheck[]> => {
122-
// Simulate an API call delay -- TODO: update to greater than 1ms delay
123-
await new Promise((resolve) => setTimeout(resolve, 1000));
146+
const url = apiUrl + "/account/check";
147+
try {
148+
const response = await authFetch(url, {
149+
method: "GET",
150+
headers: {
151+
Accept: "application/json",
152+
},
153+
});
124154

125-
return [];
155+
if (!response.ok) {
156+
throw new Error(`Fetch failed with status: ${response.status}`);
157+
}
158+
const data = await response.json();
159+
return data;
160+
} catch (error) {
161+
console.error("Error fetching checks:", error);
162+
throw error; // rethrow so you can handle it in your component if needed
163+
}
126164
};

0 commit comments

Comments
 (0)