diff --git a/backend/src/main/java/com/xly/erp/common/config/CorsConfig.java b/backend/src/main/java/com/xly/erp/common/config/CorsConfig.java new file mode 100644 index 0000000..bbdc177 --- /dev/null +++ b/backend/src/main/java/com/xly/erp/common/config/CorsConfig.java @@ -0,0 +1,31 @@ +package com.xly.erp.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.List; + +@Configuration +public class CorsConfig { + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration cfg = new CorsConfiguration(); + cfg.setAllowedOrigins(List.of( + "http://localhost:5173", + "http://127.0.0.1:5173" + )); + cfg.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); + cfg.setAllowedHeaders(List.of("*")); + cfg.setExposedHeaders(List.of("Authorization")); + cfg.setAllowCredentials(true); + cfg.setMaxAge(3600L); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/api/**", cfg); + return source; + } +} diff --git a/backend/src/main/java/com/xly/erp/common/security/SecurityConfig.java b/backend/src/main/java/com/xly/erp/common/security/SecurityConfig.java index 02e9f31..3ba915d 100644 --- a/backend/src/main/java/com/xly/erp/common/security/SecurityConfig.java +++ b/backend/src/main/java/com/xly/erp/common/security/SecurityConfig.java @@ -4,6 +4,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; @@ -24,8 +25,10 @@ public class SecurityConfig { @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf(csrf -> csrf.disable()) + .cors(Customizer.withDefaults()) .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth + .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers(HttpMethod.POST, "/api/usr/auth/login").permitAll() .anyRequest().authenticated() ) diff --git a/scripts/seed-dev-admin.sh b/scripts/seed-dev-admin.sh new file mode 100755 index 0000000..321b287 --- /dev/null +++ b/scripts/seed-dev-admin.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Seed a dev admin user (sUserName=admin, password=666666). +# Run once after first `mvn spring-boot:run` so Flyway has applied V1. +# Idempotent: uses INSERT IGNORE on the unique key. + +set -euo pipefail + +DB_HOST="${DB_HOST:-127.0.0.1}" +DB_PORT="${DB_PORT:-3306}" +DB_SCHEMA="${DB_SCHEMA:-xly_erp}" +DB_USER="${DB_USER:-root}" + +# BCrypt(666666) cost 10. Spring's BCryptPasswordEncoder accepts both $2a$ and $2b$ prefixes. +HASH='$2b$10$ZzbGP0yWo3QJkaiZqEgtAOQVrzrti911VqbY7FoethhGQFPV0/Oj6' + +mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" ${DB_PASSWORD:+-p"$DB_PASSWORD"} "$DB_SCHEMA" <