From ee83ac43c4e7f6ea4633cd471597a0363f08f84e Mon Sep 17 00:00:00 2001 From: Przemek Zatorski Date: Fri, 4 Sep 2026 00:40:22 +0200 Subject: [PATCH] =?UTF-8?q?naprawa=20has=C5=82a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 18 ++++++ .../pl/polskalokalnie/config/DataSeeder.java | 55 +++++++++++++++---- docker-compose.prod.yml | 11 ++++ docker-compose.yml | 11 ++++ 4 files changed, 84 insertions(+), 11 deletions(-) diff --git a/.env.example b/.env.example index 60fcbcc..e845781 100644 --- a/.env.example +++ b/.env.example @@ -9,3 +9,21 @@ SPRING_JPA_HIBERNATE_DDL_AUTO=update WEB_BIND_ADDRESS=0.0.0.0 BACKEND_BIND_ADDRESS=127.0.0.1 POSTGRES_BIND_ADDRESS=127.0.0.1 + +# --- Konto administratora --- +# Uzywane przy pierwszym starcie do zalozenia konta. Logowanie odbywa sie ADRESEM E-MAIL. +APP_ADMIN_EMAIL=admin@softspm.com +APP_ADMIN_PASSWORD=Admin123! +APP_ADMIN_NAME=Administrator Polska Lokalnie + +# Gdy konto administratora juz istnieje, APP_ADMIN_PASSWORD jest ignorowane - inaczej restart +# cofalby haslo zmienione w ustawieniach konta. Ustaw ponizsze na true, zrestartuj backend i +# wroc do false, zeby awaryjnie przywrocic haslo z APP_ADMIN_PASSWORD. +APP_ADMIN_RESET_PASSWORD=false + +# --- Sesje --- +# Min. 32 znaki. W produkcji ustaw wlasna wartosc - domyslna zna kazdy, kto widzial repozytorium. +APP_JWT_SECRET=local-dev-secret-change-me-please-32chars-min + +# Adres bazowy w linkach z e-maili (aktywacja konta, reset hasla). +APP_PUBLIC_BASE_URL=http://localhost diff --git a/backend/src/main/java/pl/polskalokalnie/config/DataSeeder.java b/backend/src/main/java/pl/polskalokalnie/config/DataSeeder.java index 9e6aedb..1a46996 100644 --- a/backend/src/main/java/pl/polskalokalnie/config/DataSeeder.java +++ b/backend/src/main/java/pl/polskalokalnie/config/DataSeeder.java @@ -1,6 +1,8 @@ package pl.polskalokalnie.config; import java.math.BigDecimal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.security.crypto.password.PasswordEncoder; @@ -26,6 +28,8 @@ import pl.polskalokalnie.user.UserRepository; @Component public class DataSeeder implements CommandLineRunner { + private static final Logger log = LoggerFactory.getLogger(DataSeeder.class); + private final UserRepository userRepository; private final ListingRepository listingRepository; private final BannerRepository bannerRepository; @@ -36,6 +40,7 @@ public class DataSeeder implements CommandLineRunner { private final String adminEmail; private final String adminPassword; private final String adminName; + private final boolean adminResetPassword; public DataSeeder( UserRepository userRepository, @@ -47,7 +52,8 @@ public class DataSeeder implements CommandLineRunner { NickService nickService, @Value("${app.admin.email:admin@softspm.com}") String adminEmail, @Value("${app.admin.password:Admin123!}") String adminPassword, - @Value("${app.admin.name:Administrator Polska Lokalnie}") String adminName + @Value("${app.admin.name:Administrator Polska Lokalnie}") String adminName, + @Value("${app.admin.reset-password:false}") boolean adminResetPassword ) { this.userRepository = userRepository; this.listingRepository = listingRepository; @@ -59,6 +65,7 @@ public class DataSeeder implements CommandLineRunner { this.adminEmail = adminEmail; this.adminPassword = adminPassword; this.adminName = adminName; + this.adminResetPassword = adminResetPassword; } @Override @@ -135,19 +142,45 @@ public class DataSeeder implements CommandLineRunner { return banner; } + /** + * Konto administratora z konfiguracji (APP_ADMIN_EMAIL / APP_ADMIN_PASSWORD). + * + * Gdy konta o tym adresie jeszcze nie ma - zakladamy je. Gdy juz istnieje, haslo z konfiguracji + * jest ignorowane, bo inaczej kazdy restart cofalby haslo zmienione w ustawieniach konta. + * Swiadome nadpisanie wlacza APP_ADMIN_RESET_PASSWORD=true - to jedyna droga odzyskania dostepu, + * gdy haslo administratora zostalo zgubione. + */ private void seedAdmin() { - if (userRepository.existsByEmailIgnoreCase(adminEmail)) { + String email = adminEmail.trim().toLowerCase(); + AppUser existing = userRepository.findByEmailIgnoreCase(email).orElse(null); + + if (existing == null) { + AppUser admin = new AppUser(); + admin.setEmail(email); + admin.setFullName(adminName); + admin.setNick(nickService.generateUnique(email.split("@")[0])); + admin.setPasswordHash(passwordEncoder.encode(adminPassword)); + admin.setRole(Role.ADMIN); + admin.setProvider(AuthProvider.LOCAL); + admin.setVerified(true); + userRepository.save(admin); + log.info("Utworzono konto administratora {}", email); return; } - AppUser admin = new AppUser(); - admin.setEmail(adminEmail.toLowerCase()); - admin.setFullName(adminName); - admin.setNick(nickService.generateUnique(adminEmail.split("@")[0])); - admin.setPasswordHash(passwordEncoder.encode(adminPassword)); - admin.setRole(Role.ADMIN); - admin.setProvider(AuthProvider.LOCAL); - admin.setVerified(true); - userRepository.save(admin); + + if (!adminResetPassword) { + return; + } + + // Awaryjne przywrocenie dostepu: haslo, rola i aktywacja wracaja do stanu z konfiguracji. + // Blokada konta tez znika - inaczej reset hasla nie przywrocilby logowania. + existing.setPasswordHash(passwordEncoder.encode(adminPassword)); + existing.setRole(Role.ADMIN); + existing.setVerified(true); + existing.setBlocked(false); + userRepository.save(existing); + log.warn("APP_ADMIN_RESET_PASSWORD=true - ustawiono haslo z konfiguracji dla konta {}." + + " Wylacz te zmienna po odzyskaniu dostepu.", email); } private void seedDemoListings() { diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 054c46c..f407405 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -21,6 +21,17 @@ services: SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER:-polskalokalnie} SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD:-polskalokalnie_dev} SPRING_JPA_HIBERNATE_DDL_AUTO: ${SPRING_JPA_HIBERNATE_DDL_AUTO:-update} + # Bez tych zmiennych backend bierze wartosci domyslne z application.yml, wiec login i haslo + # administratora ustawione w .env nie mialy zadnego wplywu na dzialajaca aplikacje. + APP_ADMIN_EMAIL: ${APP_ADMIN_EMAIL:-admin@softspm.com} + APP_ADMIN_PASSWORD: ${APP_ADMIN_PASSWORD:-Admin123!} + APP_ADMIN_NAME: ${APP_ADMIN_NAME:-Administrator Polska Lokalnie} + # true = przy starcie ustaw haslo administratora na APP_ADMIN_PASSWORD (odzyskanie dostepu). + APP_ADMIN_RESET_PASSWORD: ${APP_ADMIN_RESET_PASSWORD:-false} + # Sekret podpisujacy tokeny sesji. Domyslna wartosc jest jawna w repozytorium - w produkcji + # musi byc wlasna, inaczej kazdy moze wystawic sobie token administratora. + APP_JWT_SECRET: ${APP_JWT_SECRET:-local-dev-secret-change-me-please-32chars-min} + APP_PUBLIC_BASE_URL: ${APP_PUBLIC_BASE_URL:-http://localhost} depends_on: db: condition: service_healthy diff --git a/docker-compose.yml b/docker-compose.yml index a79e1e2..28dd919 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,17 @@ services: SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER:-polskalokalnie} SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD:-polskalokalnie_dev} SPRING_JPA_HIBERNATE_DDL_AUTO: ${SPRING_JPA_HIBERNATE_DDL_AUTO:-update} + # Bez tych zmiennych backend bierze wartosci domyslne z application.yml, wiec login i haslo + # administratora ustawione w .env nie mialy zadnego wplywu na dzialajaca aplikacje. + APP_ADMIN_EMAIL: ${APP_ADMIN_EMAIL:-admin@softspm.com} + APP_ADMIN_PASSWORD: ${APP_ADMIN_PASSWORD:-Admin123!} + APP_ADMIN_NAME: ${APP_ADMIN_NAME:-Administrator Polska Lokalnie} + # true = przy starcie ustaw haslo administratora na APP_ADMIN_PASSWORD (odzyskanie dostepu). + APP_ADMIN_RESET_PASSWORD: ${APP_ADMIN_RESET_PASSWORD:-false} + # Sekret podpisujacy tokeny sesji. Domyslna wartosc jest jawna w repozytorium - w produkcji + # musi byc wlasna, inaczej kazdy moze wystawic sobie token administratora. + APP_JWT_SECRET: ${APP_JWT_SECRET:-local-dev-secret-change-me-please-32chars-min} + APP_PUBLIC_BASE_URL: ${APP_PUBLIC_BASE_URL:-http://localhost} depends_on: db: condition: service_healthy