Harden startup config
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
package com.petshop.backend.config;
|
||||
|
||||
import com.petshop.backend.entity.User;
|
||||
import com.petshop.backend.repository.UserRepository;
|
||||
import com.petshop.backend.security.AppPrincipal;
|
||||
import com.petshop.backend.service.ActivityLogService;
|
||||
import jakarta.servlet.FilterChain;
|
||||
@@ -18,15 +16,13 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 20)
|
||||
public class ActivityLoggingFilter extends OncePerRequestFilter {
|
||||
@Component
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 20)
|
||||
public class ActivityLoggingFilter extends OncePerRequestFilter {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
private final ActivityLogService activityLogService;
|
||||
|
||||
public ActivityLoggingFilter(UserRepository userRepository, ActivityLogService activityLogService) {
|
||||
this.userRepository = userRepository;
|
||||
public ActivityLoggingFilter(ActivityLogService activityLogService) {
|
||||
this.activityLogService = activityLogService;
|
||||
}
|
||||
|
||||
@@ -73,12 +69,7 @@ public class ActivityLoggingFilter extends OncePerRequestFilter {
|
||||
return;
|
||||
}
|
||||
|
||||
User user = userRepository.findById(userId).orElse(null);
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String activity = String.format("%s %s -> %d", request.getMethod(), request.getRequestURI(), response.getStatus());
|
||||
activityLogService.record(user, activity);
|
||||
activityLogService.record(userId, activity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.petshop.backend.config;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.flywaydb.core.api.MigrationVersion;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
@@ -38,10 +37,7 @@ public class FlywayContextInitializer implements ApplicationContextInitializer<C
|
||||
Flyway flyway = Flyway.configure()
|
||||
.dataSource(url, username, password)
|
||||
.locations(locations)
|
||||
.baselineOnMigrate(environment.getProperty("spring.flyway.baseline-on-migrate", Boolean.class, false))
|
||||
.baselineVersion(MigrationVersion.fromVersion(environment.getProperty("spring.flyway.baseline-version", "1")))
|
||||
.load();
|
||||
flyway.repair();
|
||||
flyway.migrate();
|
||||
return;
|
||||
} catch (RuntimeException ex) {
|
||||
|
||||
@@ -101,7 +101,7 @@ public class AuthController {
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
String token = jwtUtil.generateToken(savedUser);
|
||||
activityLogService.record(savedUser, "POST /api/v1/auth/register -> 201");
|
||||
activityLogService.record(savedUser.getId(), "POST /api/v1/auth/register -> 201");
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(new RegisterResponse(
|
||||
savedUser.getId(),
|
||||
@@ -124,7 +124,7 @@ public class AuthController {
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||
|
||||
String token = jwtUtil.generateToken(user);
|
||||
activityLogService.record(user, "POST /api/v1/auth/login -> 200");
|
||||
activityLogService.record(user.getId(), "POST /api/v1/auth/login -> 200");
|
||||
|
||||
return ResponseEntity.ok(new LoginResponse(
|
||||
token,
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.petshop.backend.entity.User;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -23,6 +24,16 @@ public class JwtUtil {
|
||||
@Value("${jwt.expiration}")
|
||||
private Long expiration;
|
||||
|
||||
@PostConstruct
|
||||
void validateConfiguration() {
|
||||
if (secret == null || secret.isBlank()) {
|
||||
throw new IllegalStateException("JWT_SECRET must be configured");
|
||||
}
|
||||
if (secret.getBytes(StandardCharsets.UTF_8).length < 32) {
|
||||
throw new IllegalStateException("JWT_SECRET must be at least 32 bytes long");
|
||||
}
|
||||
}
|
||||
|
||||
private SecretKey getSigningKey() {
|
||||
return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@@ -28,13 +28,16 @@ public class ActivityLogService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void record(User user, String activity) {
|
||||
if (user == null || activity == null || activity.isBlank()) {
|
||||
public void record(Long userId, String activity) {
|
||||
if (userId == null || activity == null || activity.isBlank()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
User managedUser = userRepository.findById(user.getId()).orElse(user);
|
||||
User managedUser = userRepository.findById(userId).orElse(null);
|
||||
if (managedUser == null) {
|
||||
return;
|
||||
}
|
||||
StoreLocation store = managedUser.getPrimaryStore();
|
||||
ActivityLog entry = new ActivityLog();
|
||||
entry.setUser(managedUser);
|
||||
@@ -50,6 +53,13 @@ public class ActivityLogService {
|
||||
}
|
||||
}
|
||||
|
||||
public void record(User user, String activity) {
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
record(user.getId(), activity);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<ActivityLogResponse> getLogs(int limit) {
|
||||
return activityLogRepository.findRecent(PageRequest.of(0, limit)).stream().map(this::toResponse).toList();
|
||||
|
||||
2
backend/src/main/resources/application-local.yml
Normal file
2
backend/src/main/resources/application-local.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
jwt:
|
||||
secret: ${JWT_SECRET:local-development-jwt-secret-change-me-please-123456}
|
||||
@@ -33,9 +33,7 @@ spring:
|
||||
open-in-view: false
|
||||
|
||||
flyway:
|
||||
enabled: true
|
||||
baseline-on-migrate: true
|
||||
baseline-version: 1
|
||||
enabled: false
|
||||
|
||||
server:
|
||||
port: ${SERVER_PORT:8080}
|
||||
@@ -50,7 +48,7 @@ springdoc:
|
||||
path: /swagger-ui
|
||||
|
||||
jwt:
|
||||
secret: ${JWT_SECRET:change_me_please_make_this_at_least_32_characters_long_for_security}
|
||||
secret: ${JWT_SECRET}
|
||||
expiration: ${JWT_EXPIRATION:86400000}
|
||||
|
||||
stripe:
|
||||
|
||||
Reference in New Issue
Block a user