Skip to content

Commit 56b36cf

Browse files
authored
Merge branch 'main' into isira
2 parents 1c718f2 + 9f62b90 commit 56b36cf

16 files changed

Lines changed: 470 additions & 16 deletions

.github/dependabot.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
version: 2
2+
3+
updates:
4+
# Maven / Spring Boot dependencies
5+
- package-ecosystem: "maven"
6+
directory: "/"
7+
schedule:
8+
interval: "weekly"
9+
day: "sunday"
10+
time: "09:00"
11+
open-pull-requests-limit: 10
12+
rebase-strategy: "auto"
13+
14+
# Group updates to reduce noise in dev
15+
groups:
16+
spring:
17+
patterns:
18+
- "org.springframework*"
19+
- "org.springframework.boot*"
20+
testing:
21+
patterns:
22+
- "org.junit*"
23+
- "org.mockito*"
24+
- "org.assertj*"
25+
- "org.testcontainers*"
26+
build-plugins:
27+
patterns:
28+
- "org.apache.maven.plugins*"
29+
- "io.spring.javaformat*"
30+
- "com.diffplug.spotless*"
31+
- "org.sonarsource.scanner.maven*"
32+
misc:
33+
patterns:
34+
- "*"
35+
36+
# Avoid risky breaking changes automatically (you upgrade these intentionally)
37+
ignore:
38+
- dependency-name: "org.springframework.boot"
39+
update-types: ["version-update:semver-major"]
40+
- dependency-name: "org.springframework"
41+
update-types: ["version-update:semver-major"]
42+
- dependency-name: "org.springframework.security"
43+
update-types: ["version-update:semver-major"]
44+
- dependency-name: "org.hibernate.orm"
45+
update-types: ["version-update:semver-major"]
46+
47+
# GitHub Actions used in workflows
48+
- package-ecosystem: "github-actions"
49+
directory: "/"
50+
schedule:
51+
interval: "weekly"
52+
day: "sunday"
53+
time: "09:00"
54+
open-pull-requests-limit: 5
55+
rebase-strategy: "auto"

.github/workflows/codeql.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: "CodeQL"
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
schedule:
9+
- cron: "33 19 * * 4"
10+
11+
jobs:
12+
analyze:
13+
name: Analyze (Java 21)
14+
runs-on: ubuntu-latest
15+
16+
permissions:
17+
security-events: write
18+
actions: read
19+
contents: read
20+
packages: read
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v6
25+
26+
- name: Set up JDK 21
27+
uses: actions/setup-java@v5
28+
with:
29+
distribution: temurin
30+
java-version: "21"
31+
cache: maven
32+
33+
- name: Initialize CodeQL
34+
uses: github/codeql-action/init@v4
35+
with:
36+
languages: java-kotlin
37+
build-mode: manual
38+
queries: security-extended,security-and-quality
39+
40+
# Maven (Spring Initializr usually uses Maven)
41+
- name: Build with Maven
42+
if: hashFiles('pom.xml') != ''
43+
run: |
44+
chmod +x mvnw || true
45+
./mvnw -B -DskipTests clean package || mvn -B -DskipTests clean package
46+
47+
# Gradle (only runs if Gradle files exist)
48+
- name: Build with Gradle
49+
if: hashFiles('build.gradle', 'build.gradle.kts') != ''
50+
run: |
51+
chmod +x gradlew || true
52+
./gradlew build -x test
53+
54+
- name: Perform CodeQL Analysis
55+
uses: github/codeql-action/analyze@v4
56+
with:
57+
category: "/language:java-kotlin"

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@
6969
<version>0.12.5</version>
7070
</dependency>
7171

72+
<dependency>
73+
<groupId>org.springframework.boot</groupId>
74+
<artifactId>spring-boot-starter-validation</artifactId>
75+
</dependency>
76+
7277
<dependency>
7378
<groupId>io.jsonwebtoken</groupId>
7479
<artifactId>jjwt-impl</artifactId>
@@ -114,6 +119,8 @@
114119
<version>1.3.40</version>
115120
</dependency>
116121

122+
123+
117124
</dependencies>
118125

119126
<build>

src/main/java/com/crimeLink/analyzer/config/JwtAuthenticationFilter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ protected void doFilterInternal(
4646
|| path.startsWith("/api/auth/refresh")
4747
|| path.startsWith("/api/mobile/auth/login")
4848
|| path.startsWith("/api/health")
49-
|| path.startsWith("/api/duties")) { // ✅ IMPORTANT
49+
|| path.startsWith("/api/duties")
50+
|| path.startsWith("/api/leaves")){
5051
filterChain.doFilter(request, response);
5152
return;
5253
}
@@ -94,4 +95,4 @@ protected void doFilterInternal(
9495

9596
filterChain.doFilter(request, response);
9697
}
97-
}
98+
}

src/main/java/com/crimeLink/analyzer/config/SecurityConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
5959
// Field Officer routes
6060
.requestMatchers("/api/officers/me/**").hasRole("FieldOfficer")
6161
.requestMatchers("/api/mobile/**").hasRole("FieldOfficer")
62+
.requestMatchers("/api/leaves/**").permitAll()
6263

6364
// OIC-only routes
6465
.requestMatchers("/api/duty-schedules/**").hasRole("OIC")
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.crimeLink.analyzer.controller;
2+
3+
import com.crimeLink.analyzer.dto.*;
4+
import com.crimeLink.analyzer.service.LeaveService;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.http.ResponseEntity;
7+
import org.springframework.web.bind.annotation.*;
8+
import jakarta.validation.Valid;
9+
import java.util.List;
10+
11+
@RestController
12+
@RequestMapping("/api/leaves")
13+
@RequiredArgsConstructor
14+
@CrossOrigin(origins = "*", allowedHeaders = "*")
15+
public class LeaveController {
16+
17+
private final LeaveService leaveService;
18+
19+
@PostMapping("/request")
20+
public ResponseEntity<LeaveRequestDTO> submitLeaveRequest(
21+
@Valid @RequestBody LeaveSubmitRequest request) {
22+
LeaveRequestDTO result = leaveService.submitLeaveRequest(request);
23+
return ResponseEntity.ok(result);
24+
}
25+
26+
@GetMapping("/officer/{officerId}")
27+
public ResponseEntity<List<LeaveRequestDTO>> getOfficerLeaves(
28+
@PathVariable Long officerId) {
29+
List<LeaveRequestDTO> leaves = leaveService.getOfficerLeaves(officerId);
30+
return ResponseEntity.ok(leaves);
31+
}
32+
33+
@GetMapping("/all")
34+
public ResponseEntity<List<LeaveRequestDTO>> getAllLeaveRequests(
35+
@RequestParam String month) {
36+
List<LeaveRequestDTO> leaves = leaveService.getAllLeaveRequests(month);
37+
return ResponseEntity.ok(leaves);
38+
}
39+
40+
@PutMapping("/{leaveId}/status")
41+
public ResponseEntity<LeaveRequestDTO> updateLeaveStatus(
42+
@PathVariable Long leaveId,
43+
@Valid @RequestBody LeaveUpdateRequest request,
44+
@RequestHeader(value = "X-User-Id", required = false) Long userId) {
45+
Long respondedBy = userId != null ? userId : 1L;
46+
LeaveRequestDTO result = leaveService.updateLeaveStatus(leaveId, request, respondedBy);
47+
return ResponseEntity.ok(result);
48+
}
49+
}

src/main/java/com/crimeLink/analyzer/controller/MobileDutyController.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
import java.time.LocalDate;
1212
import java.util.List;
1313

14-
/**
15-
* REST Controller for Mobile App
16-
* CORS FIXED VERSION - No more 403 errors
17-
*/
14+
1815
@RestController
1916
@RequestMapping("/api/duties")
2017
@RequiredArgsConstructor
@@ -29,21 +26,20 @@ public class MobileDutyController {
2926
private final MobileDutyService mobileDutyService;
3027

3128
/**
32-
* GET /api/duties/officer/{officerId}
3329
* Get all duties for a specific officer
3430
*/
3531
@GetMapping("/officer/{officerId}")
3632
public ResponseEntity<List<DutyAssignmentDTO>> getDutiesByOfficer(
3733
@PathVariable Long officerId) {
3834

39-
System.out.println("📱 Mobile API Request: GET /officer/" + officerId);
35+
System.out.println(" Mobile API Request: GET /officer/" + officerId);
4036

4137
try {
4238
List<DutyAssignmentDTO> duties = mobileDutyService.getDutiesByOfficerId(officerId);
43-
System.out.println(" Returned " + duties.size() + " duties");
39+
System.out.println(" Returned " + duties.size() + " duties");
4440
return ResponseEntity.ok(duties);
4541
} catch (Exception e) {
46-
System.err.println(" Error: " + e.getMessage());
42+
System.err.println(" Error: " + e.getMessage());
4743
e.printStackTrace();
4844
return ResponseEntity.internalServerError().build();
4945
}
@@ -58,14 +54,14 @@ public ResponseEntity<List<DutyDetailDTO>> getDutyDetailsByDate(
5854
@PathVariable Long officerId,
5955
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
6056

61-
System.out.println("📱 Mobile API Request: GET /officer/" + officerId + "/date?date=" + date);
57+
System.out.println(" Mobile API Request: GET /officer/" + officerId + "/date?date=" + date);
6258

6359
try {
6460
List<DutyDetailDTO> details = mobileDutyService.getDutyDetailsByDate(officerId, date);
65-
System.out.println("Returned " + details.size() + " duty details");
61+
System.out.println("Returned " + details.size() + " duty details");
6662
return ResponseEntity.ok(details);
6763
} catch (Exception e) {
68-
System.err.println(" Error: " + e.getMessage());
64+
System.err.println(" Error: " + e.getMessage());
6965
e.printStackTrace();
7066
return ResponseEntity.internalServerError().build();
7167
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.crimeLink.analyzer.dto;
2+
3+
import lombok.Data;
4+
import java.time.LocalDate;
5+
import java.time.LocalDateTime;
6+
7+
@Data
8+
public class LeaveRequestDTO {
9+
private Long id;
10+
private Long officerId;
11+
private String officerName;
12+
private LocalDate date;
13+
private String reason;
14+
private String status;
15+
private LocalDate requestedDate;
16+
private String responseReason;
17+
private Long respondedBy;
18+
private LocalDateTime respondedDate;
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.crimeLink.analyzer.dto;
2+
3+
import lombok.Data;
4+
import jakarta.validation.constraints.*;
5+
import org.antlr.v4.runtime.misc.NotNull;
6+
7+
import java.time.LocalDate;
8+
9+
@Data
10+
public class LeaveSubmitRequest {
11+
private Long officerId;
12+
13+
private LocalDate date;
14+
15+
private String reason;
16+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.crimeLink.analyzer.dto;
2+
3+
import lombok.Data;
4+
import jakarta.validation.constraints.*;
5+
6+
@Data
7+
public class LeaveUpdateRequest {
8+
@NotBlank
9+
private String status; // APPROVED or DENIED
10+
11+
private String responseReason;
12+
}

0 commit comments

Comments
 (0)