11package com .crimeLink .analyzer .controller ;
22
33import com .crimeLink .analyzer .dto .AuditLogDTO ;
4+ import com .crimeLink .analyzer .entity .BackupMetadata ;
45import com .crimeLink .analyzer .entity .LoginAudit ;
56import com .crimeLink .analyzer .entity .User ;
67import com .crimeLink .analyzer .repository .LoginAuditRepository ;
78import com .crimeLink .analyzer .repository .UserRepository ;
9+ import com .crimeLink .analyzer .service .BackupService ;
10+ import com .crimeLink .analyzer .service .SystemSettingsService ;
811import lombok .RequiredArgsConstructor ;
912import org .springframework .data .domain .PageRequest ;
1013import org .springframework .data .domain .Sort ;
1114import org .springframework .http .ResponseEntity ;
15+ import org .springframework .security .access .prepost .PreAuthorize ;
16+ import org .springframework .security .core .Authentication ;
1217import org .springframework .security .crypto .password .PasswordEncoder ;
1318import org .springframework .web .bind .annotation .*;
1419
@@ -24,6 +29,12 @@ public class AdminController {
2429 private final UserRepository userRepo ;
2530 private final LoginAuditRepository auditRepo ;
2631 private final PasswordEncoder passwordEncoder ;
32+ private final BackupService backupService ;
33+ private final SystemSettingsService settingsService ;
34+
35+ // ════════════════════════════════════════════════════════════════
36+ // USER MANAGEMENT (Admin + OIC)
37+ // ════════════════════════════════════════════════════════════════
2738
2839 /**
2940 * Get all users or filter by role/status
@@ -124,6 +135,10 @@ public ResponseEntity<?> deactivateUser(@PathVariable Integer id) {
124135 .orElse (ResponseEntity .notFound ().build ());
125136 }
126137
138+ // ════════════════════════════════════════════════════════════════
139+ // AUDIT LOGS (Admin + OIC)
140+ // ════════════════════════════════════════════════════════════════
141+
127142 /**
128143 * Get audit logs
129144 * GET /api/admin/audit-logs?limit=100&offset=0
@@ -180,23 +195,26 @@ public ResponseEntity<List<AuditLogDTO>> getAuditLogs(
180195 return ResponseEntity .ok (dtoList );
181196 }
182197
198+ // ════════════════════════════════════════════════════════════════
199+ // BACKUP & RESTORE (Admin only)
200+ // ════════════════════════════════════════════════════════════════
201+
183202 /**
184203 * Trigger database backup
185204 * POST /api/admin/backup
186205 */
187206 @ PostMapping ("/backup" )
188- public ResponseEntity <?> triggerBackup () {
207+ @ PreAuthorize ("hasRole('Admin')" )
208+ public ResponseEntity <?> triggerBackup (Authentication authentication ) {
189209 try {
190- String timestamp = java .time .LocalDateTime .now ()
191- .format (java .time .format .DateTimeFormatter .ofPattern ("yyyy-MM-dd_HH-mm-ss" ));
192- String filename = "backup_" + timestamp + ".sql" ;
193-
194- // TODO: Implement actual backup logic
195- // For Railway PostgreSQL, use pg_dump or Spring's backup mechanisms
210+ String userEmail = authentication .getName ();
211+ BackupMetadata metadata = backupService .createBackup (userEmail );
196212
197213 return ResponseEntity .ok (Map .of (
198214 "message" , "Backup created successfully" ,
199- "file" , filename
215+ "file" , metadata .getFilename (),
216+ "sizeBytes" , metadata .getSizeBytes (),
217+ "createdAt" , metadata .getCreatedAt ().toString ()
200218 ));
201219 } catch (Exception e ) {
202220 return ResponseEntity .status (500 ).body (
@@ -210,27 +228,86 @@ public ResponseEntity<?> triggerBackup() {
210228 * POST /api/admin/restore
211229 */
212230 @ PostMapping ("/restore" )
213- public ResponseEntity <?> restoreBackup (@ RequestBody Map <String , String > request ) {
231+ @ PreAuthorize ("hasRole('Admin')" )
232+ public ResponseEntity <?> restoreBackup (
233+ @ RequestBody Map <String , String > request ,
234+ Authentication authentication ) {
214235 try {
215236 String filename = request .get ("filename" );
216- if (filename == null || filename .isEmpty ()) {
237+ if (filename == null || filename .isBlank ()) {
217238 return ResponseEntity .badRequest ()
218239 .body (Map .of ("message" , "Filename is required" ));
219240 }
220241
221- // TODO: Implement actual restore logic
222- // For Railway PostgreSQL, use psql or Spring's restore mechanisms
242+ String userEmail = authentication . getName ();
243+ backupService . restoreBackup ( filename , userEmail );
223244
224245 return ResponseEntity .ok (Map .of (
225246 "message" , "Database restored successfully from " + filename
226247 ));
248+ } catch (IllegalArgumentException e ) {
249+ return ResponseEntity .badRequest ().body (
250+ Map .of ("message" , e .getMessage ())
251+ );
227252 } catch (Exception e ) {
228253 return ResponseEntity .status (500 ).body (
229254 Map .of ("message" , "Restore failed: " + e .getMessage ())
230255 );
231256 }
232257 }
233258
259+ /**
260+ * List all available backups
261+ * GET /api/admin/backups
262+ */
263+ @ GetMapping ("/backups" )
264+ @ PreAuthorize ("hasRole('Admin')" )
265+ public ResponseEntity <List <BackupMetadata >> listBackups () {
266+ return ResponseEntity .ok (backupService .listBackups ());
267+ }
268+
269+ // ════════════════════════════════════════════════════════════════
270+ // SYSTEM SETTINGS (Admin only)
271+ // ════════════════════════════════════════════════════════════════
272+
273+ /**
274+ * Get all system settings
275+ * GET /api/admin/settings
276+ */
277+ @ GetMapping ("/settings" )
278+ @ PreAuthorize ("hasRole('Admin')" )
279+ public ResponseEntity <Map <String , String >> getSettings () {
280+ return ResponseEntity .ok (settingsService .getAllSettings ());
281+ }
282+
283+ /**
284+ * Update system settings
285+ * PUT /api/admin/settings
286+ */
287+ @ PutMapping ("/settings" )
288+ @ PreAuthorize ("hasRole('Admin')" )
289+ public ResponseEntity <?> updateSettings (@ RequestBody Map <String , String > settings ) {
290+ try {
291+ Map <String , String > updated = settingsService .updateSettings (settings );
292+ return ResponseEntity .ok (Map .of (
293+ "message" , "Settings saved successfully" ,
294+ "settings" , updated
295+ ));
296+ } catch (IllegalArgumentException e ) {
297+ return ResponseEntity .badRequest ().body (
298+ Map .of ("message" , e .getMessage ())
299+ );
300+ } catch (Exception e ) {
301+ return ResponseEntity .status (500 ).body (
302+ Map .of ("message" , "Failed to save settings: " + e .getMessage ())
303+ );
304+ }
305+ }
306+
307+ // ════════════════════════════════════════════════════════════════
308+ // SYSTEM HEALTH (public)
309+ // ════════════════════════════════════════════════════════════════
310+
234311 /**
235312 * Get system health
236313 * GET /api/admin/health
0 commit comments