From 5325d6e3aedce36793157dde97cbc72b3a173481 Mon Sep 17 00:00:00 2001 From: Bartha Maxime <231026@umons.ac.be> Date: Mon, 11 Mar 2024 17:52:08 +0100 Subject: [PATCH 1/2] Storage System (#92) First idea of the storage system Reviewed-on: https://git.herisson.ovh/PGL/Clyde/pulls/92 Co-authored-by: Bartha Maxime <231026@umons.ac.be> Co-committed-by: Bartha Maxime <231026@umons.ac.be> --- .../Clyde/EndPoints/StorageController.java | 32 ++++++++++ .../Clyde/EndPoints/UserController.java | 2 +- .../Clyde/Repositories/FileRepository.java | 9 +++ .../Clyde/Services/StorageService.java | 56 +++++++++++++++++ .../ovh/herisson/Clyde/Tables/FileType.java | 8 +++ .../herisson/Clyde/Tables/StorageFile.java | 63 +++++++++++++++++++ .../java/ovh/herisson/Clyde/Tables/User.java | 4 +- 7 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java new file mode 100644 index 0000000..2a36657 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java @@ -0,0 +1,32 @@ +package ovh.herisson.Clyde.EndPoints; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import ovh.herisson.Clyde.Services.StorageService; +import org.springframework.core.io.Resource; +import ovh.herisson.Clyde.Tables.FileType; + +@RestController +@CrossOrigin(origins = "http://localhost:5173") +public class StorageController { + + private final StorageService storageServ; + + public StorageController(StorageService storageServ){ + this.storageServ= storageServ; + } + + + @PostMapping("/upload/{fileType}") + public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file, @PathVariable FileType fileType) { + + String path = storageServ.store(file,fileType); + + if (path == null) return new ResponseEntity<>("issue with the file storage", HttpStatus.BAD_REQUEST); + + return new ResponseEntity<>(path, HttpStatus.OK); + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java index 8de166e..43bcd0c 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java @@ -31,7 +31,7 @@ public class UserController { return new ResponseEntity<>(user, HttpStatus.OK); } - @PostMapping("/user") + @PostMapping("/user") //todo check role public ResponseEntity postUser(@RequestBody User user){ userService.save(user); return new ResponseEntity<>(String.format("Account created with ID:%s",user.getRegNo()),HttpStatus.CREATED); diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java new file mode 100644 index 0000000..2240c92 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/FileRepository.java @@ -0,0 +1,9 @@ +package ovh.herisson.Clyde.Repositories; + +import org.springframework.data.repository.CrudRepository; + +import ovh.herisson.Clyde.Tables.StorageFile; + + +public interface FileRepository extends CrudRepository { +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java new file mode 100644 index 0000000..77dff70 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java @@ -0,0 +1,56 @@ +package ovh.herisson.Clyde.Services; + +import org.springframework.core.io.UrlResource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import ovh.herisson.Clyde.Repositories.FileRepository; +import ovh.herisson.Clyde.Tables.FileType; +import ovh.herisson.Clyde.Tables.StorageFile; +import java.io.IOException; +import org.springframework.core.io.Resource; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Objects; +import java.util.UUID; + +@Service +public class StorageService { + + + private final Path rootLocation = Paths.get("cdn/"); + private final FileRepository fileRepo; + + public StorageService(FileRepository filerepo){ + this.fileRepo = filerepo; + } + + + public String store(MultipartFile file, FileType fileType) { + + if (file.getOriginalFilename().isEmpty()){return null;} + + UUID uuid = UUID.randomUUID(); + String stringUuid = uuid + "." + file.getOriginalFilename().split("\\.",2)[1]; + try { + if (file.isEmpty()) { + return null; + } + + Path destinationFile = this.rootLocation.resolve(Paths.get(stringUuid)); + + Files.copy(file.getInputStream(), destinationFile,StandardCopyOption.REPLACE_EXISTING); + } + catch (IOException e) { + return null; + } + + String url = this.rootLocation.resolve(Paths.get(Objects.requireNonNull(stringUuid))) + .normalize().toString(); + + fileRepo.save(new StorageFile(file.getName(),url, fileType)); + + return url; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java new file mode 100644 index 0000000..18ce1be --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/FileType.java @@ -0,0 +1,8 @@ +package ovh.herisson.Clyde.Tables; + +public enum FileType { + + ProfilePicture, + + EducationCertificate +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java new file mode 100644 index 0000000..a96d0ec --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java @@ -0,0 +1,63 @@ +package ovh.herisson.Clyde.Tables; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + + +@Entity +public class StorageFile { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + private String url; + + private FileType fileType; + + + public StorageFile(String name, String url, FileType fileType){ + this.name = name; + this.url = url; + this.fileType = fileType; + } + + public StorageFile(){} + + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public FileType getFileType() { + return fileType; + } + + public void setFileType(FileType fileType) { + this.fileType = fileType; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java index 95467a4..101ec9e 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java @@ -23,7 +23,9 @@ public class User { private String profilePictureUrl; private ovh.herisson.Clyde.Tables.Role role; private String password; - public User(String lastName, String firstName, String email, String address, String country, Date birthDate, String profilePictureUrl, Role role, String password){ + public User(String lastName, String firstName, String email, String address, + String country, Date birthDate, String profilePictureUrl, Role role, String password) + { this.lastName = lastName; this.firstName = firstName; this.email = email; From d4c48ee9f187ccce6d174df81aa2cfc6f5c4eaaf Mon Sep 17 00:00:00 2001 From: LeoMoulin Date: Mon, 11 Mar 2024 19:16:19 +0100 Subject: [PATCH 2/2] Leo/Backend (#82) Ce merge enverra dans main : le timeout des token, la limite de 5 token par user, les nouvelles tables pour les demandes d'inscriptions Co-authored-by: Anthony Debucquoy Reviewed-on: https://git.herisson.ovh/PGL/Clyde/pulls/82 Reviewed-by: Debucquoy Anthony Reviewed-by: Maxime <231026@umons.ac.be> Reviewed-by: Wal Co-authored-by: LeoMoulin Co-committed-by: LeoMoulin --- .../Clyde/EndPoints/MockController.java | 15 ++- .../java/ovh/herisson/Clyde/JdbcConfig.java | 2 + .../Clyde/Repositories/TokenRepository.java | 3 + .../Clyde/Services/AuthenticatorService.java | 3 +- .../herisson/Clyde/Services/TokenService.java | 33 +++++- .../Clyde/Tables/InscriptionRequest.java | 108 ++++++++++++++++++ .../Clyde/Tables/ReinscriptionRequest.java | 69 +++++++++++ .../herisson/Clyde/Tables/RequestState.java | 7 ++ .../java/ovh/herisson/Clyde/Tables/Token.java | 17 ++- .../java/ovh/herisson/Clyde/Tables/User.java | 1 + 10 files changed, 244 insertions(+), 14 deletions(-) create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java index 18fea23..b140057 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java @@ -7,12 +7,14 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import ovh.herisson.Clyde.Repositories.TokenRepository; import ovh.herisson.Clyde.Repositories.UserRepository; +import ovh.herisson.Clyde.Services.TokenService; import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.User; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Date; @RestController @@ -23,13 +25,14 @@ public class MockController { public final UserRepository userRepo; public final TokenRepository tokenRepo; - + public final TokenService tokenService; ArrayList mockUsers; - public MockController(UserRepository userRepo, TokenRepository tokenRepo){ + public MockController(UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService){ this.tokenRepo = tokenRepo; this.userRepo = userRepo; + this.tokenService = tokenService; } /** Saves an example of each user type by : @@ -41,10 +44,10 @@ public class MockController { @PostMapping("/mock") public void postMock(){ - User herobrine = new User("brine","hero","admin@admin.com","in your WalLs","ShadowsLand",new Date(0), "none",Role.Admin,passwordEncoder.encode("admin")); - User joe = new User("Mama","Joe","student@student.com","roundabout","DaWarudo",new Date(0), "None",Role.Student,passwordEncoder.encode("student")); - User meh = new User("Inspiration","lackOf","secretary@secretary.com","a Box","the street",new Date(0),"none", Role.Teacher,passwordEncoder.encode("secretary")); - User joke = new User("CthemBalls","Lemme","teacher@teacher.com","lab","faculty",new Date(0), "none",Role.Teacher,passwordEncoder.encode("teacher")); + User herobrine = new User("brine","hero","admin@admin.com","in your WalLs","ShadowsLand",new Date(0), null,Role.Admin,passwordEncoder.encode("admin")); + User joe = new User("Mama","Joe","student@student.com","roundabout","DaWarudo",new Date(0), null,Role.Student,passwordEncoder.encode("student")); + User meh = new User("Inspiration","lackOf","secretary@secretary.com","a Box","the street",new Date(0), null,Role.Teacher,passwordEncoder.encode("secretary")); + User joke = new User("CthemBalls","Lemme","teacher@teacher.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher")); mockUsers = new ArrayList(Arrays.asList(herobrine,joe,meh,joke)); diff --git a/backend/src/main/java/ovh/herisson/Clyde/JdbcConfig.java b/backend/src/main/java/ovh/herisson/Clyde/JdbcConfig.java index b6525dc..6df0b74 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/JdbcConfig.java +++ b/backend/src/main/java/ovh/herisson/Clyde/JdbcConfig.java @@ -6,8 +6,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.scheduling.annotation.EnableScheduling; @Configuration +@EnableScheduling public class JdbcConfig { @Bean diff --git a/backend/src/main/java/ovh/herisson/Clyde/Repositories/TokenRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/TokenRepository.java index 6a4e47a..d3b422a 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Repositories/TokenRepository.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/TokenRepository.java @@ -4,10 +4,13 @@ import org.springframework.data.repository.CrudRepository; import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.User; +import java.util.ArrayList; + public interface TokenRepository extends CrudRepository { Token getByToken(String token); Iterable getByUser(User user); + ArrayList getByUserOrderByExpirationDate(User user); } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java index f3ae072..4cd1939 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java @@ -1,6 +1,7 @@ package ovh.herisson.Clyde.Services; import org.springframework.stereotype.Service; +import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.User; import java.util.Date; @@ -26,7 +27,7 @@ public class AuthenticatorService { if (user == null){return null;} if (!userService.checkPassword(user,password)){return null;} String token = tokenService.generateNewToken(); - tokenService.saveToken(token,user,expirationDate); + tokenService.saveToken(new Token(user, token,expirationDate)); return token; } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java index 125dbde..50ddcbf 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java @@ -1,19 +1,19 @@ package ovh.herisson.Clyde.Services; - +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import ovh.herisson.Clyde.Repositories.TokenRepository; import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.User; import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; @Service public class TokenService { - TokenRepository tokenRepo; public TokenService(TokenRepository tokenRepo){ @@ -48,7 +48,28 @@ public class TokenService { return tokenRep.getUser(); } - public void saveToken(String token, User user, Date expirationDate){// todo faire qlq chose de l'expDate - tokenRepo.save(new Token(user,token)); + public void saveToken(Token token){ + //Si l'utilisateur a déja 5 token delete celui qui devait expirer le plus vite + ArrayList tokenList = tokenRepo.getByUserOrderByExpirationDate(token.getUser()); + while(tokenList.size() >= 5){ + tokenRepo.delete(tokenList.get(0)); + tokenList.remove(tokenList.get(0)); + } + tokenRepo.save(token); } -} \ No newline at end of file + + //Tous les jours a minuit + @Scheduled(cron = "0 0 0 * * ?") + public void autoDeleteToken() { + for (Token t: tokenRepo.findAll()){ + Calendar cal = Calendar.getInstance(); + + Calendar cal2 = Calendar.getInstance(); + cal2.setTime(t.getExpirationDate()); + + if (cal.compareTo(cal2) >= 0){ + tokenRepo.delete(t); + } + } + }; +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java new file mode 100644 index 0000000..2e5bf0d --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java @@ -0,0 +1,108 @@ +package ovh.herisson.Clyde.Tables; + +import jakarta.persistence.*; + +import java.util.Date; + +public class InscriptionRequest { + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String firstName; + private String lastName; + private String adress; + private String email; + private String country; + private Date birthDate; + + @ManyToOne + @JoinColumn(name="Cursus") + private Cursus cursus; + private RequestState state; + private String profilePicture; + public InscriptionRequest(){} + public InscriptionRequest(String lastName, String firstName, String adress, String email, String country, Date birthDate, RequestState state, String profilePicture){ + this.lastName = lastName; + this.firstName = firstName; + this.adress = adress; + this.email = email; + this.country = country; + this.birthDate = birthDate; + this.state = state; + } + + public int getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getAdress() { + return adress; + } + + public void setAdress(String adress) { + this.adress = adress; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + public Cursus getCursus() { + return cursus; + } + + public void setCursus(Cursus cursus) { + this.cursus = cursus; + } + + public RequestState getState() { + return state; + } + + public void setState(RequestState state) { + this.state = state; + } + + public String getProfilePicture() { + return profilePicture; + } + + public void setProfilePicture(String profilePicture) { + this.profilePicture = profilePicture; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java new file mode 100644 index 0000000..8a56f88 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java @@ -0,0 +1,69 @@ +package ovh.herisson.Clyde.Tables; + +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; + +public class ReinscriptionRequest { + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + @ManyToOne + @JoinColumn(name = "User") + private User user; + + @ManyToOne + @JoinColumn(name = "Cursus") + private Cursus newCursus; + private RequestState state; + + //Permet de différencier les demandes de changement et une réinscription dans le même cursus + //Pour la réinscription on va le mettre a 0 + private boolean type; + + public ReinscriptionRequest(){} + + public ReinscriptionRequest(User user, Cursus newCursus, RequestState state, boolean type){ + this.user = user; + this.newCursus = newCursus; + this.state = state; + this.type = type; + } + + public int getId() { + return id; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Cursus getNewCursus() { + return newCursus; + } + + public void setNewCursus(Cursus newCursus) { + this.newCursus = newCursus; + } + + public RequestState getState() { + return state; + } + + public void setState(RequestState state) { + this.state = state; + } + + public boolean isType() { + return type; + } + + public void setType(boolean type) { + this.type = type; + } +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java new file mode 100644 index 0000000..f0345c1 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/RequestState.java @@ -0,0 +1,7 @@ +package ovh.herisson.Clyde.Tables; + +public enum RequestState { + Accepted, + Refused, + Pending; +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Token.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Token.java index 848f836..8aa4c0e 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/Token.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Token.java @@ -1,6 +1,10 @@ package ovh.herisson.Clyde.Tables; import jakarta.persistence.*; +import org.springframework.scheduling.annotation.Scheduled; +import ovh.herisson.Clyde.Repositories.TokenRepository; + +import java.util.Date; @Entity public class Token { @@ -12,13 +16,16 @@ public class Token { @JoinColumn(name ="Users") private User user; private String token; + private Date expirationDate; - public Token(User user, String token){ + public Token(User user, String token, Date expirationDate){ this.user = user; this.token = token; + this.expirationDate = expirationDate; } public Token(){} + public int getId() { return id; } @@ -37,4 +44,12 @@ public class Token { public void setToken(String data) { this.token = data; } + + public void setExpirationDate(Date date){ + this.expirationDate = date; + } + + public Date getExpirationDate(){ + return expirationDate; + } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java index 101ec9e..55c5be2 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java @@ -16,6 +16,7 @@ public class User { private int regNo; private String lastName; private String firstName; + @Column(unique = true) private String email; private String address; private String country;