Revert "auth"
All checks were successful
Build Org Backend / build (push) Successful in 10s

This reverts commit c8937357e5.
This commit is contained in:
2026-05-09 01:19:43 +01:00
parent 6dac9e7cc1
commit 0e5f8d7b1c
12 changed files with 25 additions and 210 deletions

View File

@@ -4,7 +4,6 @@ package org.zaine.app.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.zaine.app.security.JwtUtil;
import org.zaine.app.security.RequiresAuth;
import org.zaine.app.user.User;
import org.zaine.app.user.UserRepository;
import org.springframework.http.*;
@@ -17,7 +16,6 @@ import java.util.Map;
@RestController
@RequestMapping("/api/auth")
@RequiresAuth
@Tag(name = "Authentication")
public class AuthController {
@@ -76,4 +74,4 @@ public class AuthController {
public record LoginRequest(String username, String password) {}
public record RegisterRequest(String username, String password) {}
}
}

View File

@@ -7,7 +7,6 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.zaine.app.dto.CalibreBookDTO;
import org.zaine.app.security.RequiresAuth;
import org.zaine.app.service.CalibreService;
import io.swagger.v3.oas.annotations.Operation;
@@ -17,7 +16,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@RestController
@RequestMapping("/api/calibre")
@RequiresAuth
@Tag(name = "Calibre", description = "Calibre API")
public class CalibreController {
@@ -34,4 +32,4 @@ public class CalibreController {
public List<CalibreBookDTO> getBooks() {
return calibreService.getAllBooks();
}
}
}

View File

@@ -12,7 +12,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.zaine.app.dto.CreateCommentDTO;
import org.zaine.app.model.Comments;
import org.zaine.app.security.RequiresAuth;
import org.zaine.app.service.CommentsService;
import io.swagger.v3.oas.annotations.Operation;
@@ -86,7 +85,6 @@ public class CommentsController {
value = "",
consumes = "application/json"
)
@RequiresAuth
public void addComment(@RequestBody CreateCommentDTO dto) {
if (dto.getContent() == null || dto.getContent().trim().isEmpty()) {

View File

@@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.zaine.app.dto.CompetenciesDTO;
import org.zaine.app.model.Competencies;
import org.zaine.app.security.RequiresAuth;
import org.zaine.app.service.CompetenciesService;
import io.swagger.v3.oas.annotations.Operation;
@@ -21,7 +20,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@RestController
@RequestMapping("/api/competencies")
@RequiresAuth
@Tag(name = "Competencies", description = "Operations about competencies")
public class CompetenciesController {

View File

@@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.zaine.app.dto.CreateNoteDTO;
import org.zaine.app.model.Notes;
import org.zaine.app.security.RequiresAuth;
import org.zaine.app.service.NotesService;
import io.swagger.v3.oas.annotations.Operation;
@@ -20,7 +19,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@RestController
@RequestMapping("/api")
@RequiresAuth
@Tag(name = "Notes", description = "Operations related to notes")
public class NotesController {
@Autowired
@@ -61,3 +59,4 @@ public class NotesController {
return notesService.createNote(note);
}
}

View File

@@ -19,7 +19,6 @@ import org.zaine.app.dto.MotalahSessionDTO;
import org.zaine.app.dto.WirdEntryDTO;
import org.zaine.app.model.MotalahSession;
import org.zaine.app.model.WirdEntry;
import org.zaine.app.security.RequiresAuth;
import org.zaine.app.service.MotalahService;
import org.zaine.app.service.WirdService;
@@ -27,7 +26,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@RestController
@RequestMapping("/api/wird")
@RequiresAuth
@Tag(name = "Wird", description = "Wird API")
public class WirdController {

View File

@@ -28,7 +28,6 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.zaine.app.security.RequiresAuth;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@@ -143,7 +142,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@PostMapping("/build-web")
@RequiresAuth
public ResponseEntity<String> triggerWebBuild() {
return startBuild(webBuildDirectory, webBuildLogFile, webBuildRunning, webProcess, true);
}
@@ -157,7 +155,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@DeleteMapping("/build-web")
@RequiresAuth
public ResponseEntity<String> cancelWebBuild() {
return killProcess(webProcess, webBuildRunning, "web build");
}
@@ -171,7 +168,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/build-web/status")
@RequiresAuth
public ResponseEntity<BuildStatus> getWebBuildStatus() {
return ResponseEntity.ok(new BuildStatus(webBuildRunning.get(), webLastRun, webLastExitCode));
}
@@ -185,7 +181,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/build-web/logs")
@RequiresAuth
public SseEmitter streamWebLogs() {
return streamLogs(webBuildLogFile);
}
@@ -203,7 +198,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@PostMapping("/build-roam")
@RequiresAuth
public ResponseEntity<String> triggerRoamBuild() {
return startBuild(roamBuildDirectory, roamBuildLogFile, roamBuildRunning, roamProcess, false);
}
@@ -217,7 +211,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@DeleteMapping("/build-roam")
@RequiresAuth
public ResponseEntity<String> cancelRoamBuild() {
return killProcess(roamProcess, roamBuildRunning, "roam build");
}
@@ -231,7 +224,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/build-roam/status")
@RequiresAuth
public ResponseEntity<BuildStatus> getRoamBuildStatus() {
return ResponseEntity.ok(new BuildStatus(roamBuildRunning.get(), roamLastRun, roamLastExitCode));
}
@@ -245,7 +237,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/build-roam/logs")
@RequiresAuth
public SseEmitter streamRoamLogs() {
return streamLogs(roamBuildLogFile);
}
@@ -263,7 +254,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@PostMapping("/rerun-emacs")
@RequiresAuth
public ResponseEntity<String> triggerEmacs() {
log.info("Triggering Emacs command");
return startCommand(emacsRunDirectory, emacsRunLogFile, emacsRunning, emacsProcess);
@@ -278,7 +268,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@DeleteMapping("/rerun-emacs")
@RequiresAuth
public ResponseEntity<String> cancelEmacs() {
return killProcess(emacsProcess, emacsRunning, "emacs");
}
@@ -292,7 +281,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/rerun-emacs/status")
@RequiresAuth
public ResponseEntity<BuildStatus> getEmacsStatus() {
return ResponseEntity.ok(new BuildStatus(emacsRunning.get(), emacsLastRun, emacsLastExitCode));
}
@@ -306,7 +294,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/rerun-emacs/logs")
@RequiresAuth
public SseEmitter streamEmacsLogs() {
return streamLogs(emacsRunLogFile);
}
@@ -324,7 +311,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@PostMapping("/run-combined")
@RequiresAuth
public ResponseEntity<String> triggerCombined() {
if (!combinedRunning.compareAndSet(false, true)) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("Combined run already in progress");
@@ -403,7 +389,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@DeleteMapping("/run-combined")
@RequiresAuth
public ResponseEntity<String> cancelCombined() {
return killProcess(combinedProcess, combinedRunning, "combined run");
}
@@ -417,7 +402,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/run-combined/status")
@RequiresAuth
public ResponseEntity<BuildStatus> getCombinedStatus() {
return ResponseEntity.ok(new BuildStatus(combinedRunning.get(), combinedLastRun, combinedLastExitCode));
}
@@ -431,7 +415,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/run-combined/logs")
@RequiresAuth
public SseEmitter streamCombinedLogs() {
return streamLogs(combinedRunLogFile);
}
@@ -449,7 +432,6 @@ public class BuildController {
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping("/last-runs")
@RequiresAuth
public ResponseEntity<Map<String, Object>> getLastRuns() {
return ResponseEntity.ok(Map.of(
"web", Map.of("lastRun", nullSafe(webLastRun), "exitCode", nullSafe(webLastExitCode)),
@@ -794,4 +776,4 @@ public class BuildController {
this.lastExitCode = lastExitCode;
}
}
}
}

View File

@@ -1,31 +0,0 @@
package org.zaine.app.security;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ApiKeyAuthService {
private final String apiKey;
public ApiKeyAuthService(@Value("${org.auth.api-key:}") String apiKey) {
this.apiKey = apiKey == null ? "" : apiKey.trim();
}
public boolean isConfigured() {
return !apiKey.isBlank();
}
public boolean isValid(String candidate) {
if (!isConfigured() || candidate == null || candidate.isBlank()) {
return false;
}
byte[] expected = apiKey.getBytes(StandardCharsets.UTF_8);
byte[] provided = candidate.trim().getBytes(StandardCharsets.UTF_8);
return MessageDigest.isEqual(expected, provided);
}
}

View File

@@ -19,14 +19,11 @@ import java.util.List;
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
public static final String API_KEY_HEADER = "X-Org-Api-Key";
private final ApiKeyAuthService apiKeyAuthService;
private final JwtUtil jwtUtil;
private final RequestMappingHandlerMapping requestMappingHandlerMapping;
public JwtAuthFilter(ApiKeyAuthService apiKeyAuthService,
RequestMappingHandlerMapping requestMappingHandlerMapping) {
this.apiKeyAuthService = apiKeyAuthService;
public JwtAuthFilter(JwtUtil jwtUtil, RequestMappingHandlerMapping requestMappingHandlerMapping) {
this.jwtUtil = jwtUtil;
this.requestMappingHandlerMapping = requestMappingHandlerMapping;
}
@@ -39,17 +36,26 @@ public class JwtAuthFilter extends OncePerRequestFilter {
return;
}
String apiKey = request.getHeader(API_KEY_HEADER);
if (apiKeyAuthService.isValid(apiKey)) {
var auth = new UsernamePasswordAuthenticationToken("api-key", null, List.of());
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(auth);
filterChain.doFilter(request, response);
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing or invalid Authorization header");
return;
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Missing or invalid " + API_KEY_HEADER + " header");
String token = authHeader.substring(7);
if (!jwtUtil.isTokenValid(token)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid or expired token");
return;
}
String username = jwtUtil.extractUsername(token);
var auth = new UsernamePasswordAuthenticationToken(username, null, List.of());
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(auth);
filterChain.doFilter(request, response);
}
private boolean endpointRequiresAuth(HttpServletRequest request) {
@@ -65,4 +71,4 @@ public class JwtAuthFilter extends OncePerRequestFilter {
return false;
}
}
}
}