From 4df33663d8030935b179e81afd31b0f8d86da219 Mon Sep 17 00:00:00 2001 From: Ksan Date: Tue, 12 May 2026 21:25:30 +0200 Subject: [PATCH] changed some stuff lol --- compose.yaml | 2 +- init.sql | 16 +++-- .../EtfoglasiServerApplication.java | 17 +++-- .../controller/SubjectController.java | 2 +- .../controller/UserController.java | 45 ++++++++---- .../etfoglasiserver/dto/JwtResponseDTO.java | 10 ++- .../etfoglasiserver/dto/UserCreationDTO.java | 8 --- .../dev/ksan/etfoglasiserver/dto/UserDTO.java | 7 -- .../dev/ksan/etfoglasiserver/model/User.java | 2 +- .../etfoglasiserver/service/JWTService.java | 1 + .../ksan/etfoglasiserver/service/Scraper.java | 5 ++ .../service/SubjectService.java | 5 ++ .../etfoglasiserver/service/UserService.java | 71 +++++++++++++++---- 13 files changed, 130 insertions(+), 61 deletions(-) diff --git a/compose.yaml b/compose.yaml index 198b6de..3ffe9ef 100644 --- a/compose.yaml +++ b/compose.yaml @@ -8,6 +8,6 @@ services: - 'POSTGRES_USER=test' volumes: - ./init.sql:/docker-entrypoint-initdb.d/init.sql - - .db:/var/lib/postgresql/data + - ./.db:/var/lib/postgresql/data ports: - '5432:5432' diff --git a/init.sql b/init.sql index dda85d4..607a075 100644 --- a/init.sql +++ b/init.sql @@ -1,5 +1,6 @@ -- This script was generated by the ERD tool in pgAdmin 4. -- Please log an issue at https://github.com/pgadmin-org/pgadmin4/issues/new/choose if you find any bugs, including reproduction steps. +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; BEGIN; @@ -12,16 +13,19 @@ CREATE TABLE IF NOT EXISTS public.alt_subject CONSTRAINT alt_subject_name_key UNIQUE (name) ); + + CREATE TABLE IF NOT EXISTS public.entries ( - id text COLLATE pg_catalog."default" NOT NULL, + id uuid NOT NULL, subject_id uuid NOT NULL, - title text COLLATE pg_catalog."default", - info_entry text COLLATE pg_catalog."default", - paragraph text COLLATE pg_catalog."default", + title text, + info_entry text, + paragraph text, time_published timestamp without time zone NOT NULL, - filepath text COLLATE pg_catalog."default", - group_name text COLLATE pg_catalog."default", + filepath text, + group_name text, + CONSTRAINT entries_pkey PRIMARY KEY (id) ); diff --git a/src/main/java/dev/ksan/etfoglasiserver/EtfoglasiServerApplication.java b/src/main/java/dev/ksan/etfoglasiserver/EtfoglasiServerApplication.java index 5da02ba..920aa6d 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/EtfoglasiServerApplication.java +++ b/src/main/java/dev/ksan/etfoglasiserver/EtfoglasiServerApplication.java @@ -3,6 +3,7 @@ package dev.ksan.etfoglasiserver; import dev.ksan.etfoglasiserver.service.Scraper; import java.util.Scanner; +import dev.ksan.etfoglasiserver.service.SubjectService; import dev.ksan.etfoglasiserver.util.SubjectLoader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; @@ -21,16 +22,18 @@ public class EtfoglasiServerApplication { Scraper scraper = context.getBean(Scraper.class); -/* - SubjectLoader subjectLoader = context.getBean(SubjectLoader.class); + SubjectService subjectService = context.getBean(SubjectService.class); - subjectLoader.loadSubjects(); + if (subjectService.count() <= 1) { + SubjectLoader subjectLoader = context.getBean(SubjectLoader.class); - System.out.println("Loading..."); - subjectLoader.loadAlts(); + subjectLoader.loadSubjects(); - - */ + System.out.println("Loading..."); + subjectLoader.loadAlts(); + } else { + System.out.println("Subjects already loaded, skipping..."); + } Thread webClientThread = new Thread(scraper, "WebClientThread"); Scanner scanner = new Scanner(System.in); diff --git a/src/main/java/dev/ksan/etfoglasiserver/controller/SubjectController.java b/src/main/java/dev/ksan/etfoglasiserver/controller/SubjectController.java index 1400f33..571c7a6 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/controller/SubjectController.java +++ b/src/main/java/dev/ksan/etfoglasiserver/controller/SubjectController.java @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.RestController; public class SubjectController { @Autowired SubjectService service; - @GetMapping("/subject") + @GetMapping("/subjects") public List getSubjects() { return service.getSubjects(); } diff --git a/src/main/java/dev/ksan/etfoglasiserver/controller/UserController.java b/src/main/java/dev/ksan/etfoglasiserver/controller/UserController.java index af0aebb..6f38073 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/controller/UserController.java +++ b/src/main/java/dev/ksan/etfoglasiserver/controller/UserController.java @@ -18,12 +18,12 @@ public class UserController { @Autowired UserService service; - @GetMapping("/users") - public ResponseEntity> getUsers() { - - return new ResponseEntity(service.getUsers(), HttpStatus.OK); - } - +// @GetMapping("/users") +// public ResponseEntity> getUsers() { +// +// return new ResponseEntity(service.getUsers(), HttpStatus.OK); +// } +// @GetMapping("users/{userId}") public ResponseEntity getUserById(@PathVariable UUID userId) { @@ -38,8 +38,6 @@ public class UserController { @PutMapping("/users") public ResponseEntity updateUser(@RequestBody UserCreationDTO user) { - NotificationMethod method = NotificationMethod.valueOf(user.getNotification()); - user.setNotificationMethod(method); UserDTO userUpdated = service.updateUser(user); if (userUpdated != null) { return new ResponseEntity<>(userUpdated, HttpStatus.OK); @@ -47,6 +45,27 @@ public class UserController { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } + @PutMapping("/users/{userId}/subjects/{subjectId}") + public ResponseEntity addSubject( + @PathVariable UUID userId, + @PathVariable UUID subjectId + ) { + + UserDTO updatedUser = service.addSubject(userId, subjectId); + + return ResponseEntity.ok(updatedUser); + } + + @DeleteMapping("/users/{userId}/subjects/{subjectId}") + public ResponseEntity removeSubject( + @PathVariable UUID userId, + @PathVariable UUID subjectId + ) { + + UserDTO updatedUser = service.removeSubject(userId, subjectId); + + return ResponseEntity.ok(updatedUser); + } @PostMapping("/login") public ResponseEntity login(@RequestBody UserLoginDTO user) { @@ -63,11 +82,11 @@ public class UserController { if (newUser != null) return new ResponseEntity<>(newUser, HttpStatus.CREATED); return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } - - @DeleteMapping("/users/{userId}") - public void deleteUser(@PathVariable UUID userId) { - service.deleteUser(userId); - } +// +// @DeleteMapping("/users/{userId}") +// public void deleteUser(@PathVariable UUID userId) { +// service.deleteUser(userId); +// } /* @PostMapping("/users") diff --git a/src/main/java/dev/ksan/etfoglasiserver/dto/JwtResponseDTO.java b/src/main/java/dev/ksan/etfoglasiserver/dto/JwtResponseDTO.java index 1d649ea..8ac15d0 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/dto/JwtResponseDTO.java +++ b/src/main/java/dev/ksan/etfoglasiserver/dto/JwtResponseDTO.java @@ -4,15 +4,21 @@ public class JwtResponseDTO { private String token; private String email; + private String userId; private String message; - public JwtResponseDTO(String token, String email, String message) { + public JwtResponseDTO(String token, String email, String userId, String message) { this.token = token; this.email = email; + this.userId = userId; this.message = message; } - public String getToken() { + public String getUserId() { + return userId; + } + + public String getToken() { return token; } diff --git a/src/main/java/dev/ksan/etfoglasiserver/dto/UserCreationDTO.java b/src/main/java/dev/ksan/etfoglasiserver/dto/UserCreationDTO.java index 8388f30..d5db0c4 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/dto/UserCreationDTO.java +++ b/src/main/java/dev/ksan/etfoglasiserver/dto/UserCreationDTO.java @@ -11,7 +11,6 @@ public class UserCreationDTO { private String password; private Set subjectSet; private String notification; - private NotificationMethod notificationMethod; public String getEmail() { return email; @@ -54,11 +53,4 @@ public class UserCreationDTO { } - public void setNotificationMethod(NotificationMethod method) { - - this.notificationMethod = method; - } - public NotificationMethod getNotificationMethod() { - return notificationMethod; - } } diff --git a/src/main/java/dev/ksan/etfoglasiserver/dto/UserDTO.java b/src/main/java/dev/ksan/etfoglasiserver/dto/UserDTO.java index 3c0eebf..3bdb5c8 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/dto/UserDTO.java +++ b/src/main/java/dev/ksan/etfoglasiserver/dto/UserDTO.java @@ -9,7 +9,6 @@ public class UserDTO { private UUID id; private String email; private Set subjectSet; - private NotificationMethod notificationMethod; public UserDTO() {} @@ -44,11 +43,5 @@ public class UserDTO { this.subjectSet = subjectSet; } - public NotificationMethod getNotificationMethod() { - return notificationMethod; - } - public void setNotificationMethod(NotificationMethod notificationMethod) { - this.notificationMethod = notificationMethod; - } } diff --git a/src/main/java/dev/ksan/etfoglasiserver/model/User.java b/src/main/java/dev/ksan/etfoglasiserver/model/User.java index 5f408e2..8721f28 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/model/User.java +++ b/src/main/java/dev/ksan/etfoglasiserver/model/User.java @@ -31,7 +31,7 @@ public class User { @Column(name = "notification_type", nullable = false) private NotificationMethod notificationType = NotificationMethod.NO_NOTIFICATION; - @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @ManyToMany(fetch = FetchType.LAZY ) @JoinTable(name = "user-subject", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "subject_id")) private Set subjectSet; diff --git a/src/main/java/dev/ksan/etfoglasiserver/service/JWTService.java b/src/main/java/dev/ksan/etfoglasiserver/service/JWTService.java index 578a619..64d95ba 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/service/JWTService.java +++ b/src/main/java/dev/ksan/etfoglasiserver/service/JWTService.java @@ -18,6 +18,7 @@ import org.springframework.stereotype.Service; @Service public class JWTService { + //TODO add persistent token env variable private String secretKey = ""; private JWTService() { diff --git a/src/main/java/dev/ksan/etfoglasiserver/service/Scraper.java b/src/main/java/dev/ksan/etfoglasiserver/service/Scraper.java index 1cde60d..5a4010b 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/service/Scraper.java +++ b/src/main/java/dev/ksan/etfoglasiserver/service/Scraper.java @@ -20,6 +20,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; + +// This exists because i made it a while ago and I just kept it just because +// should probably move to just hitting the endpoints directly instead of digging through the html manually + + @Component public class Scraper implements Runnable { diff --git a/src/main/java/dev/ksan/etfoglasiserver/service/SubjectService.java b/src/main/java/dev/ksan/etfoglasiserver/service/SubjectService.java index 49fab97..db6cc42 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/service/SubjectService.java +++ b/src/main/java/dev/ksan/etfoglasiserver/service/SubjectService.java @@ -90,4 +90,9 @@ public class SubjectService { public void sendPushNotification(Entry entry,User user) { System.out.println("Sending push notification"); } + + public long count() { + + return subjectRepo.count(); + } } diff --git a/src/main/java/dev/ksan/etfoglasiserver/service/UserService.java b/src/main/java/dev/ksan/etfoglasiserver/service/UserService.java index 40af35f..9f34ff2 100644 --- a/src/main/java/dev/ksan/etfoglasiserver/service/UserService.java +++ b/src/main/java/dev/ksan/etfoglasiserver/service/UserService.java @@ -4,8 +4,9 @@ import dev.ksan.etfoglasiserver.dto.JwtResponseDTO; import dev.ksan.etfoglasiserver.dto.UserCreationDTO; import dev.ksan.etfoglasiserver.dto.UserDTO; import dev.ksan.etfoglasiserver.dto.UserLoginDTO; +import dev.ksan.etfoglasiserver.model.Subject; import dev.ksan.etfoglasiserver.model.User; -import dev.ksan.etfoglasiserver.model.UserPrincipal; +import dev.ksan.etfoglasiserver.repository.SubjectRepo; import dev.ksan.etfoglasiserver.repository.UserRepo; import java.util.List; @@ -19,8 +20,6 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,12 +27,18 @@ import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class UserService { + @Autowired + SubjectRepo subjectRepo; + @Autowired UserRepo userRepo; @Autowired private AuthenticationManager authManager; @Autowired private JWTService jwtService; + + + private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); public List getUsers() { @@ -70,10 +75,10 @@ public class UserService { if (user.getPassword() != null && user.getPassword().length() > 0) { if (this.isValidPassword(user.getPassword())) { - existingUser.setPassword(user.getPassword()); + existingUser.setPassword(encoder.encode(user.getPassword())); } else throw new RuntimeException("Password too short"); } - if (user.getNewEmail() != null && user.getNewEmail() != existingUser.getEmail()) { + if (user.getNewEmail() != null && !user.getNewEmail().equals(existingUser.getEmail())) { existingUser.setEmail(user.getNewEmail()); } else { @@ -83,8 +88,6 @@ public class UserService { existingUser.setSubjectSet(user.getSubjectSet()); - existingUser.setNotificationMethod(user.getNotificationMethod()); - userRepo.save(existingUser); return getUserDTO(existingUser); @@ -139,24 +142,62 @@ public class UserService { throw new RuntimeException("Invalid email"); } - public JwtResponseDTO verify(UserLoginDTO user) { + public JwtResponseDTO verify(UserLoginDTO user) { + Authentication authentication = authManager.authenticate( + new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()) + ); - Authentication authentication = authManager.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword())); + if (!authentication.isAuthenticated()) { + throw new BadCredentialsException("Invalid username or password"); + } - if (authentication.isAuthenticated()) { + String token = jwtService.generateToken(user.getEmail()); - String token = jwtService.generateToken(user.getEmail()); - return new JwtResponseDTO(token, user.getEmail(), HttpStatus.OK.toString()); - } else { + User foundUser = userRepo.findByEmail(user.getEmail()) + .orElseThrow(() -> new RuntimeException("User not found after authentication")); - throw new BadCredentialsException("Invalid username or password"); + return new JwtResponseDTO( + token, + foundUser.getEmail(), + foundUser.getId().toString(), + HttpStatus.OK.toString() + ); } - } public Optional getAccountByEmail(String email) { return userRepo.findByEmail(email); } + public UserDTO addSubject(UUID userId, UUID subjectId) { + + User user = userRepo.findById(userId) + .orElseThrow(() -> new RuntimeException("User not found")); + + Subject subject = subjectRepo.findById(subjectId) + .orElseThrow(() -> new RuntimeException("Subject not found")); + + user.getSubjectSet().add(subject); + + userRepo.save(user); + + return getUserDTO(user); + } + + public UserDTO removeSubject(UUID userId, UUID subjectId) { + + User user = userRepo.findById(userId) + .orElseThrow(() -> new RuntimeException("User not found")); + + Subject subject = subjectRepo.findById(subjectId) + .orElseThrow(() -> new RuntimeException("Subject not found")); + + + user.getSubjectSet().remove(subject); + + userRepo.save(user); + + return getUserDTO(user); + } }