Explorar o código

Add user and transport simple components

TomaszKK hai 2 semanas
pai
achega
798513cc28

+ 1 - 0
.gitignore

@@ -23,3 +23,4 @@ dependency-reduced-pom.xml
 buildNumber.properties
 buildNumber.properties
 .mvn/timing.properties
 .mvn/timing.properties
 
 
+/.idea/

+ 45 - 0
userService/src/main/java/pl/dmcs/userservice/config/SecurityConfig.java

@@ -0,0 +1,45 @@
+package pl.dmcs.userservice.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig {
+
+    /**
+     * Konfiguracja bezpieczeństwa
+     * Umożliwia dostęp do wszystkich endpointów API bez autentykacji (dev mode)
+     * Gdy Keycloak będzie gotowy, zmień permitAll() na: .requestMatchers("/user/**", "/transport/**").authenticated()
+     */
+    @Bean
+    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+        http
+            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+            .authorizeHttpRequests(authz -> authz
+                // Pozwól na dostęp bez autentykacji (DEV MODE)
+                .requestMatchers("/user/**", "/transport/**").permitAll()
+                // Wszystkie inne żądania wymagają autentykacji
+                .anyRequest().authenticated()
+            )
+            .csrf(csrf -> csrf.disable())  // Wyłącz CSRF dla REST API
+            .cors(cors -> {});  // Włącz CORS
+
+        return http.build();
+    }
+
+    /**
+     * Encoder hasła dla przyszłej autentykacji
+     */
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+}
+

+ 79 - 0
userService/src/main/java/pl/dmcs/userservice/controller/TransportController.java

@@ -0,0 +1,79 @@
+package pl.dmcs.userservice.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import pl.dmcs.userservice.model.Transport;
+import pl.dmcs.userservice.service.TransportService;
+
+import java.util.List;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/transport")
+public class TransportController {
+
+    private final TransportService transportService;
+
+    @Autowired
+    public TransportController(TransportService transportService) {
+        this.transportService = transportService;
+    }
+
+    @GetMapping
+    public ResponseEntity<List<Transport>> getAllTransports() {
+        List<Transport> transports = transportService.getAllTransports();
+        return ResponseEntity.ok(transports);
+    }
+
+    @GetMapping("/{id}")
+    public ResponseEntity<Transport> getTransportById(@PathVariable Long id) {
+        Optional<Transport> transport = transportService.getTransportById(id);
+        return transport.map(ResponseEntity::ok)
+                .orElseGet(() -> ResponseEntity.notFound().build());
+    }
+
+    @GetMapping("/courier/{courierId}")
+    public ResponseEntity<List<Transport>> getTransportsByCourierId(@PathVariable Long courierId) {
+        List<Transport> transports = transportService.getTransportsByCourierId(courierId);
+        return ResponseEntity.ok(transports);
+    }
+
+    @PostMapping("/courier/{courierId}")
+    public ResponseEntity<Transport> createTransport(@PathVariable Long courierId, @RequestBody Transport transport) {
+        try {
+            Transport createdTransport = transportService.createTransport(courierId, transport);
+            return ResponseEntity.status(HttpStatus.CREATED).body(createdTransport);
+        } catch (IllegalArgumentException e) {
+            return ResponseEntity.badRequest().build();
+        }
+    }
+
+    @PutMapping("/{id}")
+    public ResponseEntity<Transport> updateTransport(@PathVariable Long id, @RequestBody Transport transportDetails) {
+        Transport updatedTransport = transportService.updateTransport(id, transportDetails);
+        if (updatedTransport != null) {
+            return ResponseEntity.ok(updatedTransport);
+        } else {
+            return ResponseEntity.notFound().build();
+        }
+    }
+
+    @PatchMapping("/{id}")
+    public ResponseEntity<Transport> partialUpdateTransport(@PathVariable Long id, @RequestBody Transport transportDetails) {
+        Transport updatedTransport = transportService.updateTransport(id, transportDetails);
+        if (updatedTransport != null) {
+            return ResponseEntity.ok(updatedTransport);
+        } else {
+            return ResponseEntity.notFound().build();
+        }
+    }
+
+    @DeleteMapping("/{id}")
+    public ResponseEntity<Void> deleteTransport(@PathVariable Long id) {
+        transportService.deleteTransport(id);
+        return ResponseEntity.noContent().build();
+    }
+}
+

+ 68 - 0
userService/src/main/java/pl/dmcs/userservice/controller/UserController.java

@@ -0,0 +1,68 @@
+package pl.dmcs.userservice.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import pl.dmcs.userservice.model.User;
+import pl.dmcs.userservice.service.UserService;
+
+import java.util.List;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/user")
+public class UserController {
+
+    private final UserService userService;
+
+    @Autowired
+    public UserController(UserService userService) {
+        this.userService = userService;
+    }
+
+    @GetMapping
+    public ResponseEntity<List<User>> getAllUsers() {
+        List<User> users = userService.getAllUsers();
+        return ResponseEntity.ok(users);
+    }
+
+    @GetMapping("/{id}")
+    public ResponseEntity<User> getUserById(@PathVariable Long id) {
+        Optional<User> user = userService.getUserById(id);
+        return user.map(ResponseEntity::ok)
+                .orElseGet(() -> ResponseEntity.notFound().build());
+    }
+
+    @PostMapping
+    public ResponseEntity<User> createUser(@RequestBody User user) {
+        User createdUser = userService.createUser(user);
+        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
+    }
+
+    @PutMapping("/{id}")
+    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
+        User updatedUser = userService.updateUser(id, userDetails);
+        if (updatedUser != null) {
+            return ResponseEntity.ok(updatedUser);
+        } else {
+            return ResponseEntity.notFound().build();
+        }
+    }
+
+    @PatchMapping("/{id}")
+    public ResponseEntity<User> partialUpdateUser(@PathVariable Long id, @RequestBody User userDetails) {
+        User updatedUser = userService.updateUser(id, userDetails);
+        if (updatedUser != null) {
+            return ResponseEntity.ok(updatedUser);
+        } else {
+            return ResponseEntity.notFound().build();
+        }
+    }
+
+    @DeleteMapping("/{id}")
+    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
+        userService.deleteUser(id);
+        return ResponseEntity.noContent().build();
+    }
+}

+ 40 - 0
userService/src/main/java/pl/dmcs/userservice/model/Transport.java

@@ -0,0 +1,40 @@
+package pl.dmcs.userservice.model;
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Entity
+@Table(name = "transports")
+@Getter @Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class Transport {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "courier_id", nullable = false)
+    private User courier;
+
+    @Column(nullable = false)
+    private TransportType transportType;
+
+    private String brand;
+    private String model;
+
+    private String fuelType;
+
+    private Double trunkVolume;
+    private Double cargoCapacity;
+
+    private Double consumption;
+
+    private String licensePlate;
+    private String color;
+}
+

+ 9 - 0
userService/src/main/java/pl/dmcs/userservice/model/TransportType.java

@@ -0,0 +1,9 @@
+package pl.dmcs.userservice.model;
+
+public enum TransportType {
+    BIKE,
+    SCOOTER,
+    CAR,
+    VAN,
+    TRUCK
+}

+ 33 - 0
userService/src/main/java/pl/dmcs/userservice/model/User.java

@@ -0,0 +1,33 @@
+package pl.dmcs.userservice.model;
+
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import java.util.List;
+
+@Entity
+@Table(name = "users")
+@Getter @Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class User {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    private String firstName;
+    private String lastName;
+    private String phoneNumber;
+    private String email;
+
+    @Enumerated(EnumType.STRING)
+    @Column(nullable = false)
+    private UserType userType;
+
+    @OneToMany(mappedBy = "courier", cascade = CascadeType.ALL, orphanRemoval = true)
+    private List<Transport> transports;
+}

+ 8 - 0
userService/src/main/java/pl/dmcs/userservice/model/UserType.java

@@ -0,0 +1,8 @@
+package pl.dmcs.userservice.model;
+
+public enum UserType {
+    CUSTOMER,   // Klient
+    COURIER,    // Kurier
+    ADMIN       // Administrator
+}
+

+ 10 - 0
userService/src/main/java/pl/dmcs/userservice/repository/TransportRepository.java

@@ -0,0 +1,10 @@
+package pl.dmcs.userservice.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import pl.dmcs.userservice.model.Transport;
+import java.util.List;
+
+public interface TransportRepository extends JpaRepository<Transport, Long> {
+    List<Transport> findByCourierId(Long courierId);
+}
+

+ 7 - 0
userService/src/main/java/pl/dmcs/userservice/repository/UserRepository.java

@@ -0,0 +1,7 @@
+package pl.dmcs.userservice.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import pl.dmcs.userservice.model.User;
+
+public interface UserRepository extends JpaRepository<User, Long> {
+}

+ 86 - 0
userService/src/main/java/pl/dmcs/userservice/service/TransportService.java

@@ -0,0 +1,86 @@
+package pl.dmcs.userservice.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import pl.dmcs.userservice.model.Transport;
+import pl.dmcs.userservice.model.User;
+import pl.dmcs.userservice.model.UserType;
+import pl.dmcs.userservice.repository.TransportRepository;
+import pl.dmcs.userservice.repository.UserRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class TransportService {
+    private final TransportRepository transportRepository;
+    private final UserRepository userRepository;
+
+    @Autowired
+    public TransportService(TransportRepository transportRepository, UserRepository userRepository) {
+        this.transportRepository = transportRepository;
+        this.userRepository = userRepository;
+    }
+
+    public List<Transport> getAllTransports() {
+        return transportRepository.findAll();
+    }
+
+    public Optional<Transport> getTransportById(Long id) {
+        return transportRepository.findById(id);
+    }
+
+    public List<Transport> getTransportsByCourierId(Long courierId) {
+        return transportRepository.findByCourierId(courierId);
+    }
+
+    public Transport createTransport(Long courierId, Transport transport) {
+        Optional<User> courier = userRepository.findById(courierId);
+        if (courier.isPresent() && courier.get().getUserType() == UserType.COURIER) {
+            transport.setCourier(courier.get());
+            return transportRepository.save(transport);
+        }
+        throw new IllegalArgumentException("Kurier o id " + courierId + " nie został znaleziony lub nie jest kurierem");
+    }
+
+    public Transport updateTransport(Long id, Transport transportDetails) {
+        Optional<Transport> transport = transportRepository.findById(id);
+        if (transport.isPresent()) {
+            Transport existingTransport = transport.get();
+            if (transportDetails.getTransportType() != null) {
+                existingTransport.setTransportType(transportDetails.getTransportType());
+            }
+            if (transportDetails.getBrand() != null) {
+                existingTransport.setBrand(transportDetails.getBrand());
+            }
+            if (transportDetails.getModel() != null) {
+                existingTransport.setModel(transportDetails.getModel());
+            }
+            if (transportDetails.getFuelType() != null) {
+                existingTransport.setFuelType(transportDetails.getFuelType());
+            }
+            if (transportDetails.getTrunkVolume() != null) {
+                existingTransport.setTrunkVolume(transportDetails.getTrunkVolume());
+            }
+            if (transportDetails.getCargoCapacity() != null) {
+                existingTransport.setCargoCapacity(transportDetails.getCargoCapacity());
+            }
+            if (transportDetails.getConsumption() != null) {
+                existingTransport.setConsumption(transportDetails.getConsumption());
+            }
+            if (transportDetails.getLicensePlate() != null) {
+                existingTransport.setLicensePlate(transportDetails.getLicensePlate());
+            }
+            if (transportDetails.getColor() != null) {
+                existingTransport.setColor(transportDetails.getColor());
+            }
+            return transportRepository.save(existingTransport);
+        }
+        return null;
+    }
+
+    public void deleteTransport(Long id) {
+        transportRepository.deleteById(id);
+    }
+}
+

+ 59 - 0
userService/src/main/java/pl/dmcs/userservice/service/UserService.java

@@ -0,0 +1,59 @@
+package pl.dmcs.userservice.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import pl.dmcs.userservice.model.User;
+import pl.dmcs.userservice.repository.UserRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class UserService {
+    private final UserRepository userRepository;
+
+    @Autowired
+    public UserService(UserRepository userRepository) {
+        this.userRepository = userRepository;
+    }
+
+    public List<User> getAllUsers() {
+        return userRepository.findAll();
+    }
+
+    public Optional<User> getUserById(Long id) {
+        return userRepository.findById(id);
+    }
+
+    public User createUser(User user) {
+        return userRepository.save(user);
+    }
+
+    public User updateUser(Long id, User userDetails) {
+        Optional<User> user = userRepository.findById(id);
+        if (user.isPresent()) {
+            User existingUser = user.get();
+            if (userDetails.getFirstName() != null) {
+                existingUser.setFirstName(userDetails.getFirstName());
+            }
+            if (userDetails.getLastName() != null) {
+                existingUser.setLastName(userDetails.getLastName());
+            }
+            if (userDetails.getPhoneNumber() != null) {
+                existingUser.setPhoneNumber(userDetails.getPhoneNumber());
+            }
+            if (userDetails.getEmail() != null) {
+                existingUser.setEmail(userDetails.getEmail());
+            }
+            if (userDetails.getUserType() != null) {
+                existingUser.setUserType(userDetails.getUserType());
+            }
+            return userRepository.save(existingUser);
+        }
+        return null;
+    }
+
+    public void deleteUser(Long id) {
+        userRepository.deleteById(id);
+    }
+}

+ 6 - 1
userService/src/main/resources/application.properties

@@ -8,13 +8,18 @@ spring.application.name=userService
 # ===============================
 # ===============================
 # KONFIGURACJA BAZY DANYCH (PostgreSQL)
 # KONFIGURACJA BAZY DANYCH (PostgreSQL)
 # ===============================
 # ===============================
-spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
+spring.datasource.url=jdbc:postgresql://localhost:5432/userservice
 spring.datasource.username=postgres
 spring.datasource.username=postgres
 spring.datasource.password=postgres
 spring.datasource.password=postgres
 
 
 spring.jpa.hibernate.ddl-auto=validate
 spring.jpa.hibernate.ddl-auto=validate
 spring.jpa.show-sql=true
 spring.jpa.show-sql=true
 
 
+# Flyway konfiguracja
+spring.flyway.enabled=true
+spring.flyway.locations=classpath:db/migration
+spring.flyway.baselineOnMigrate=true
+
 spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8181/realms/logiroute-realm
 spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8181/realms/logiroute-realm
 
 
 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

+ 32 - 0
userService/src/main/resources/db/migration/V1__Initial_schema.sql

@@ -0,0 +1,32 @@
+-- Tworzenie tabeli użytkowników
+CREATE TABLE users (
+    id BIGSERIAL PRIMARY KEY,
+    first_name VARCHAR(100) NOT NULL,
+    last_name VARCHAR(100) NOT NULL,
+    phone_number VARCHAR(20),
+    email VARCHAR(100) UNIQUE NOT NULL,
+    user_type VARCHAR(20) NOT NULL CHECK (user_type IN ('CUSTOMER', 'COURIER', 'ADMIN'))
+);
+
+-- Tworzenie tabeli transportu
+CREATE TABLE transports (
+    id BIGSERIAL PRIMARY KEY,
+    courier_id BIGINT NOT NULL,
+    transport_type VARCHAR(100) NOT NULL CHECK (transport_type IN ('CAR', 'BIKE', 'VAN', 'TRUCK', 'SCOOTER')),
+    brand VARCHAR(100),
+    model VARCHAR(100),
+    fuel_type VARCHAR(50),
+    trunk_volume DOUBLE PRECISION,
+    cargo_capacity DOUBLE PRECISION,
+    consumption DOUBLE PRECISION,
+    license_plate VARCHAR(20) UNIQUE,
+    color VARCHAR(50),
+    FOREIGN KEY (courier_id) REFERENCES users(id) ON DELETE CASCADE
+);
+
+-- Indeksy dla poprawy wydajności
+CREATE INDEX idx_users_user_type ON users(user_type);
+CREATE INDEX idx_users_email ON users(email);
+CREATE INDEX idx_transports_courier_id ON transports(courier_id);
+CREATE INDEX idx_transports_license_plate ON transports(license_plate);
+