6 Commits

Author SHA1 Message Date
3355914c70 Refactor of the whole AuthController 2025-06-10 10:26:29 +02:00
0f14c72fdd login endpoint refactored 2025-06-09 19:57:27 +02:00
2589c6010e Dodawanie atrybutów razem z notice 2025-06-08 20:15:26 +02:00
00b9f99af5 Refactor
added possibility to get attributes
2025-06-08 14:36:38 +02:00
81cbc1f4b2 ClientID for orders 2025-06-08 10:25:36 +02:00
190083c133 ClientId from token in Wishlist controller 2025-06-07 15:18:51 +02:00
28 changed files with 497 additions and 228 deletions

View File

@@ -1,70 +1,68 @@
package _11.asktpk.artisanconnectbackend.controller; package _11.asktpk.artisanconnectbackend.controller;
import _11.asktpk.artisanconnectbackend.customExceptions.ClientAlreadyExistsException;
import _11.asktpk.artisanconnectbackend.customExceptions.WrongLoginPasswordException;
import _11.asktpk.artisanconnectbackend.dto.*; import _11.asktpk.artisanconnectbackend.dto.*;
import _11.asktpk.artisanconnectbackend.entities.Client; import _11.asktpk.artisanconnectbackend.service.AuthService;
import _11.asktpk.artisanconnectbackend.security.JwtUtil;
import _11.asktpk.artisanconnectbackend.service.ClientService;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*; import org.springframework.http.*;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("/api/v1/auth") @RequestMapping("/api/v1/auth")
public class AuthController { public class AuthController {
private final ClientService clientService; private final AuthService authService;
private final JwtUtil jwtUtil;
public AuthController(ClientService clientService, JwtUtil jwtUtil) { public AuthController(AuthService authService) {
this.clientService = clientService; this.authService = authService;
this.jwtUtil = jwtUtil;
} }
@PostMapping("/login") @PostMapping("/login")
public ResponseEntity<AuthResponseDTO> login(@RequestBody AuthRequestDTO authRequestDTO) { public ResponseEntity<?> login(@RequestBody AuthRequestDTO authRequestDTO) {
if (clientService.checkClientCredentials(authRequestDTO)) { if (authRequestDTO.getEmail() == null || authRequestDTO.getPassword() == null
Client client = clientService.getClientByEmail(authRequestDTO.getEmail()); || authRequestDTO.getEmail().isEmpty() || authRequestDTO.getPassword().isEmpty()) {
Long userId = client.getId(); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new RequestResponseDTO("Przekazano puste login lub hasło"));
String userRole = client.getRole().getRole(); }
String token = jwtUtil.generateToken(client.getEmail(), userRole, userId); authRequestDTO.setEmail(authRequestDTO.getEmail().toLowerCase());
try {
AuthResponseDTO responseDTO = authService.login(authRequestDTO.getEmail(), authRequestDTO.getPassword());
log.info("User logged in with {}", client.getEmail());
return ResponseEntity.status(HttpStatus.OK) return ResponseEntity.status(HttpStatus.OK)
.body(new AuthResponseDTO(userId, userRole, token)); .body(responseDTO);
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null); } catch (WrongLoginPasswordException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new RequestResponseDTO(e.getMessage()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new RequestResponseDTO(e.getMessage()));
} }
} }
@PostMapping("/register") @PostMapping("/register")
public ResponseEntity<AuthResponseDTO> register(@RequestBody ClientRegistrationDTO clientDTO) { public ResponseEntity<?> register(@RequestBody ClientRegistrationDTO clientRegistrationDTO) {
if (clientService.getClientByEmail(clientDTO.getEmail()) != null) { if (clientRegistrationDTO.getEmail() == null || clientRegistrationDTO.getPassword() == null
return ResponseEntity.status(HttpStatus.CONFLICT).build(); || clientRegistrationDTO.getEmail().isEmpty() || clientRegistrationDTO.getPassword().isEmpty()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new RequestResponseDTO("Przekazano puste login lub hasło"));
} }
ClientDTO savedClient = clientService.registerClient(clientDTO); clientRegistrationDTO.setEmail(clientRegistrationDTO.getEmail().toLowerCase());
String token = jwtUtil.generateToken( try {
savedClient.getEmail(), AuthResponseDTO registrationData = authService.register(clientRegistrationDTO.getEmail(), clientRegistrationDTO.getPassword(), clientRegistrationDTO.getFirstName(), clientRegistrationDTO.getLastName());
savedClient.getRole(),
savedClient.getId()
);
log.info("New user registered with {}", savedClient.getEmail()); return ResponseEntity.status(HttpStatus.CREATED)
.body(registrationData);
return ResponseEntity.status(HttpStatus.CREATED) } catch (ClientAlreadyExistsException clientAlreadyExistsException) {
.body(new AuthResponseDTO( return ResponseEntity.status(HttpStatus.CONFLICT)
savedClient.getId(), .body(new RequestResponseDTO(clientAlreadyExistsException.getMessage()));
savedClient.getRole(), } catch (Exception e) {
token return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new RequestResponseDTO(e.getMessage()));
)); }
} }
@PostMapping("/logout") @PostMapping("/logout")
@@ -73,7 +71,7 @@ public class AuthController {
if (authHeader != null && authHeader.startsWith("Bearer ")) { if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7); String token = authHeader.substring(7);
jwtUtil.blacklistToken(token); authService.logout(token);
return ResponseEntity.ok(new RequestResponseDTO("Successfully logged out")); return ResponseEntity.ok(new RequestResponseDTO("Successfully logged out"));
} }
@@ -82,43 +80,16 @@ public class AuthController {
@PostMapping("/google") @PostMapping("/google")
public ResponseEntity<?> authenticateWithGoogle(@RequestBody GoogleAuthRequestDTO dto) { public ResponseEntity<?> authenticateWithGoogle(@RequestBody GoogleAuthRequestDTO dto) {
if(dto.getGoogleToken() == null){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new RequestResponseDTO("Invalid or empty token"));
}
try { try {
String accessToken = dto.getGoogleToken(); AuthResponseDTO response = authService.googleLogin(dto.getGoogleToken());
String googleUserInfoUrl = "https://www.googleapis.com/oauth2/v3/userinfo"; return ResponseEntity.status(HttpStatus.OK).body(response);
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Map> response = restTemplate.exchange(
googleUserInfoUrl, HttpMethod.GET, entity, Map.class);
Map<String, Object> userInfo = response.getBody();
// String googleId = (String) userInfo.get("sub"); Potencjalnie możemy używać googlowskiego ID, ale to ma konflikt z naszym generowanym
assert userInfo != null;
String email = (String) userInfo.get("email");
String name = (String) userInfo.get("name");
Client client = clientService.getClientByEmail(email);
if (client == null) {
client = new Client();
client.setEmail(email);
client.setFirstName(name);
client.setRole(clientService.getUserRole()); // to pobiera po prostu role "USER" z tabeli w bazie
clientService.saveClientToDB(client);
}
String jwt = jwtUtil.generateToken(client.getEmail(), client.getRole().getRole(), client.getId());
log.info("User authenticated with google: {}", email);
return ResponseEntity.ok(new AuthResponseDTO(client.getId(), client.getRole().getRole(), jwt));
} catch (HttpClientErrorException httpClientErrorException) { } catch (HttpClientErrorException httpClientErrorException) {
log.error("Token is invalid or expired"); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new RequestResponseDTO("Google access token is invalid or expired"));
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new RequestResponseDTO("Invalid access token"));
} catch (Exception e) { } catch (Exception e) {
log.error("Error while checking Google access token", e);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED) return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(new RequestResponseDTO("Authentication Error (Google): " + e.getMessage())); .body(new RequestResponseDTO("Authentication Error (Google): " + e.getMessage()));
} }

View File

@@ -1,17 +1,17 @@
package _11.asktpk.artisanconnectbackend.controller; package _11.asktpk.artisanconnectbackend.controller;
import _11.asktpk.artisanconnectbackend.dto.NoticeAdditionDTO; import _11.asktpk.artisanconnectbackend.dto.*;
import _11.asktpk.artisanconnectbackend.dto.NoticeBoostDTO;
import _11.asktpk.artisanconnectbackend.dto.RequestResponseDTO;
import _11.asktpk.artisanconnectbackend.service.ClientService; import _11.asktpk.artisanconnectbackend.service.ClientService;
import _11.asktpk.artisanconnectbackend.service.NoticeService; import _11.asktpk.artisanconnectbackend.service.NoticeService;
import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; import _11.asktpk.artisanconnectbackend.utils.Enums;
import _11.asktpk.artisanconnectbackend.utils.Tools;
import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.EntityNotFoundException;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList; import java.util.Arrays;
import java.util.List; import java.util.List;
@RequestMapping("/api/v1/notices") @RequestMapping("/api/v1/notices")
@@ -19,14 +19,16 @@ import java.util.List;
public class NoticeController { public class NoticeController {
private final NoticeService noticeService; private final NoticeService noticeService;
private final ClientService clientService; private final ClientService clientService;
private final Tools tools;
public NoticeController(NoticeService noticeService, ClientService clientService) { public NoticeController(NoticeService noticeService, ClientService clientService, Tools tools) {
this.noticeService = noticeService; this.noticeService = noticeService;
this.clientService = clientService; this.clientService = clientService;
this.tools = tools;
} }
@GetMapping("/get/all") @GetMapping("/get/all")
public List<NoticeDTO> getAllNotices() { public List<NoticeResponseDTO> getAllNotices() {
return noticeService.getAllNotices(); return noticeService.getAllNotices();
} }
@@ -40,57 +42,34 @@ public class NoticeController {
} }
@PostMapping("/add") @PostMapping("/add")
public ResponseEntity<NoticeAdditionDTO> addNotice(@RequestBody NoticeDTO dto) { public ResponseEntity<NoticeAdditionDTO> addNotice(@RequestBody NoticeRequestDTO dto, HttpServletRequest request) {
if (!clientService.clientExists(dto.getClientId())) { Long clientId = tools.getClientIdFromRequest(request);
if (!clientService.clientExists(clientId)) {
return ResponseEntity return ResponseEntity
.status(HttpStatus.BAD_REQUEST) .status(HttpStatus.BAD_REQUEST)
.body(new NoticeAdditionDTO("Nie znaleziono klienta o ID: " + dto.getClientId())); .body(new NoticeAdditionDTO("Nie znaleziono klienta o ID: " + clientId));
} }
if (dto.getCategory() == null) { dto.setClientId(clientId);
if (dto.getCategory() == null || !Arrays.asList(Enums.Category.values()).contains(dto.getCategory())) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new NoticeAdditionDTO("Nie ma takiej kategorii")); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new NoticeAdditionDTO("Nie ma takiej kategorii"));
} }
dto.setPublishDate(java.time.LocalDateTime.now());
Long newNoticeId = noticeService.addNotice(dto); Long newNoticeId = noticeService.addNotice(dto);
return ResponseEntity.status(HttpStatus.CREATED).body(new NoticeAdditionDTO(newNoticeId ,"Dodano ogłoszenie.")); return ResponseEntity.status(HttpStatus.CREATED).body(new NoticeAdditionDTO(newNoticeId ,"Dodano ogłoszenie."));
} }
// TODO: zamiast dodawać tutaj pętlą, musi to robić NoticeService, trzeba zaimplementować odpowienią metodę
@PostMapping("/bulk_add")
public ResponseEntity<String> addNotices(@RequestBody List<NoticeDTO> notices_list) {
ResponseEntity<String> response = new ResponseEntity<>(HttpStatus.CREATED);
List<String> errors = new ArrayList<>();
boolean isError = false;
if (notices_list.isEmpty()) {
return response.status(HttpStatus.BAD_REQUEST).body("Lista ogłoszeń jest pusta.");
}
for (NoticeDTO dto : notices_list) {
if (!clientService.clientExists(dto.getClientId())) {
isError = true;
errors.add(dto.getClientId().toString());
} else {
if (!isError) {
noticeService.addNotice(dto);
}
}
}
if (isError) {
return response.status(HttpStatus.BAD_REQUEST).body("Nie znaleziono klientów: " + errors);
}
return response;
}
@PutMapping("/edit/{id}") @PutMapping("/edit/{id}")
public ResponseEntity<Object> editNotice(@PathVariable("id") long id, @RequestBody NoticeDTO dto) { public ResponseEntity<Object> editNotice(@PathVariable("id") long id, @RequestBody NoticeRequestDTO dto, HttpServletRequest request) {
Long clientIdFromToken = tools.getClientIdFromRequest(request);
if (noticeService.noticeExists(id)) { if (noticeService.noticeExists(id)) {
if (!noticeService.isNoticeOwnedByClient(id, clientIdFromToken)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new RequestResponseDTO("Nie masz uprawnień do edycji tego ogłoszenia."));
}
try { try {
return new ResponseEntity<>(noticeService.updateNotice(id, dto), HttpStatus.OK); return ResponseEntity.status(HttpStatus.OK).body(noticeService.updateNotice(id, dto));
} catch (EntityNotFoundException e) { } catch (EntityNotFoundException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage()); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
} }
@@ -100,8 +79,13 @@ public class NoticeController {
} }
@DeleteMapping("/delete/{id}") @DeleteMapping("/delete/{id}")
public ResponseEntity<RequestResponseDTO> deleteNotice(@PathVariable("id") long id) { public ResponseEntity<RequestResponseDTO> deleteNotice(@PathVariable("id") long id, HttpServletRequest request) {
Long clientIdFromToken = tools.getClientIdFromRequest(request);
if (noticeService.noticeExists(id)) { if (noticeService.noticeExists(id)) {
if (!noticeService.isNoticeOwnedByClient(id, clientIdFromToken)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new RequestResponseDTO("Nie masz uprawnień do usunięcia tego ogłoszenia."));
}
noticeService.deleteNotice(id); noticeService.deleteNotice(id);
return ResponseEntity.status(HttpStatus.OK).body(new RequestResponseDTO("Pomyślnie usunięto ogłoszenie o ID: " + id)); return ResponseEntity.status(HttpStatus.OK).body(new RequestResponseDTO("Pomyślnie usunięto ogłoszenie o ID: " + id));
} else { } else {
@@ -109,9 +93,10 @@ public class NoticeController {
} }
} }
@PostMapping("/boost/{id}") @PostMapping("/boost")
public ResponseEntity<RequestResponseDTO> boostNotice(@PathVariable("id") long clientId, @RequestBody NoticeBoostDTO dto) { public ResponseEntity<RequestResponseDTO> boostNotice(@RequestBody NoticeBoostDTO dto, HttpServletRequest request) {
if (!noticeService.isNoticeOwnedByClient(dto.getNoticeId(), clientId)) { Long clientId = tools.getClientIdFromRequest(request);
if (noticeService.isNoticeOwnedByClient(dto.getNoticeId(), clientId)) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new RequestResponseDTO("Ogłoszenie nie istnieje lub nie należy do zalogowanego klienta.")); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new RequestResponseDTO("Ogłoszenie nie istnieje lub nie należy do zalogowanego klienta."));
} }
noticeService.boostNotice(dto.getNoticeId()); noticeService.boostNotice(dto.getNoticeId());

View File

@@ -2,40 +2,45 @@ package _11.asktpk.artisanconnectbackend.controller;
import _11.asktpk.artisanconnectbackend.dto.*; import _11.asktpk.artisanconnectbackend.dto.*;
import _11.asktpk.artisanconnectbackend.entities.Order; import _11.asktpk.artisanconnectbackend.entities.Order;
import _11.asktpk.artisanconnectbackend.service.ClientService;
import _11.asktpk.artisanconnectbackend.service.OrderService; import _11.asktpk.artisanconnectbackend.service.OrderService;
import _11.asktpk.artisanconnectbackend.service.PaymentService; import _11.asktpk.artisanconnectbackend.service.PaymentService;
import _11.asktpk.artisanconnectbackend.utils.Enums; import _11.asktpk.artisanconnectbackend.utils.Enums;
import _11.asktpk.artisanconnectbackend.utils.Tools;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@RestController @RestController
@RequestMapping("/api/v1/orders") @RequestMapping("/api/v1/orders")
public class OrderController { public class OrderController {
private final OrderService orderService; private final OrderService orderService;
private final PaymentService paymentService; private final PaymentService paymentService;
private final Tools tools;
public OrderController(OrderService orderService, PaymentService paymentService) { public OrderController(OrderService orderService, PaymentService paymentService, Tools tools) {
this.orderService = orderService; this.orderService = orderService;
this.paymentService = paymentService; this.paymentService = paymentService;
this.tools = tools;
} }
@PostMapping("/add") @PostMapping("/add")
public ResponseEntity addClient(@RequestBody OrderDTO orderDTO) { public ResponseEntity<?> addClient(@RequestBody OrderDTO orderDTO, HttpServletRequest request) {
return new ResponseEntity<>(orderService.addOrder(orderDTO), HttpStatus.CREATED); orderDTO.setClientId(tools.getClientIdFromRequest(request));
return ResponseEntity.status(HttpStatus.CREATED).body(orderService.addOrder(orderDTO));
} }
@PutMapping("/changeStatus") @PutMapping("/changeStatus")
public ResponseEntity changeStatus(@RequestBody OrderStatusDTO orderStatusDTO) { public ResponseEntity<?> changeStatus(@RequestBody OrderStatusDTO orderStatusDTO) {
return new ResponseEntity<>(orderService.changeOrderStatus(orderStatusDTO.getId(),orderStatusDTO.getStatus()), HttpStatus.OK); return ResponseEntity.status(HttpStatus.OK).body(orderService.changeOrderStatus(orderStatusDTO.getId(), orderStatusDTO.getStatus()));
} }
@PostMapping("/token") @PostMapping("/token")
public ResponseEntity<?> fetchToken() { public ResponseEntity<?> fetchToken() {
Order order = orderService.getOrderById(1L); Order order = orderService.getOrderById(1L);
OAuthPaymentResponseDTO authPaymentDTO= paymentService.getOAuthToken(); OAuthPaymentResponseDTO authPaymentDTO = paymentService.getOAuthToken();
TransactionPaymentRequestDTO.Payer payer = new TransactionPaymentRequestDTO.Payer( TransactionPaymentRequestDTO.Payer payer = new TransactionPaymentRequestDTO.Payer(
"patryk@test.pl", "Patryk Test"); "patryk@test.pl", "Patryk Test");
@@ -44,10 +49,10 @@ public class OrderController {
TransactionPaymentRequestDTO request = new TransactionPaymentRequestDTO( TransactionPaymentRequestDTO request = new TransactionPaymentRequestDTO(
order.getAmount(), paymentDescription, payer); order.getAmount(), paymentDescription, payer);
String response = paymentService.createTransaction(order,authPaymentDTO.getAccess_token(), request); String response = paymentService.createTransaction(order, authPaymentDTO.getAccess_token(), request);
System.out.println(response); System.out.println(response);
System.out.println(request); System.out.println(request);
return ResponseEntity.ok(response); return ResponseEntity.status(HttpStatus.OK).body(response);
} }
} }

View File

@@ -1,35 +1,39 @@
package _11.asktpk.artisanconnectbackend.controller; package _11.asktpk.artisanconnectbackend.controller;
import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; import _11.asktpk.artisanconnectbackend.dto.NoticeResponseDTO;
import _11.asktpk.artisanconnectbackend.dto.RequestResponseDTO; import _11.asktpk.artisanconnectbackend.dto.RequestResponseDTO;
import _11.asktpk.artisanconnectbackend.dto.WishlistDTO;
import _11.asktpk.artisanconnectbackend.service.ClientService; import _11.asktpk.artisanconnectbackend.service.ClientService;
import _11.asktpk.artisanconnectbackend.service.NoticeService; import _11.asktpk.artisanconnectbackend.service.NoticeService;
import _11.asktpk.artisanconnectbackend.service.WishlistService; import _11.asktpk.artisanconnectbackend.service.WishlistService;
import _11.asktpk.artisanconnectbackend.utils.Tools;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@Slf4j
@RestController @RestController
@RequestMapping("/api/v1/wishlist") @RequestMapping("/api/v1/wishlist")
public class WishlistController { public class WishlistController {
private final WishlistService wishlistService; private final WishlistService wishlistService;
private final ClientService clientService; private final ClientService clientService;
private final NoticeService noticeService; private final NoticeService noticeService;
private final Tools tools;
public WishlistController(WishlistService wishlistService, ClientService clientService, NoticeService noticeService) { public WishlistController(WishlistService wishlistService, ClientService clientService, NoticeService noticeService, Tools tools) {
this.wishlistService = wishlistService; this.wishlistService = wishlistService;
this.clientService = clientService; this.clientService = clientService;
this.noticeService = noticeService; this.noticeService = noticeService;
this.tools = tools;
} }
@PostMapping("/toggle/{noticeId}") @PostMapping("/toggle/{noticeId}")
public ResponseEntity<RequestResponseDTO> toggleWishlist(@PathVariable Long noticeId) { public ResponseEntity<RequestResponseDTO> toggleWishlist(@PathVariable Long noticeId, HttpServletRequest request) {
Long clientId = tools.getClientIdFromRequest(request);
Long clientId = 1L; NoticeResponseDTO noticeResponseDTO = noticeService.getNoticeById(noticeId);
NoticeDTO noticeDTO = noticeService.getNoticeById(noticeId); if (noticeResponseDTO == null) {
if (noticeDTO == null) {
return ResponseEntity.badRequest().body(new RequestResponseDTO("Notice not found")); return ResponseEntity.badRequest().body(new RequestResponseDTO("Notice not found"));
} }
boolean added = wishlistService.toggleWishlist( boolean added = wishlistService.toggleWishlist(
@@ -51,9 +55,8 @@ public class WishlistController {
// } // }
@GetMapping("/") @GetMapping("/")
public List<NoticeDTO> getWishlistForClient() { public List<NoticeResponseDTO> getWishlistForClient(HttpServletRequest request) {
// TODO: Replace with actual client ID from authentication context Long clientId = tools.getClientIdFromRequest(request);
Long clientId = 1L;
return wishlistService.getNoticesInWishlist(clientId); return wishlistService.getNoticesInWishlist(clientId);
} }
} }

View File

@@ -0,0 +1,7 @@
package _11.asktpk.artisanconnectbackend.customExceptions;
public class ClientAlreadyExistsException extends Exception {
public ClientAlreadyExistsException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package _11.asktpk.artisanconnectbackend.customExceptions;
public class WrongLoginPasswordException extends Exception {
public WrongLoginPasswordException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,11 @@
package _11.asktpk.artisanconnectbackend.dto;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class AttributeDto {
private String name;
private String value;
}

View File

@@ -1,12 +1,16 @@
package _11.asktpk.artisanconnectbackend.dto; package _11.asktpk.artisanconnectbackend.dto;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import jakarta.validation.constraints.Email; import jakarta.validation.constraints.Email;
@Getter @Setter @Getter @Setter
@AllArgsConstructor
@NoArgsConstructor
public class ClientDTO { public class ClientDTO {
private Long id; private Long id;

View File

@@ -0,0 +1,27 @@
package _11.asktpk.artisanconnectbackend.dto;
import _11.asktpk.artisanconnectbackend.utils.Enums;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter @Setter
public class NoticeRequestDTO {
private String title;
private Long clientId;
private String description;
private Double price;
private Enums.Category category;
private Enums.Status status;
private List<AttributeDto> attributes;
public NoticeRequestDTO() {
}
}

View File

@@ -1,6 +1,5 @@
package _11.asktpk.artisanconnectbackend.dto; package _11.asktpk.artisanconnectbackend.dto;
import _11.asktpk.artisanconnectbackend.entities.AttributesNotice;
import _11.asktpk.artisanconnectbackend.utils.Enums; import _11.asktpk.artisanconnectbackend.utils.Enums;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -9,7 +8,7 @@ import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@Getter @Setter @Getter @Setter
public class NoticeDTO { public class NoticeResponseDTO {
private long noticeId; private long noticeId;
private String title; private String title;
@@ -26,11 +25,9 @@ public class NoticeDTO {
private LocalDateTime publishDate; private LocalDateTime publishDate;
private List<AttributesNotice> attributesNotices; private List<AttributeDto> attributes;
private boolean isWishlisted; public NoticeResponseDTO() {
public NoticeDTO() {
} }
} }

View File

@@ -1,9 +1,12 @@
package _11.asktpk.artisanconnectbackend.entities; package _11.asktpk.artisanconnectbackend.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity @Entity
@Table(name = "attribute_values") @Table(name = "attribute_values")
@Getter @Setter
public class AttributeValues { public class AttributeValues {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -14,6 +17,4 @@ public class AttributeValues {
private Attributes attribute; private Attributes attribute;
private String value; private String value;
// Getters, setters, and constructors
} }

View File

@@ -1,10 +1,14 @@
package _11.asktpk.artisanconnectbackend.entities; package _11.asktpk.artisanconnectbackend.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Setter;
import lombok.Getter;
import java.util.List; import java.util.List;
@Entity @Entity
@Table(name = "attributes") @Table(name = "attributes")
@Getter @Setter
public class Attributes { public class Attributes {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -12,8 +16,6 @@ public class Attributes {
private String name; private String name;
@OneToMany(mappedBy = "attribute", cascade = CascadeType.ALL) @OneToMany(mappedBy = "attribute")
private List<AttributeValues> attributeValues; private List<AttributeValues> attributeValues;
// Getters, setters, and constructors
} }

View File

@@ -1,21 +1,20 @@
package _11.asktpk.artisanconnectbackend.entities; package _11.asktpk.artisanconnectbackend.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Setter;
import lombok.Getter;
@Entity @Entity
@Table(name = "attributes_notice") @Table(name = "attributes_notice")
@Getter @Setter
public class AttributesNotice { public class AttributesNotice {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@ManyToOne private Long notice_id;
@JoinColumn(name = "id_notice")
private Notice notice;
@ManyToOne @ManyToOne
@JoinColumn(name = "id_value") @JoinColumn(name = "id_value")
private AttributeValues attributeValue; private AttributeValues attributeValue;
// Getters, setters, and constructors
} }

View File

@@ -2,6 +2,7 @@ package _11.asktpk.artisanconnectbackend.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.CreationTimestamp;
@@ -11,7 +12,15 @@ import java.util.List;
@Entity @Entity
@Table(name = "clients") @Table(name = "clients")
@Getter @Setter @Getter @Setter
@NoArgsConstructor
public class Client { public class Client {
public Client(String email, String password, String firstName, String lastName) {
this.email = email;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
}
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;

View File

@@ -35,10 +35,10 @@ public class Notice {
private LocalDateTime publishDate; private LocalDateTime publishDate;
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) @OneToMany(mappedBy = "notice_id")
private List<AttributesNotice> attributesNotices; private List<AttributesNotice> attributesNotices;
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) @OneToMany(mappedBy = "notice")
private List<Order> orders; private List<Order> orders;
// @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) // @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL)

View File

@@ -0,0 +1,14 @@
package _11.asktpk.artisanconnectbackend.repository;
import _11.asktpk.artisanconnectbackend.entities.AttributeValues;
import _11.asktpk.artisanconnectbackend.entities.Attributes;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface AttributeValuesRepository extends JpaRepository<AttributeValues, Long> {
Optional<AttributeValues> findByAttributeAndValue(Attributes attribute, String value);
}

View File

@@ -0,0 +1,9 @@
package _11.asktpk.artisanconnectbackend.repository;
import _11.asktpk.artisanconnectbackend.entities.AttributesNotice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AttributesNoticeRepository extends JpaRepository<AttributesNotice, Long> {
}

View File

@@ -0,0 +1,12 @@
package _11.asktpk.artisanconnectbackend.repository;
import _11.asktpk.artisanconnectbackend.entities.Attributes;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface AttributesRepository extends JpaRepository<Attributes, Long> {
Optional<Attributes> findByName(String name);
}

View File

@@ -1,11 +1,9 @@
package _11.asktpk.artisanconnectbackend.repository; package _11.asktpk.artisanconnectbackend.repository;
import _11.asktpk.artisanconnectbackend.entities.Notice; import _11.asktpk.artisanconnectbackend.entities.Notice;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
public interface NoticeRepository extends JpaRepository<Notice, Long> { public interface NoticeRepository extends JpaRepository<Notice, Long> {
boolean existsByIdNoticeAndClientId(long noticeId, long clientId); boolean existsByIdNoticeAndClientId(long noticeId, long clientId);
}
}

View File

@@ -43,7 +43,7 @@ public class JwtRequestFilter extends OncePerRequestFilter {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json"); response.setContentType("application/json");
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
String jsonResponse = "{\"error\": \"Token is invalid or expired. Please login again.\"}"; String jsonResponse = "{\"error\": \"Token is invalid. Please login again.\"}";
response.getWriter().write(jsonResponse); response.getWriter().write(jsonResponse);
return; return;
} }
@@ -53,6 +53,7 @@ public class JwtRequestFilter extends OncePerRequestFilter {
} catch (ExpiredJwtException expiredJwtException) { } catch (ExpiredJwtException expiredJwtException) {
logger.error(expiredJwtException.getMessage()); logger.error(expiredJwtException.getMessage());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write(new RequestResponseDTO("Authentication token is expired. Please login again.").toJSON());
return; return;
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage()); logger.error(e.getMessage());

View File

@@ -82,6 +82,10 @@ public class JwtUtil {
return extractAllClaims(token).get("role", String.class); return extractAllClaims(token).get("role", String.class);
} }
public Long extractUserId(String token) {
return extractAllClaims(token).get("userId", Long.class);
}
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) { public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token); final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims); return claimsResolver.apply(claims);

View File

@@ -0,0 +1,117 @@
package _11.asktpk.artisanconnectbackend.service;
import _11.asktpk.artisanconnectbackend.customExceptions.ClientAlreadyExistsException;
import _11.asktpk.artisanconnectbackend.customExceptions.WrongLoginPasswordException;
import _11.asktpk.artisanconnectbackend.dto.AuthResponseDTO;
import _11.asktpk.artisanconnectbackend.dto.ClientDTO;
import _11.asktpk.artisanconnectbackend.entities.Client;
import _11.asktpk.artisanconnectbackend.security.JwtUtil;
import org.springframework.http.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Slf4j
@Service
public class AuthService {
private final ClientService clientService;
private final PasswordEncoder passwordEncoder;
private final JwtUtil jwtUtil;
public AuthService(ClientService clientService, JwtUtil jwtUtil) {
this.clientService = clientService;
this.jwtUtil = jwtUtil;
this.passwordEncoder = new BCryptPasswordEncoder();
}
public AuthResponseDTO login(String email, String password) throws Exception {
Client client = clientService.getClientByEmail(email);
if (client == null) {
throw new Exception("Klient o podanym adresie nie istnieje!");
}
if (passwordEncoder.matches(password, client.getPassword())) {
String token = jwtUtil.generateToken(client.getEmail(), client.getRole().getRole(), client.getId());
log.info("User logged in with {}", client.getEmail());
return new AuthResponseDTO(client.getId(), client.getRole().getRole(), token);
}
throw new WrongLoginPasswordException("Login lub hasło jest niepoprawny!");
}
public AuthResponseDTO register(String email, String password, String firstName, String lastName) throws Exception {
if (clientService.getClientByEmail(email) != null) {
throw new ClientAlreadyExistsException("Klient o podanym adresie email już istnieje!");
}
Client newClient = new Client();
newClient.setEmail(email);
newClient.setPassword(passwordEncoder.encode(password));
newClient.setFirstName(firstName);
newClient.setLastName(lastName);
ClientDTO savedClient = clientService.registerClient(newClient);
if (savedClient != null) {
log.info("New user registered with {}", savedClient.getEmail());
String token = jwtUtil.generateToken(
savedClient.getEmail(),
savedClient.getRole(),
savedClient.getId()
);
return new AuthResponseDTO(savedClient.getId(), savedClient.getRole(), token);
} else {
throw new Exception("Rejestracja nie powiodła się!");
}
}
public void logout(String token) {
jwtUtil.blacklistToken(token);
}
public AuthResponseDTO googleLogin(String googleAccessToken) throws Exception {
String googleUserInfoUrl = "https://www.googleapis.com/oauth2/v3/userinfo";
ResponseEntity<Map> response;
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(googleAccessToken);
RestTemplate restTemplate = new RestTemplate();
response = restTemplate.exchange(
googleUserInfoUrl, HttpMethod.GET, new HttpEntity<>(headers), Map.class);
Map<String, Object> userInfo = response.getBody();
// String googleId = (String) userInfo.get("sub"); Potencjalnie możemy używać googlowskiego ID, ale to ma konflikt z naszym generowanym
if (userInfo == null) {
throw new Exception("Pobrany użytkownik jest pusty! Może to być spowodowane niepoprawnym tokenem lub brakiem dostępu do Google API.");
}
String email = (String) userInfo.get("email");
String name = (String) userInfo.get("name");
Client client = clientService.getClientByEmail(email);
if (client == null) {
client = new Client();
client.setEmail(email);
client.setFirstName(name);
client.setRole(clientService.getUserRole()); // to pobiera po prostu role "USER" z tabeli w bazie
clientService.saveClientToDB(client);
}
String jwt = jwtUtil.generateToken(client.getEmail(), client.getRole().getRole(), client.getId());
log.info("User authenticated with google: {}", client.getEmail());
return new AuthResponseDTO(
client.getId(),
client.getRole().getRole(),
jwt
);
}
}

View File

@@ -1,6 +1,5 @@
package _11.asktpk.artisanconnectbackend.service; package _11.asktpk.artisanconnectbackend.service;
import _11.asktpk.artisanconnectbackend.dto.AuthRequestDTO;
import _11.asktpk.artisanconnectbackend.dto.ClientDTO; import _11.asktpk.artisanconnectbackend.dto.ClientDTO;
import _11.asktpk.artisanconnectbackend.dto.ClientRegistrationDTO; import _11.asktpk.artisanconnectbackend.dto.ClientRegistrationDTO;
import _11.asktpk.artisanconnectbackend.entities.Client; import _11.asktpk.artisanconnectbackend.entities.Client;
@@ -25,7 +24,7 @@ public class ClientService {
this.rolesRepository = rolesRepository; this.rolesRepository = rolesRepository;
} }
private ClientDTO toDto(Client client) { public ClientDTO toDto(Client client) {
if(client == null) { if(client == null) {
return null; return null;
} }
@@ -42,7 +41,7 @@ public class ClientService {
return dto; return dto;
} }
private Client fromDto(ClientDTO dto) { public Client fromDto(ClientDTO dto) {
Client client = new Client(); Client client = new Client();
Role rola; Role rola;
@@ -86,6 +85,14 @@ public class ClientService {
return toDto(clientRepository.findById(id).orElse(null)); return toDto(clientRepository.findById(id).orElse(null));
} }
public Client getClientByEmail(String email) {
return clientRepository.findByEmail(email);
}
public Role getUserRole() {
return rolesRepository.findRoleByRole("USER");
}
public boolean clientExists(Long id) { public boolean clientExists(Long id) {
return clientRepository.existsById(id); return clientRepository.existsById(id);
} }
@@ -117,29 +124,9 @@ public class ClientService {
clientRepository.deleteById(id); clientRepository.deleteById(id);
} }
// И замените метод checkClientCredentials на: public ClientDTO registerClient(Client client) {
public boolean checkClientCredentials(AuthRequestDTO dto) { client.setRole(getUserRole()); // ID 1 - USER role
Client cl = clientRepository.findByEmail(dto.getEmail());
if (cl == null) {
return false;
}
return passwordEncoder.matches(dto.getPassword(), cl.getPassword());
}
// При создании нового пользователя не забудьте шифровать пароль:
public ClientDTO registerClient(ClientRegistrationDTO clientDTO) {
Client client = fromDto(clientDTO);
client.setRole(rolesRepository.findRoleById(1L));
client.setPassword(passwordEncoder.encode(client.getPassword())); client.setPassword(passwordEncoder.encode(client.getPassword()));
return toDto(clientRepository.save(client)); return toDto(clientRepository.save(client));
} }
public Client getClientByEmail(String email) {
return clientRepository.findByEmail(email);
}
public Role getUserRole() {
return rolesRepository.findRoleByRole("USER");
}
} }

View File

@@ -1,10 +1,10 @@
package _11.asktpk.artisanconnectbackend.service; package _11.asktpk.artisanconnectbackend.service;
import _11.asktpk.artisanconnectbackend.entities.Client; import _11.asktpk.artisanconnectbackend.dto.AttributeDto;
import _11.asktpk.artisanconnectbackend.entities.Notice; import _11.asktpk.artisanconnectbackend.dto.NoticeRequestDTO;
import _11.asktpk.artisanconnectbackend.repository.ClientRepository; import _11.asktpk.artisanconnectbackend.entities.*;
import _11.asktpk.artisanconnectbackend.repository.NoticeRepository; import _11.asktpk.artisanconnectbackend.repository.*;
import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; import _11.asktpk.artisanconnectbackend.dto.NoticeResponseDTO;
import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.EntityNotFoundException;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -14,7 +14,6 @@ import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
@Service @Service
public class NoticeService { public class NoticeService {
@@ -25,25 +24,32 @@ public class NoticeService {
private final NoticeRepository noticeRepository; private final NoticeRepository noticeRepository;
private final ClientRepository clientRepository; private final ClientRepository clientRepository;
private final WishlistService wishlistService;
private final ImageService imageService; private final ImageService imageService;
private final AttributesRepository attributesRepository;
private final AttributeValuesRepository attributeValuesRepository;
private final AttributesNoticeRepository attributesNoticeRepository;
public NoticeService(NoticeRepository noticeRepository, ClientRepository clientRepository, WishlistService wishlistService, ImageService imageService) { public NoticeService(NoticeRepository noticeRepository,
ClientRepository clientRepository,
ImageService imageService,
AttributesRepository attributesRepository,
AttributeValuesRepository attributeValuesRepository,
AttributesNoticeRepository attributesNoticeRepository) {
this.noticeRepository = noticeRepository; this.noticeRepository = noticeRepository;
this.clientRepository = clientRepository; this.clientRepository = clientRepository;
this.wishlistService = wishlistService;
this.imageService = imageService; this.imageService = imageService;
this.attributesRepository = attributesRepository;
this.attributeValuesRepository = attributeValuesRepository;
this.attributesNoticeRepository = attributesNoticeRepository;
} }
public Notice fromDTO(NoticeDTO dto) { public Notice fromDTO(NoticeRequestDTO dto) {
Notice notice = new Notice(); Notice notice = new Notice();
notice.setTitle(dto.getTitle()); notice.setTitle(dto.getTitle());
notice.setDescription(dto.getDescription()); notice.setDescription(dto.getDescription());
notice.setPrice(dto.getPrice()); notice.setPrice(dto.getPrice());
notice.setCategory(dto.getCategory()); notice.setCategory(dto.getCategory());
notice.setStatus(dto.getStatus()); notice.setStatus(dto.getStatus());
notice.setPublishDate(dto.getPublishDate());
notice.setAttributesNotices(dto.getAttributesNotices());
Client client = clientRepository.findById(dto.getClientId()) Client client = clientRepository.findById(dto.getClientId())
.orElseThrow(() -> new EntityNotFoundException("Nie znaleziono klienta o ID: " + dto.getClientId())); .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono klienta o ID: " + dto.getClientId()));
@@ -52,15 +58,8 @@ public class NoticeService {
return notice; return notice;
} }
private NoticeDTO toDTO(Notice notice) { private NoticeResponseDTO toDTO(Notice notice) {
NoticeDTO dto = new NoticeDTO(); NoticeResponseDTO dto = new NoticeResponseDTO();
// TODO: To be updated using AuthService after implementing authentication.
Optional<Client> client = clientRepository.findById(1L);
boolean isWishlisted = false;
if (client.isPresent()) {
Client c = client.get();
isWishlisted = wishlistService.isWishlisted(c, notice);
}
dto.setNoticeId(notice.getIdNotice()); dto.setNoticeId(notice.getIdNotice());
dto.setTitle(notice.getTitle()); dto.setTitle(notice.getTitle());
dto.setClientId(notice.getClient().getId()); dto.setClientId(notice.getClient().getId());
@@ -69,20 +68,30 @@ public class NoticeService {
dto.setCategory(notice.getCategory()); dto.setCategory(notice.getCategory());
dto.setStatus(notice.getStatus()); dto.setStatus(notice.getStatus());
dto.setPublishDate(notice.getPublishDate()); dto.setPublishDate(notice.getPublishDate());
dto.setAttributesNotices(notice.getAttributesNotices());
dto.setWishlisted(isWishlisted); List<AttributeDto> attributes = new ArrayList<>();
if (notice.getAttributesNotices() != null) {
for (AttributesNotice an : notice.getAttributesNotices()) {
AttributeDto attr = new AttributeDto();
attr.setName(an.getAttributeValue().getAttribute().getName());
attr.setValue(an.getAttributeValue().getValue());
attributes.add(attr);
}
}
dto.setAttributes(attributes);
return dto; return dto;
} }
public List<NoticeDTO> getAllNotices() { public List<NoticeResponseDTO> getAllNotices() {
List<NoticeDTO> result = new ArrayList<>(); List<NoticeResponseDTO> result = new ArrayList<>();
for (Notice notice : noticeRepository.findAll()) { for (Notice notice : noticeRepository.findAll()) {
result.add(toDTO(notice)); result.add(toDTO(notice));
} }
return result; return result;
} }
public NoticeDTO getNoticeById(Long id) { public NoticeResponseDTO getNoticeById(Long id) {
Notice notice = noticeRepository.findById(id) Notice notice = noticeRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id)); .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id));
return toDTO(notice); return toDTO(notice);
@@ -93,15 +102,48 @@ public class NoticeService {
.orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id)); .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id));
} }
public Long addNotice(NoticeDTO dto) { public Long addNotice(NoticeRequestDTO dto) {
return noticeRepository.save(fromDTO(dto)).getIdNotice(); Notice notice = fromDTO(dto);
notice.setPublishDate(LocalDateTime.now());
Notice savedNotice = noticeRepository.save(notice);
if (dto.getAttributes() != null && !dto.getAttributes().isEmpty()) {
saveAttributes(savedNotice.getIdNotice(), dto.getAttributes());
}
return savedNotice.getIdNotice();
}
private void saveAttributes(Long noticeId, List<AttributeDto> attributeDtos) {
for (AttributeDto attributeDto : attributeDtos) {
Attributes attribute = attributesRepository.findByName(attributeDto.getName())
.orElseGet(() -> {
Attributes newAttribute = new Attributes();
newAttribute.setName(attributeDto.getName());
return attributesRepository.save(newAttribute);
});
AttributeValues attributeValue = attributeValuesRepository
.findByAttributeAndValue(attribute, attributeDto.getValue())
.orElseGet(() -> {
AttributeValues newValue = new AttributeValues();
newValue.setAttribute(attribute);
newValue.setValue(attributeDto.getValue());
return attributeValuesRepository.save(newValue);
});
AttributesNotice attributesNotice = new AttributesNotice();
attributesNotice.setNotice_id(noticeId);
attributesNotice.setAttributeValue(attributeValue);
attributesNoticeRepository.save(attributesNotice);
}
} }
public boolean noticeExists(Long id) { public boolean noticeExists(Long id) {
return noticeRepository.existsById(id); return noticeRepository.existsById(id);
} }
public NoticeDTO updateNotice(Long id, NoticeDTO dto) { public NoticeResponseDTO updateNotice(Long id, NoticeRequestDTO dto) {
Notice existingNotice = noticeRepository.findById(id) Notice existingNotice = noticeRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id)); .orElseThrow(() -> new EntityNotFoundException("Nie znaleziono ogłoszenia o ID: " + id));
@@ -110,7 +152,6 @@ public class NoticeService {
existingNotice.setPrice(dto.getPrice()); existingNotice.setPrice(dto.getPrice());
existingNotice.setCategory(dto.getCategory()); existingNotice.setCategory(dto.getCategory());
existingNotice.setStatus(dto.getStatus()); existingNotice.setStatus(dto.getStatus());
existingNotice.setAttributesNotices(dto.getAttributesNotices());
if (dto.getClientId() != null && !dto.getClientId().equals(existingNotice.getClient().getId())) { if (dto.getClientId() != null && !dto.getClientId().equals(existingNotice.getClient().getId())) {
Client client = clientRepository.findById(dto.getClientId()) Client client = clientRepository.findById(dto.getClientId())

View File

@@ -56,8 +56,7 @@ public class OrderService {
public Long addOrder(OrderDTO orderDTO) { public Long addOrder(OrderDTO orderDTO) {
Order order = fromDTO(orderDTO); return orderRepository.save(fromDTO(orderDTO)).getId();
return orderRepository.save(order).getId();
} }
public Long changeOrderStatus(Long id, Enums.OrderStatus status) { public Long changeOrderStatus(Long id, Enums.OrderStatus status) {

View File

@@ -1,7 +1,7 @@
package _11.asktpk.artisanconnectbackend.service; package _11.asktpk.artisanconnectbackend.service;
import _11.asktpk.artisanconnectbackend.dto.WishlistDTO; import _11.asktpk.artisanconnectbackend.dto.WishlistDTO;
import _11.asktpk.artisanconnectbackend.dto.NoticeDTO; import _11.asktpk.artisanconnectbackend.dto.NoticeResponseDTO;
import _11.asktpk.artisanconnectbackend.entities.Client; import _11.asktpk.artisanconnectbackend.entities.Client;
import _11.asktpk.artisanconnectbackend.entities.Notice; import _11.asktpk.artisanconnectbackend.entities.Notice;
import _11.asktpk.artisanconnectbackend.entities.Wishlist; import _11.asktpk.artisanconnectbackend.entities.Wishlist;
@@ -31,12 +31,6 @@ public class WishlistService {
.toList(); .toList();
} }
public boolean isWishlisted(Client client, Notice notice) {
Optional<Wishlist> existingEntry = wishlistRepository.findByClientAndNotice(client, notice);
return existingEntry.isEmpty();
}
public boolean toggleWishlist(Client client, Notice notice) { public boolean toggleWishlist(Client client, Notice notice) {
Optional<Wishlist> existingEntry = wishlistRepository.findByClientAndNotice(client, notice); Optional<Wishlist> existingEntry = wishlistRepository.findByClientAndNotice(client, notice);
@@ -61,7 +55,7 @@ public class WishlistService {
return dto; return dto;
} }
public List<NoticeDTO> getNoticesInWishlist(Long clientId) { public List<NoticeResponseDTO> getNoticesInWishlist(Long clientId) {
List<Wishlist> wishlistEntries = wishlistRepository.findAllByClientId(clientId); List<Wishlist> wishlistEntries = wishlistRepository.findAllByClientId(clientId);
return wishlistEntries.stream() return wishlistEntries.stream()

View File

@@ -0,0 +1,24 @@
package _11.asktpk.artisanconnectbackend.utils;
import _11.asktpk.artisanconnectbackend.security.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
@Component
public class Tools {
private final JwtUtil jwtUtil;
public Tools(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
public Long getClientIdFromRequest(HttpServletRequest request) {
String authorizationHeader = request.getHeader("Authorization");
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
return jwtUtil.extractUserId(authorizationHeader.substring(7));
} else {
return -1L;
}
}
}

View File

@@ -17,4 +17,45 @@ INSERT INTO notice (title, description, client_id, price, category, status, publ
('Drewniany stół', 'Solidny stół wykonany z litego drewna dębowego.', 3, 1200.00, 'Furniture', 'ACTIVE', '2023-09-15'), ('Drewniany stół', 'Solidny stół wykonany z litego drewna dębowego.', 3, 1200.00, 'Furniture', 'ACTIVE', '2023-09-15'),
('Ceramiczna waza', 'Piękna waza ceramiczna, idealna na prezent.', 2, 300.00, 'Ceramics', 'INACTIVE', '2023-08-20'), ('Ceramiczna waza', 'Piękna waza ceramiczna, idealna na prezent.', 2, 300.00, 'Ceramics', 'INACTIVE', '2023-08-20'),
('Obraz olejny', 'Obraz olejny przedstawiający krajobraz górski.', 4, 800.00, 'Painting', 'ACTIVE', '2023-07-10'), ('Obraz olejny', 'Obraz olejny przedstawiający krajobraz górski.', 4, 800.00, 'Painting', 'ACTIVE', '2023-07-10'),
('Skórzany portfel', 'Ręcznie wykonany portfel ze skóry naturalnej.', 1, 250.00, 'Leatherwork', 'ACTIVE', '2023-06-05'); ('Skórzany portfel', 'Ręcznie wykonany portfel ze skóry naturalnej.', 1, 250.00, 'Leatherwork', 'ACTIVE', '2023-06-05');
insert into attributes (name) values
('Kolor'),
('Materiał');
-- Kolory
insert into attribute_values (value, id_attribute) values
('Zielony', 1),
('Czerwony', 1),
('Niebieski', 1),
('Żółty', 1),
('Biały', 1),
('Czarny', 1),
('Różowy', 1),
('Szary', 1),
('Fioletowy', 1),
('Pomarańczowy', 1),
('Inny', 1);
-- Materiały
insert into attribute_values (value, id_attribute) values
('Bawełna', 2),
('Wełna', 2),
('Syntetyk', 2),
('Skóra', 2),
('Len', 2),
('Jedwab', 2),
('Poliester', 2),
('Akryl', 2),
('Wiskoza', 2),
('Nylon', 2),
('Inny', 2);
insert into attributes_notice (id_value, notice_id) values
(1, 1), -- Ręcznie robiona biżuteria - Zielony
(22, 1),
(2, 2), -- Drewniany stół - Czerwony
(3, 3), -- Ceramiczna waza - Niebieski
(4, 4), -- Obraz olejny - Żółty
(5, 5); -- Skórzany portfel - Biały