From 21de520175e748d342852d4a71efc8e7c7fd998e Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Sat, 9 Mar 2024 10:29:32 +0100 Subject: [PATCH 01/47] Fixing the cross origine on the frontend side --- frontend/src/rest/Users.js | 2 +- frontend/src/rest/restConsumer.js | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/frontend/src/rest/Users.js b/frontend/src/rest/Users.js index e34d611..bcbf8b9 100644 --- a/frontend/src/rest/Users.js +++ b/frontend/src/rest/Users.js @@ -1,7 +1,7 @@ import { restGet, restPost } from './restConsumer.js' export async function login(user, pass, exp){ - return restPost("/login", {login: user, password: pass, expiration: exp}); + return restPost("/login", {identifier: user, password: pass, expiration: exp}); } export async function register(user, pass, mail){ diff --git a/frontend/src/rest/restConsumer.js b/frontend/src/rest/restConsumer.js index 25729bd..63a0a0d 100644 --- a/frontend/src/rest/restConsumer.js +++ b/frontend/src/rest/restConsumer.js @@ -8,15 +8,15 @@ export async function restGet(endPoint) { } export async function restPost(endPoint, data) { - return await _rest(endPoint, {method: "POST", body: data}); + return await _rest(endPoint, {method: "POST", body: JSON.stringify(data)}); } export async function restDelete(endPoint, data) { - return await _rest(endPoint, {method: "DELETE", body: data}); + return await _rest(endPoint, {method: "DELETE", body: JSON.stringify(data)}); } export async function restPatch(endPoint, data) { - return await _rest(endPoint, {method: "PATCH", body: data}); + return await _rest(endPoint, {method: "PATCH", body: JSON.stringify(data)); } /** @@ -31,8 +31,12 @@ export async function restPatch(endPoint, data) { async function _rest(endPoint, config){ endPoint.at(0) != "/" ? console.error("Carefull, you certainly should put a / at the begenning of your endPoint ") : true; let session_token = getCookie("session_token"); - let headers = new Headers({'Authorization': session_token}); + let headers = new Headers({ + 'Authorization': session_token, + 'Content-Type': 'application/json', + }); config['headers'] = headers; + config['credentials'] = 'include' return toast.promise(fetch(restURL + endPoint, config), { pending: config['pending'] != null ? config['pending'] : 'pending', From 0b4b38f6c555180320ef94b41206a4c497ef9050 Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Sat, 9 Mar 2024 10:36:20 +0100 Subject: [PATCH 02/47] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merci javascript pour ces erreurs de qualitée... --- frontend/src/rest/restConsumer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/rest/restConsumer.js b/frontend/src/rest/restConsumer.js index 63a0a0d..9e42e49 100644 --- a/frontend/src/rest/restConsumer.js +++ b/frontend/src/rest/restConsumer.js @@ -16,7 +16,7 @@ export async function restDelete(endPoint, data) { } export async function restPatch(endPoint, data) { - return await _rest(endPoint, {method: "PATCH", body: JSON.stringify(data)); + return await _rest(endPoint, {method: "PATCH", body: JSON.stringify(data)}); } /** From 847b1ca4194023c352c3d966b1cb7d230a5da0bb Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Sat, 9 Mar 2024 16:20:55 +0100 Subject: [PATCH 03/47] Solve crossOrigin Finally --- .../main/java/ovh/herisson/Clyde/EndPoints/LoginController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java index 8a0722d..8c687ee 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java @@ -9,7 +9,7 @@ import ovh.herisson.Clyde.Services.AuthenticatorService; import java.util.Date; @RestController -@CrossOrigin(origins = "http://localhost:5173") +@CrossOrigin(origins = "http://localhost:5173", allowCredentials = "true") public class LoginController { private final AuthenticatorService authServ; From ac8830703698f317bdf5ec3972722d36d4efd7fc Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Sat, 9 Mar 2024 16:22:38 +0100 Subject: [PATCH 04/47] fix expiration date and frontend requests --- frontend/src/rest/Users.js | 2 +- frontend/src/rest/restConsumer.js | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/rest/Users.js b/frontend/src/rest/Users.js index bcbf8b9..cca662d 100644 --- a/frontend/src/rest/Users.js +++ b/frontend/src/rest/Users.js @@ -1,7 +1,7 @@ import { restGet, restPost } from './restConsumer.js' export async function login(user, pass, exp){ - return restPost("/login", {identifier: user, password: pass, expiration: exp}); + return restPost("/login", {identifier: user, password: pass, expirationDate: exp}); } export async function register(user, pass, mail){ diff --git a/frontend/src/rest/restConsumer.js b/frontend/src/rest/restConsumer.js index 9e42e49..b2d1546 100644 --- a/frontend/src/rest/restConsumer.js +++ b/frontend/src/rest/restConsumer.js @@ -8,15 +8,15 @@ export async function restGet(endPoint) { } export async function restPost(endPoint, data) { - return await _rest(endPoint, {method: "POST", body: JSON.stringify(data)}); + return await _rest(endPoint, {method: "POST", credentials: 'include', body: JSON.stringify(data)}); } export async function restDelete(endPoint, data) { - return await _rest(endPoint, {method: "DELETE", body: JSON.stringify(data)}); + return await _rest(endPoint, {method: "DELETE", credentials: 'include', body: JSON.stringify(data)}); } export async function restPatch(endPoint, data) { - return await _rest(endPoint, {method: "PATCH", body: JSON.stringify(data)}); + return await _rest(endPoint, {method: "PATCH", credentials: 'include', body: JSON.stringify(data)}); } /** @@ -36,7 +36,6 @@ async function _rest(endPoint, config){ 'Content-Type': 'application/json', }); config['headers'] = headers; - config['credentials'] = 'include' return toast.promise(fetch(restURL + endPoint, config), { pending: config['pending'] != null ? config['pending'] : 'pending', From 8fdfb470cb3c130f0d0e3bde1adc9b7e4edb1981 Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Sat, 9 Mar 2024 18:54:46 +0100 Subject: [PATCH 05/47] fixing the origin requests once and for all --- .../main/java/ovh/herisson/Clyde/EndPoints/LoginController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java index 8c687ee..e43f0a1 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java @@ -9,7 +9,7 @@ import ovh.herisson.Clyde.Services.AuthenticatorService; import java.util.Date; @RestController -@CrossOrigin(origins = "http://localhost:5173", allowCredentials = "true") +@CrossOrigin(originPatterns = "*", allowCredentials = "true") public class LoginController { private final AuthenticatorService authServ; From 84fe1df67175915d6e64119b63e4d4c894f9f822 Mon Sep 17 00:00:00 2001 From: Anthony Debucquoy Date: Sat, 9 Mar 2024 19:14:57 +0100 Subject: [PATCH 06/47] Reactive Translations Make Translated text reactive so that when switching lang, text is reload on the fly Fixes: #77 --- frontend/src/i18n.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/frontend/src/i18n.js b/frontend/src/i18n.js index d8909f1..8c39fb4 100644 --- a/frontend/src/i18n.js +++ b/frontend/src/i18n.js @@ -10,9 +10,10 @@ */ import { getCookie, setCookie } from './utils.js'; +import { reactive } from 'vue'; const default_lang = "EN"; -let langs; +const langs = reactive({}); /** @@ -27,8 +28,8 @@ let langs; export default function i18n(key, options) { let ret = langs[key]; if(options != null){ - for (let key in options) { - ret = ret.replaceAll("$" + key, options[key]); + for (let option in options) { + ret = ret.replaceAll("$" + option, options[option]); } } return ret; @@ -47,14 +48,12 @@ export async function loadLangs(lang){ const content = await (await fetch(filename)).text(); const lines = content.split("\n"); - let filteredLines = {}; for (let line of lines) { if(!line.trim().startsWith("#") && line.trim() != ""){ let split = line.indexOf("=") - filteredLines[line.substr(0, split)] = line.substr(split+1, line.length); + langs[line.substr(0, split)] = line.substr(split+1, line.length); }; } - langs = filteredLines; } await loadLangs(); From ce2efb61c851589bb555e0a8aa8ab6ecebdf8c4d Mon Sep 17 00:00:00 2001 From: Bartha Maxime <231026@umons.ac.be> Date: Sun, 10 Mar 2024 23:28:13 +0100 Subject: [PATCH 07/47] fixed some issue for the token authorization (#87) Reviewed-on: https://git.herisson.ovh/PGL/Clyde/pulls/87 Reviewed-by: Debucquoy Anthony Co-authored-by: Bartha Maxime <231026@umons.ac.be> Co-committed-by: Bartha Maxime <231026@umons.ac.be> --- .../Clyde/EndPoints/MockController.java | 4 --- .../Clyde/EndPoints/TokenController.java | 26 +++++++++++++++++++ .../Clyde/EndPoints/UserController.java | 12 ++++----- .../Clyde/Repositories/TokenRepository.java | 1 + .../herisson/Clyde/Services/TokenService.java | 13 ++++++++-- .../java/ovh/herisson/Clyde/Tables/Token.java | 2 +- 6 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 backend/src/main/java/ovh/herisson/Clyde/EndPoints/TokenController.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 f7825f6..18fea23 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java @@ -49,10 +49,6 @@ public class MockController { mockUsers = new ArrayList(Arrays.asList(herobrine,joe,meh,joke)); userRepo.saveAll(mockUsers); - - for (User user: mockUsers){ - tokenRepo.save(new Token(user,user.getPassword())); - } } @DeleteMapping("/mock") diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/TokenController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/TokenController.java new file mode 100644 index 0000000..793e61b --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/TokenController.java @@ -0,0 +1,26 @@ +package ovh.herisson.Clyde.EndPoints; + + + +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import ovh.herisson.Clyde.Services.TokenService; +import ovh.herisson.Clyde.Tables.Token; + +@RestController +@CrossOrigin(origins = "http://localhost:5173") +public class TokenController { + + private final TokenService tokenServ; + + public TokenController(TokenService tokenServ){ + this.tokenServ = tokenServ; + } + + + @GetMapping("/tokens") + public Iterable getTokens(){ + return tokenServ.getAllTokens(); + } +} 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 ba54926..8de166e 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java @@ -23,18 +23,18 @@ public class UserController { } @GetMapping("/user") - public ResponseEntity getUser(@RequestHeader("Authorization") String token){ - User user = authServ.getUserFromToken(token); - if (user == null) { - return new UnauthorizedResponse<>(null); - } + public ResponseEntity getUser(@RequestHeader("Cookie") String authorization){ + + if (authorization == null) return new UnauthorizedResponse<>(null); + User user = authServ.getUserFromToken(authorization); + if (user == null) return new UnauthorizedResponse<>(null); return new ResponseEntity<>(user, HttpStatus.OK); } @PostMapping("/user") public ResponseEntity postUser(@RequestBody User user){ userService.save(user); - return new ResponseEntity(String.format("Account created with ID:%s",user.getRegNo()),HttpStatus.CREATED); + return new ResponseEntity<>(String.format("Account created with ID:%s",user.getRegNo()),HttpStatus.CREATED); } @GetMapping("/users") 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 d375e7a..6a4e47a 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Repositories/TokenRepository.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/TokenRepository.java @@ -9,4 +9,5 @@ public interface TokenRepository extends CrudRepository { Token getByToken(String token); Iterable getByUser(User user); + } 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 a82951d..125dbde 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java @@ -20,12 +20,19 @@ public class TokenService { this.tokenRepo = tokenRepo; } + public Iterable getAllTokens() { + return tokenRepo.findAll(); + } + public String generateNewToken(){ byte[] bytes = new byte[64]; new SecureRandom().nextBytes(bytes); for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) (((bytes[i]+256)%256 %95+ 32)); + while ((char)bytes[i] == ';'){ + bytes[i] = new SecureRandom().generateSeed(1)[0]; + } } // will never end up in the catch because of the way that SecureRandom.nextBytes is implemented try { @@ -35,8 +42,10 @@ public class TokenService { } } - public User getUserFromToken(String token){ - return tokenRepo.getByToken(token).getUser(); + public User getUserFromToken(String token) { + Token tokenRep = tokenRepo.getByToken(token); + if (tokenRep == null) return null; + return tokenRep.getUser(); } public void saveToken(String token, User user, Date expirationDate){// todo faire qlq chose de l'expDate 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 5b61cb9..848f836 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/Token.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Token.java @@ -8,7 +8,7 @@ public class Token { @Id private int id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name ="Users") private User user; private String token; 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 08/47] 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 09/47] 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; From ab91a39a63ce37dcc9985423aa6b6be7ffa19b50 Mon Sep 17 00:00:00 2001 From: LeoMoulin Date: Mon, 11 Mar 2024 20:23:45 +0100 Subject: [PATCH 10/47] Create exception for file deletion. Add user/inscriptionrequest connection to StorageFile entity. Create a prototype of the delete for file function --- .../Clyde/EndPoints/StorageController.java | 2 +- .../CouldntDeleteFileException.java | 4 +++ .../Clyde/Services/StorageService.java | 23 ++++++++++--- .../Clyde/Tables/InscriptionRequest.java | 3 ++ .../Clyde/Tables/ReinscriptionRequest.java | 2 +- .../herisson/Clyde/Tables/StorageFile.java | 34 ++++++++++++++++--- 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 backend/src/main/java/ovh/herisson/Clyde/Exceptions/CouldntDeleteFileException.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 index 2a36657..be58f17 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java @@ -23,7 +23,7 @@ public class StorageController { @PostMapping("/upload/{fileType}") public ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file, @PathVariable FileType fileType) { - String path = storageServ.store(file,fileType); + String path = storageServ.store(file,fileType, null, null); if (path == null) return new ResponseEntity<>("issue with the file storage", HttpStatus.BAD_REQUEST); diff --git a/backend/src/main/java/ovh/herisson/Clyde/Exceptions/CouldntDeleteFileException.java b/backend/src/main/java/ovh/herisson/Clyde/Exceptions/CouldntDeleteFileException.java new file mode 100644 index 0000000..ce0d637 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Exceptions/CouldntDeleteFileException.java @@ -0,0 +1,4 @@ +package ovh.herisson.Clyde.Exceptions; + +public class CouldntDeleteFileException extends Exception{ +} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java index 77dff70..eeea9e3 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java @@ -3,11 +3,14 @@ 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.Exceptions.CouldntDeleteFileException; import ovh.herisson.Clyde.Repositories.FileRepository; -import ovh.herisson.Clyde.Tables.FileType; -import ovh.herisson.Clyde.Tables.StorageFile; +import ovh.herisson.Clyde.Tables.*; + +import java.io.File; 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; @@ -27,7 +30,7 @@ public class StorageService { } - public String store(MultipartFile file, FileType fileType) { + public String store(MultipartFile file, FileType fileType, User user, InscriptionRequest request) { if (file.getOriginalFilename().isEmpty()){return null;} @@ -49,8 +52,20 @@ public class StorageService { String url = this.rootLocation.resolve(Paths.get(Objects.requireNonNull(stringUuid))) .normalize().toString(); - fileRepo.save(new StorageFile(file.getName(),url, fileType)); + fileRepo.save(new StorageFile(file.getName(),url, fileType, user, request)); return url; } + + public void delete(StorageFile file) throws CouldntDeleteFileException { + File f = new File(file.getUrl()); + //Delete le fichier + try{ + f.delete(); + } catch (Exception e) { + throw new CouldntDeleteFileException(); + } + //Delete l'entité + fileRepo.delete(file); + } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java index 2e5bf0d..fa853b1 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java @@ -4,7 +4,10 @@ import jakarta.persistence.*; import java.util.Date; + +@Entity public class InscriptionRequest { + @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String firstName; diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java index 8a56f88..0a4db64 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java @@ -20,7 +20,7 @@ public class ReinscriptionRequest { //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; + private boolean type = false; public ReinscriptionRequest(){} diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java index a96d0ec..4124231 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java @@ -1,9 +1,6 @@ package ovh.herisson.Clyde.Tables; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; @Entity @@ -20,10 +17,21 @@ public class StorageFile { private FileType fileType; - public StorageFile(String name, String url, FileType fileType){ + //Pour lier un user ou une demande d'inscription au fichier + @ManyToOne + @JoinColumn(name = "user") + private User user; + + @ManyToOne + @JoinColumn(name = "inscriptionrequest") + private InscriptionRequest request; + + public StorageFile(String name, String url, FileType fileType, User user, InscriptionRequest request){ this.name = name; this.url = url; this.fileType = fileType; + this.user = user; + this.request = request; } public StorageFile(){} @@ -60,4 +68,20 @@ public class StorageFile { public void setFileType(FileType fileType) { this.fileType = fileType; } + + public void setUser(User user) { + this.user = user; + } + + public User getUser() { + return user; + } + + public void setRequest(InscriptionRequest request) { + this.request = request; + } + + public InscriptionRequest getRequest() { + return request; + } } From 28d252279a83dad0c0b4f8f0ddd06fdda826c56d Mon Sep 17 00:00:00 2001 From: Bartha Maxime <231026@umons.ac.be> Date: Mon, 11 Mar 2024 22:33:53 +0100 Subject: [PATCH 11/47] added a small description --- .../java/ovh/herisson/Clyde/Tables/User.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) 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..5ba70ab 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java @@ -8,7 +8,6 @@ import java.util.Date; //et l'attribut tokenApi doit encore être ajouté vu qu'il faut en discuter @Entity -//Je rajoute un s au nom de la table pour éviter les conflits avec les mots réservés @Table(name = "Users") public class User { @Id @@ -37,6 +36,31 @@ public class User { this.password = password; } + + /** Constructor for the first registration request from a student (can't specify a Role) + * + * @param lastName + * @param firstName + * @param email + * @param address + * @param country + * @param birthDate + * @param profilePictureUrl + * @param password + */ + public User(String lastName, String firstName, String email, String address, + String country, Date birthDate, String profilePictureUrl, String password) + { + this.lastName = lastName; + this.firstName = firstName; + this.email = email; + this.address = address; + this.country = country; + this.birthDate = birthDate; + this.profilePictureUrl = profilePictureUrl; + this.password = password; + this.role = Role.Student; + } public User() {} public int getRegNo(){ From 5c728098dff85db2dc61fcf4153d7d6269614ffe Mon Sep 17 00:00:00 2001 From: Bartha Maxime <231026@umons.ac.be> Date: Tue, 12 Mar 2024 00:03:32 +0100 Subject: [PATCH 12/47] protected post /user and get/users and return without password --- .../Clyde/EndPoints/UserController.java | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) 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 43bcd0c..4a20058 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java @@ -8,8 +8,11 @@ import org.springframework.web.bind.annotation.*; import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Services.AuthenticatorService; import ovh.herisson.Clyde.Services.UserService; +import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.User; +import java.util.ArrayList; + @RestController @CrossOrigin(origins = "http://localhost:5173") @@ -23,25 +26,57 @@ public class UserController { } @GetMapping("/user") - public ResponseEntity getUser(@RequestHeader("Cookie") String authorization){ + public ResponseEntity getUser(@RequestHeader("Authorization") String authorization){ if (authorization == null) return new UnauthorizedResponse<>(null); User user = authServ.getUserFromToken(authorization); if (user == null) return new UnauthorizedResponse<>(null); - return new ResponseEntity<>(user, HttpStatus.OK); + + return new ResponseEntity<>(userWithoutPassword(user), HttpStatus.OK); } - @PostMapping("/user") //todo check role - public ResponseEntity postUser(@RequestBody User user){ + @PostMapping("/user") + public ResponseEntity postUser(@RequestBody User user,@RequestHeader("Authorization") String authorization){ + + if (authorization == null) return new UnauthorizedResponse<>(null); + User poster = authServ.getUserFromToken(authorization); + + if (poster.getRole() != Role.Secretary || poster.getRole() != Role.Admin) + return new UnauthorizedResponse<>(null); + + userService.save(user); return new ResponseEntity<>(String.format("Account created with ID:%s",user.getRegNo()),HttpStatus.CREATED); } @GetMapping("/users") - public Iterable getAllUsers(){ - return userService.getAll(); + public ResponseEntity> getAllUsers(@RequestHeader("Authorization") String authorization){ + + if (authorization == null) return new UnauthorizedResponse<>(null); + User poster = authServ.getUserFromToken(authorization); + + if (poster == null) return new UnauthorizedResponse<>(null); + + if (poster.getRole() != Role.Secretary || poster.getRole() != Role.Admin) + return new UnauthorizedResponse<>(null); + + Iterable users = userService.getAll(); + ArrayList withoutPassword = new ArrayList<>(); + + for (User u :users){ + withoutPassword.add(userWithoutPassword(u)); + } + return new ResponseEntity<>(withoutPassword, HttpStatus.OK); } + + /** return user's data except password + * @param user the user to return + * @return all the user data without the password + */ + private Object[] userWithoutPassword(User user){ + return new Object[] {user.getRegNo(),user.getFirstName(),user.getLastName(),user.getBirthDate(),user.getCountry(),user.getAddress(),user.getRole()}; + } } From c14d0a9d21ca37e3ec409f4ee06dd70f4bef12af Mon Sep 17 00:00:00 2001 From: Wawilski Date: Sat, 9 Mar 2024 11:07:13 +0100 Subject: [PATCH 13/47] option language settings start --- frontend/src/App.vue | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 51f8882..2ee53b0 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -26,8 +26,10 @@ const notifications=ref(i18n("app.notifications")) const settings=ref(i18n("app.settings")) const login=ref(i18n("app.login")) - - + const active=ref(false) + function toggle() { + active = !active; + } @@ -52,9 +54,17 @@
-
  • +
  • +
  • @@ -122,8 +132,30 @@ .leftBar{ grid-area:leftBar; } +.option { + position: relative; + display: block; +} +.dropdown { + margin-top:55px; + display: block; + height:150px; + font-size: 13px; + position: absolute; + z-index: 1; + background-color:white; +} + +.dropdown .content { + color: #4CAF50; + padding: 8px 10px; + text-decoration: none; + display: block; + transition: 0.1s; +} + ul.vertical{ list-style-type: none; margin-top: 61px; @@ -176,7 +208,6 @@ position: fixed; height:61px; width: 100%; - overflow: hidden; background-color: rgb(24, 24, 24); } From 07e5fb3a7307a23e970f9a226be25a1c48638531 Mon Sep 17 00:00:00 2001 From: Wawilski Date: Sat, 9 Mar 2024 22:48:33 +0100 Subject: [PATCH 14/47] profil menu base --- frontend/src/App.vue | 115 ++++++++++++---------------------- frontend/src/Apps/Login.vue | 10 --- frontend/src/Apps/Profil.vue | 98 +++++++++++++++++++++++++++++ frontend/src/Apps/Request.vue | 15 ++--- 4 files changed, 144 insertions(+), 94 deletions(-) create mode 100644 frontend/src/Apps/Profil.vue diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 2ee53b0..bedd1f1 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -7,16 +7,21 @@ // Liste des apps import LoginPage from './Apps/Login.vue' import Inscription from "./Apps/Inscription.vue" + import Profil from "./Apps/Profil.vue" const apps = { '/login': LoginPage, - '/inscription': Inscription + '/inscription': Inscription, + '/profil': Profil } const currentPath = ref(window.location.hash) window.addEventListener('hashchange', () => { currentPath.value = window.location.hash }) + + function refreshPage() { + window.location.reload();} const currentView = computed(() => { return apps[currentPath.value.slice(1) || '/'] @@ -27,10 +32,7 @@ const settings=ref(i18n("app.settings")) const login=ref(i18n("app.login")) const active=ref(false) - function toggle() { - active = !active; - } - + @@ -32,11 +27,11 @@ .container{ color:white; height:100px; - font-size:20px; + font-size:20px; display:grid; - grid-template-columns:[firstCol-start]100px[firstCol-end secondCol-start]150px[secondCol-end thirdCol-start]200px[thirdCol-end fourthCol-start]150px[fourthCol-end]150px[fifthCol-end]150px[sixthCol-end]150px[endCol]; + grid-template-columns:[firstCol-start]100px[firstCol-end secondCol-start]150px[endCol]; grid-template-areas: - "id type surname firstname infos accept refuse"; + " accept refuse"; column-gap:10px; } From 3cf5153e79ac1b2114e0cded486b719b738faca2 Mon Sep 17 00:00:00 2001 From: Wawilski Date: Sun, 10 Mar 2024 12:34:44 +0100 Subject: [PATCH 15/47] Profil Student Prototype --- frontend/src/Apps/Profil.vue | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/frontend/src/Apps/Profil.vue b/frontend/src/Apps/Profil.vue index 893104c..76f5017 100644 --- a/frontend/src/Apps/Profil.vue +++ b/frontend/src/Apps/Profil.vue @@ -13,14 +13,15 @@ "name": "Math pour l'info", "credits": 11, "faculty": "science", - "Teacher": 42, + "teacher": 42, "Assistants": []}, - cours2:{ "id": 42, + cours2:{ + "id": 42, "name": "Fonctionnement des ordinateurs", "credits": 11, "faculty": "science", - "Teacher": 42, - "Assistants": []} + "teacher": 42, + "Assistants": []}, }, option:"IT", @@ -37,8 +38,8 @@
    -
    -
    +
    +
    {{example.firstName}} {{example.lastName.toUpperCase()}}
    @@ -50,8 +51,17 @@
    -
    +
    +
    + Liste des cours +
    +
    + {{item.name}} Teacher: {{item.teacher}} Credits:{{item.credits}} +
    +
    From 042553c1239c7029214d5f6c0342bec5052b77e6 Mon Sep 17 00:00:00 2001 From: Wawilski Date: Sun, 10 Mar 2024 16:01:47 +0100 Subject: [PATCH 16/47] Profil Teacher and examples --- frontend/src/Apps/Profil.vue | 160 +++++++++++++++++++++++++++++++--- frontend/src/Apps/Request.vue | 13 ++- 2 files changed, 156 insertions(+), 17 deletions(-) diff --git a/frontend/src/Apps/Profil.vue b/frontend/src/Apps/Profil.vue index 76f5017..b95ff54 100644 --- a/frontend/src/Apps/Profil.vue +++ b/frontend/src/Apps/Profil.vue @@ -1,8 +1,11 @@ @@ -38,30 +70,60 @@
    -
    +
    - {{example.firstName}} {{example.lastName.toUpperCase()}} + {{user.firstName}} {{user.lastName.toUpperCase()}}
    - E-mail: {{example.email}} + E-mail: {{user.email}} +
    +
    + {{user.option}} {{user.role.toUpperCase()}} +
    +
    + Faculty: {{user.faculty}} + Role: {{user.role}}
    - {{example.option}} {{example.role.toUpperCase()}} + +
    +
    + +
    -
    -
    + +
    +
    Liste des cours
    -
    - {{item.name}} Teacher: {{item.teacher}} Credits:{{item.credits}} +
    +
    +
    {{item.name}}
    +
    {{item.teacher}}
    +
    Credits:{{item.credits}}
    +
    + +
    +
    + +
    +
    + Liste des cours +
    +
    + {{item.name}} +
    +
    + +
    +
    +
    @@ -104,5 +166,77 @@ width:100%; margin-bottom:10px; } + .containerElement{ + justify-content:center; + display:grid; + grid-template-columns:350px 350px 200px; + grid-template-areas: + "name teacher credits"; + column-gap:10px; + + } + + .name { + grid-area:name; + align-self:center; + } + .teacher{ + grid-area:teacher; + align-self:center; + } + + .credits{ + grid-area:credits; + align-self:center; + } + +.listTitle{ + display: flex; + justify-content: center; + align-items: center; + width:200px; + margin-left:auto; + margin-right:auto; + border:2px solid black; + font-size:25px; + color:white; + padding:20px; + background-color:rgb(50,50,50); + border-radius:20px;margin-bottom:10px; +} + +.listElement{ + border:2px solid black; + font-size:25px; + color:white; + padding:20px; + background-color:rgb(50,50,50); + border-radius:20px; + margin-bottom:10px; +} + +.infosContainer { +padding-bottom:50px; +border:2px solid black; +font-size:25px; +color:white; +padding:20px; +background-color:rgb(50,50,50); +border-radius:20px; +} + + +button{ + border:none; + background-color:rgb(239, 60, 168); + border-radius:10px; + height:35px; + margin-top:10px; + +} + +button:hover{ + opacity:0.8; +} diff --git a/frontend/src/Apps/Request.vue b/frontend/src/Apps/Request.vue index 7b65e80..b8ec6c1 100644 --- a/frontend/src/Apps/Request.vue +++ b/frontend/src/Apps/Request.vue @@ -17,8 +17,13 @@
    -
    -
    + + + + +
    +
    +
    @@ -29,9 +34,9 @@ height:100px; font-size:20px; display:grid; - grid-template-columns:[firstCol-start]100px[firstCol-end secondCol-start]150px[endCol]; + grid-template-columns:[firstCol-start]100px[firstCol-end secondCol-start]150px[secondCol-end thirdCol-start]200px[thirdCol-end fourthCol-start]150px[fourthCol-end]150px[fifthCol-end]150px[sixthCol-end]150px[endCol]; grid-template-areas: - " accept refuse"; + "id type surname firstname infos accept refuse"; column-gap:10px; } From 2fe615370551adfc9455c525782dd7f4d0e38c70 Mon Sep 17 00:00:00 2001 From: Wawilski Date: Mon, 11 Mar 2024 12:02:27 +0100 Subject: [PATCH 17/47] Translation correction --- frontend/src/App.vue | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index bedd1f1..6ed110c 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -20,9 +20,6 @@ currentPath.value = window.location.hash }) - function refreshPage() { - window.location.reload();} - const currentView = computed(() => { return apps[currentPath.value.slice(1) || '/'] }) @@ -63,10 +60,10 @@
    • - +
    • -
    • +
    From 68df9f99fa392e57b097b351916aa680508f32f7 Mon Sep 17 00:00:00 2001 From: Wawilski Date: Mon, 11 Mar 2024 21:24:40 +0100 Subject: [PATCH 18/47] modify profil strating setup --- frontend/src/Apps/Profil.vue | 38 ++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/frontend/src/Apps/Profil.vue b/frontend/src/Apps/Profil.vue index b95ff54..a4b1d45 100644 --- a/frontend/src/Apps/Profil.vue +++ b/frontend/src/Apps/Profil.vue @@ -1,5 +1,5 @@ @@ -70,7 +75,7 @@
    -
    +
    {{user.firstName}} {{user.lastName.toUpperCase()}}
    @@ -85,15 +90,40 @@ Role: {{user.role}}
    - +
    +
    +
    + Profil Picture + +
    +
    + E-mail: + +
    +
    + Address: + +
    +
    + Password + +
    +
    + Confirm Password + +
    +
    + +
    +
    -
    +
    From 86f1a6f17b2f5c9aa54fb2e49ce561a76c4b3e05 Mon Sep 17 00:00:00 2001 From: Wawilski Date: Mon, 11 Mar 2024 21:45:51 +0100 Subject: [PATCH 19/47] Little corrections --- frontend/src/App.vue | 2 +- frontend/src/Apps/Profil.vue | 19 ++++++++++--------- frontend/src/Apps/Request.vue | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 6ed110c..ef68173 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -56,7 +56,7 @@
  • -