-
Notifications
You must be signed in to change notification settings - Fork 0
Sidebar adjustments #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
8efeb8b
feat: Update role-based access for field-officers and admin routes to…
JinethBosilu 6516fb7
feat: Enhance criminal management with CRUD operations and update sec…
JinethBosilu 21f7fea
feat: Implement CRUD operations for criminal records with photo uploa…
JinethBosilu fb0fb35
Merge branch 'main' into sidebar-adjustments
JinethBosilu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
src/main/java/com/crimeLink/analyzer/controller/CriminalController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| package com.crimeLink.analyzer.controller; | ||
|
|
||
| import com.crimeLink.analyzer.service.CriminalService; | ||
| import com.crimeLink.analyzer.util.LogSanitizer; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
| import org.springframework.web.multipart.MultipartFile; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
|
|
||
| /** | ||
| * REST Controller for Criminal record management (CRUD). | ||
| * Operates directly against the database via JPA — coordinates with Python ML for embeddings. | ||
| * | ||
| * Endpoints: | ||
| * - POST /api/criminals - Create new criminal (with photo upload + embedding) | ||
| * - GET /api/criminals - List all criminals | ||
| * - GET /api/criminals/{id} - Get criminal details | ||
| * - PUT /api/criminals/{id} - Update criminal profile (with optional photo) | ||
| * - DELETE /api/criminals/{id} - Delete criminal record | ||
| */ | ||
| @RestController | ||
| @RequestMapping("/api/criminals") | ||
| @RequiredArgsConstructor | ||
| @Slf4j | ||
| public class CriminalController { | ||
|
|
||
| private final CriminalService criminalService; | ||
|
|
||
| /** | ||
| * Create a new criminal record with optional photo. | ||
| */ | ||
| @PostMapping | ||
| public ResponseEntity<?> createCriminal( | ||
| @RequestParam("name") String name, | ||
| @RequestParam("nic") String nic, | ||
| @RequestParam(value = "photo", required = false) MultipartFile photo, | ||
| @RequestParam(value = "risk_level", required = false) String riskLevel, | ||
| @RequestParam(value = "crime_history", required = false) String crimeHistory, | ||
| @RequestParam(value = "address", required = false) String address, | ||
| @RequestParam(value = "contact_number", required = false) String contactNumber, | ||
| @RequestParam(value = "secondary_contact", required = false) String secondaryContact, | ||
| @RequestParam(value = "date_of_birth", required = false) String dateOfBirth, | ||
| @RequestParam(value = "gender", required = false) String gender, | ||
| @RequestParam(value = "alias", required = false) String alias, | ||
| @RequestParam(value = "status", required = false) String status) { | ||
|
|
||
| try { | ||
| log.info("Criminal registration requested: name={}, nic={}", | ||
| LogSanitizer.sanitize(name), LogSanitizer.sanitize(nic)); | ||
|
|
||
| if (name == null || name.trim().isEmpty()) { | ||
| return ResponseEntity.badRequest().body(Map.of("error", "Name is required")); | ||
| } | ||
| if (nic == null || nic.trim().isEmpty()) { | ||
| return ResponseEntity.badRequest().body(Map.of("error", "NIC is required")); | ||
| } | ||
|
|
||
| Map<String, Object> result = criminalService.createCriminal( | ||
| name.trim(), nic.trim(), riskLevel, crimeHistory, | ||
| address, contactNumber, secondaryContact, | ||
| dateOfBirth, gender, alias, status, photo); | ||
|
|
||
| return ResponseEntity.ok(result); | ||
|
|
||
| } catch (Exception e) { | ||
| log.error("Criminal registration failed: {}", e.getMessage()); | ||
| return ResponseEntity.internalServerError() | ||
| .body(Map.of("error", "Registration failed: " + e.getMessage())); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Get all criminals (summary list). | ||
| */ | ||
| @GetMapping | ||
| public ResponseEntity<?> getAllCriminals() { | ||
| try { | ||
| List<Map<String, Object>> criminals = criminalService.getAllCriminals(); | ||
| return ResponseEntity.ok(criminals); | ||
| } catch (Exception e) { | ||
| log.error("Failed to fetch criminals: {}", e.getMessage()); | ||
| return ResponseEntity.internalServerError() | ||
| .body(Map.of("error", "Failed to fetch criminals: " + e.getMessage())); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Get full details for a specific criminal. | ||
| */ | ||
| @GetMapping("/{criminalId}") | ||
| public ResponseEntity<?> getCriminalDetails(@PathVariable String criminalId) { | ||
| try { | ||
| Optional<Map<String, Object>> result = criminalService.getCriminalDetails(criminalId); | ||
| if (result.isEmpty()) { | ||
| return ResponseEntity.status(404) | ||
| .body(Map.of("error", "Criminal not found: " + LogSanitizer.sanitize(criminalId))); | ||
| } | ||
| return ResponseEntity.ok(result.get()); | ||
| } catch (Exception e) { | ||
| log.error("Failed to fetch criminal {}: {}", LogSanitizer.sanitize(criminalId), e.getMessage()); | ||
| return ResponseEntity.internalServerError() | ||
| .body(Map.of("error", "Failed to fetch criminal details: " + e.getMessage())); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Update an existing criminal's profile data (with optional photo change). | ||
| */ | ||
| @PutMapping("/{criminalId}") | ||
| public ResponseEntity<?> updateCriminal( | ||
| @PathVariable String criminalId, | ||
| @RequestParam(value = "name", required = false) String name, | ||
| @RequestParam(value = "nic", required = false) String nic, | ||
| @RequestParam(value = "photo", required = false) MultipartFile photo, | ||
| @RequestParam(value = "risk_level", required = false) String riskLevel, | ||
| @RequestParam(value = "crime_history", required = false) String crimeHistory, | ||
| @RequestParam(value = "address", required = false) String address, | ||
| @RequestParam(value = "contact_number", required = false) String contactNumber, | ||
| @RequestParam(value = "secondary_contact", required = false) String secondaryContact, | ||
| @RequestParam(value = "date_of_birth", required = false) String dateOfBirth, | ||
| @RequestParam(value = "gender", required = false) String gender, | ||
| @RequestParam(value = "alias", required = false) String alias, | ||
| @RequestParam(value = "status", required = false) String status) { | ||
|
|
||
| try { | ||
| log.info("Criminal update requested for ID: {}", LogSanitizer.sanitize(criminalId)); | ||
|
|
||
| Optional<Map<String, Object>> result = criminalService.updateCriminal( | ||
| criminalId, name, nic, riskLevel, crimeHistory, | ||
| address, contactNumber, secondaryContact, | ||
| dateOfBirth, gender, alias, status, photo); | ||
|
|
||
| if (result.isEmpty()) { | ||
| return ResponseEntity.status(404) | ||
| .body(Map.of("error", "Criminal not found: " + LogSanitizer.sanitize(criminalId))); | ||
| } | ||
|
|
||
| Map<String, Object> response = new java.util.LinkedHashMap<>(); | ||
| response.put("message", "Criminal updated successfully"); | ||
| response.put("criminal", result.get()); | ||
| return ResponseEntity.ok(response); | ||
|
|
||
| } catch (Exception e) { | ||
| log.error("Criminal update failed for {}: {}", LogSanitizer.sanitize(criminalId), e.getMessage()); | ||
| return ResponseEntity.internalServerError() | ||
| .body(Map.of("error", "Update failed: " + e.getMessage())); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Delete a criminal record (cascades to suspect_photos, cleans up storage). | ||
| */ | ||
| @DeleteMapping("/{criminalId}") | ||
| public ResponseEntity<?> deleteCriminal(@PathVariable String criminalId) { | ||
| try { | ||
| log.info("Criminal deletion requested for ID: {}", LogSanitizer.sanitize(criminalId)); | ||
|
|
||
| boolean deleted = criminalService.deleteCriminal(criminalId); | ||
| if (!deleted) { | ||
| return ResponseEntity.status(404) | ||
| .body(Map.of("error", "Criminal not found: " + LogSanitizer.sanitize(criminalId))); | ||
| } | ||
|
|
||
| return ResponseEntity.ok(Map.of("message", "Criminal deleted successfully", "criminal_id", criminalId)); | ||
|
|
||
| } catch (Exception e) { | ||
| log.error("Criminal deletion failed for {}: {}", LogSanitizer.sanitize(criminalId), e.getMessage()); | ||
| return ResponseEntity.internalServerError() | ||
| .body(Map.of("error", "Deletion failed: " + e.getMessage())); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/api/criminals/**already matches/api/criminals, so the additional matcher for/api/criminalsis redundant and never reached. Removing the duplicate reduces confusion about which rule applies.