diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index f105250..6557b82 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -41,3 +41,4 @@ tasks.register("run") { tasks.withType { useJUnitPlatform() } + diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/InscriptionController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/InscriptionController.java new file mode 100644 index 0000000..a997c54 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/InscriptionController.java @@ -0,0 +1,84 @@ +package ovh.herisson.Clyde.EndPoints; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ovh.herisson.Clyde.Responses.UnauthorizedResponse; +import ovh.herisson.Clyde.Services.AuthenticatorService; +import ovh.herisson.Clyde.Services.InscriptionService; +import ovh.herisson.Clyde.Tables.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Role; +import ovh.herisson.Clyde.Tables.User; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +@RestController +@CrossOrigin(originPatterns = "*", allowCredentials = "true") + +public class InscriptionController { + + + private final InscriptionService inscriptionServ; + private final AuthenticatorService authServ; + + public InscriptionController(InscriptionService inscriptionServ, AuthenticatorService authServ){ + this.inscriptionServ = inscriptionServ; + this.authServ = authServ; + } + + + @GetMapping("/inscriptionRequests") + public ResponseEntity>> getAllRequests(@RequestHeader("Authorization") String token){ + + if (!isSecretaryOrAdmin(token)){return new UnauthorizedResponse<>(null);} + + Iterable inscriptionRequests = inscriptionServ.getAll(); + ArrayList> toReturn = new ArrayList<>(); + + for (InscriptionRequest i:inscriptionRequests){ + toReturn.add(requestWithoutPassword(i)); + } + + return new ResponseEntity<>(toReturn, HttpStatus.OK); + } + + + @GetMapping("/inscriptionRequest/{id}") + public ResponseEntity> getById(@PathVariable long id){ + + + + InscriptionRequest inscriptionRequest = inscriptionServ.getById(id); + if (inscriptionRequest == null) {return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);} + + return new ResponseEntity<>(requestWithoutPassword(inscriptionRequest), HttpStatus.OK); + } + + + private Map requestWithoutPassword(InscriptionRequest inscriptionRequest) { + Map toReturn = new HashMap<>(); + + toReturn.put("id", inscriptionRequest.getId()); + toReturn.put("firstName", inscriptionRequest.getFirstName()); + toReturn.put("lastName", inscriptionRequest.getLastName()); + toReturn.put("address", inscriptionRequest.getAddress()); + toReturn.put("birthDate", inscriptionRequest.getBirthDate()); + toReturn.put("country", inscriptionRequest.getCountry()); + toReturn.put("cursus", inscriptionRequest.getCursus()); + toReturn.put("profilePictureUrl", inscriptionRequest.getProfilePicture()); + toReturn.put("state", inscriptionRequest.getState()); + return toReturn; + } + + + private boolean isSecretaryOrAdmin(String authorization){ + if (authorization ==null) + return false; + + User poster = authServ.getUserFromToken(authorization); + if (poster == null) return false; + + return poster.getRole() == Role.Secretary && poster.getRole() == Role.Admin; + } +} 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..20542b5 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java @@ -1,15 +1,22 @@ package ovh.herisson.Clyde.EndPoints; import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.persistence.Column; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Services.AuthenticatorService; +import ovh.herisson.Clyde.Tables.Cursus; +import ovh.herisson.Clyde.Tables.CursusType; +import ovh.herisson.Clyde.Tables.InscriptionRequest; +import ovh.herisson.Clyde.Tables.User; import java.util.Date; +import java.util.HashMap; @RestController -@CrossOrigin(origins = "http://localhost:5173") +@CrossOrigin(originPatterns = "*", allowCredentials = "true") public class LoginController { private final AuthenticatorService authServ; @@ -40,6 +47,13 @@ public class LoginController { responseHeaders.set("Set-Cookie",String.format("session_token=%s",sessionToken)); return ResponseEntity.ok().headers(responseHeaders).build(); } + + @PostMapping("/register") + public ResponseEntity register(@RequestBody InscriptionRequest inscriptionRequest){ + + authServ.register(inscriptionRequest); + return new ResponseEntity<>("Is OK", HttpStatus.OK); + } } 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..136cecd 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/MockController.java @@ -1,35 +1,33 @@ package ovh.herisson.Clyde.EndPoints; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import ovh.herisson.Clyde.Repositories.TokenRepository; import ovh.herisson.Clyde.Repositories.UserRepository; -import ovh.herisson.Clyde.Tables.Role; -import ovh.herisson.Clyde.Tables.Token; -import ovh.herisson.Clyde.Tables.User; +import ovh.herisson.Clyde.Services.TokenService; +import ovh.herisson.Clyde.Tables.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @RestController -@CrossOrigin(origins = "http://localhost:5173") +@CrossOrigin(originPatterns = "*", allowCredentials = "true") public class MockController { private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 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,18 +39,13 @@ 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)); userRepo.saveAll(mockUsers); - - for (User user: mockUsers){ - tokenRepo.save(new Token(user,user.getPassword())); - } } @DeleteMapping("/mock") @@ -63,3 +56,4 @@ public class MockController { userRepo.deleteAll(mockUsers); } } + diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/PingController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/PingController.java index f0f26d3..b1148bf 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/PingController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/PingController.java @@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RestController; import ovh.herisson.Clyde.Responses.PingResponse; @RestController -@CrossOrigin(origins = "http://localhost:5173") +@CrossOrigin(originPatterns = "*", allowCredentials = "true") public class PingController { @GetMapping("/ping") 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..724ae10 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/StorageController.java @@ -0,0 +1,36 @@ +package ovh.herisson.Clyde.EndPoints; + +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 ovh.herisson.Clyde.Tables.FileType; +import ovh.herisson.Clyde.Tables.StorageFile; + +@RestController +@CrossOrigin(originPatterns = "*", allowCredentials = "true") +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) { + + StorageFile fileEntry = null; + try { + fileEntry = storageServ.store(file,fileType); + + } catch(Exception e){ + e.printStackTrace(); + } + + + return new ResponseEntity<>(fileEntry, HttpStatus.OK); + } +} 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..ba07fca --- /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(originPatterns = "*", allowCredentials = "true") +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..844e82e 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java @@ -1,18 +1,26 @@ package ovh.herisson.Clyde.EndPoints; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; 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.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + @RestController -@CrossOrigin(origins = "http://localhost:5173") +@CrossOrigin(originPatterns = "*", allowCredentials = "true") public class UserController { private final UserService userService; @@ -23,25 +31,80 @@ public class UserController { } @GetMapping("/user") - public ResponseEntity getUser(@RequestHeader("Authorization") String token){ - User user = authServ.getUserFromToken(token); - if (user == null) { - return new UnauthorizedResponse<>(null); - } - return new ResponseEntity<>(user, HttpStatus.OK); + 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<>(userWithoutPassword(user), HttpStatus.OK); } @PostMapping("/user") - public ResponseEntity postUser(@RequestBody User user){ + public ResponseEntity postUser(@RequestBody User user,@RequestHeader("Authorization") String authorization){ + + if (!isSecretaryOrAdmin(authorization)) + return new UnauthorizedResponse<>(null); + 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") - public Iterable getAllUsers(){ - return userService.getAll(); + public ResponseEntity>> getAllUsers(@RequestHeader("Authorization") String authorization){ + + if (!isSecretaryOrAdmin(authorization)) + 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); + } + @PatchMapping("/user") + public ResponseEntity patchUser(@RequestBody Map updates, @RequestHeader("Authorization") String authorization) { + + if (authorization == null) return new UnauthorizedResponse<>(null); + + User poster = authServ.getUserFromToken(authorization); + if (poster == null) {return new UnauthorizedResponse<>("bad authorization");} + + if (!userService.modifyData(poster, updates, poster)) + return new UnauthorizedResponse<>("there was an issue with the updates requested"); + + return new ResponseEntity<>("data modified", HttpStatus.OK); } + /** return user's data except password + * @param user the user to return + * @return all the user data without the password + */ + private HashMap userWithoutPassword(User user){ + HashMap toReturn = new HashMap<>(); + + toReturn.put("regNo",user.getRegNo()); + toReturn.put("firstName",user.getFirstName()); + toReturn.put("lastName",user.getLastName()); + toReturn.put("birthDate",user.getBirthDate()); + toReturn.put("country",user.getCountry()); + toReturn.put("address",user.getAddress()); + toReturn.put("role",user.getRole()); + + return toReturn; + } + + private boolean isSecretaryOrAdmin(String authorization){ + if (authorization ==null) + return false; + + User poster = authServ.getUserFromToken(authorization); + if (poster == null) return false; + + return poster.getRole() == Role.Secretary && poster.getRole() == Role.Admin; + } } 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/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/Repositories/InscriptionRepository.java b/backend/src/main/java/ovh/herisson/Clyde/Repositories/InscriptionRepository.java new file mode 100644 index 0000000..0d83e6b --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Repositories/InscriptionRepository.java @@ -0,0 +1,10 @@ +package ovh.herisson.Clyde.Repositories; + +import org.springframework.data.repository.CrudRepository; +import ovh.herisson.Clyde.Tables.InscriptionRequest; + + +public interface InscriptionRepository extends CrudRepository { + + InscriptionRequest findById(long aLong); +} 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..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,9 +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..60dc6bc 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,10 @@ package ovh.herisson.Clyde.Services; import org.springframework.stereotype.Service; +import ovh.herisson.Clyde.EndPoints.LoginController; +import ovh.herisson.Clyde.Repositories.InscriptionRepository; +import ovh.herisson.Clyde.Tables.InscriptionRequest; +import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.User; import java.util.Date; @@ -10,10 +14,12 @@ public class AuthenticatorService { private final TokenService tokenService; private final UserService userService; + private final InscriptionService inscriptionService; - public AuthenticatorService(TokenService tokenService, UserService userService){ + public AuthenticatorService(TokenService tokenService, UserService userService, InscriptionService inscriptionService){ this.tokenService = tokenService; this.userService = userService; + this.inscriptionService = inscriptionService; } public User getUserFromToken(String token){ @@ -26,7 +32,11 @@ 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; } + + public void register(InscriptionRequest inscriptionRequest) { + inscriptionService.save(inscriptionRequest); + } } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/InscriptionService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/InscriptionService.java new file mode 100644 index 0000000..45495b7 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/InscriptionService.java @@ -0,0 +1,34 @@ +package ovh.herisson.Clyde.Services; + +import org.springframework.stereotype.Service; +import ovh.herisson.Clyde.Repositories.InscriptionRepository; +import ovh.herisson.Clyde.Tables.InscriptionRequest; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class InscriptionService { + + InscriptionRepository incriptionRepo; + public void save(InscriptionRequest inscriptionRequest){ + incriptionRepo.save(inscriptionRequest); + } + + public InscriptionService(InscriptionRepository inscriptionRepo){ + this.incriptionRepo = inscriptionRepo; + } + + public InscriptionRequest getById(long id){ + InscriptionRequest inscriptionRequest = incriptionRepo.findById(id); + + if (inscriptionRequest == null){ + return null; + } + return inscriptionRequest; + } + + public Iterable getAll(){ + return incriptionRepo.findAll(); + } +} \ No newline at end of file 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..c7f8d1b --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/StorageService.java @@ -0,0 +1,70 @@ +package ovh.herisson.Clyde.Services; + +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import ovh.herisson.Clyde.Repositories.FileRepository; +import ovh.herisson.Clyde.Tables.*; + +import java.io.File; +import java.io.IOException; + +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; + + if(!Files.exists(rootLocation)){ + try { + Files.createDirectories(rootLocation); + } catch(IOException e){ + e.printStackTrace(); + } + } + } + + + public StorageFile 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(); + + return fileRepo.save(new StorageFile(file.getName(),url, fileType)); + } + + public void delete(StorageFile file) throws SecurityException { + File f = new File(file.getUrl()); + f.delete(); + + //Delete l'entité + fileRepo.delete(file); + } +} 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..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,31 +1,38 @@ 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){ 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,11 +42,34 @@ 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 - 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/Services/UserService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/UserService.java index f16c68f..55a2f92 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/UserService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/UserService.java @@ -5,16 +5,10 @@ import org.springframework.stereotype.Service; import ovh.herisson.Clyde.Repositories.UserRepository; import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.User; - -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; +import java.util.*; @Service public class UserService { - private final UserRepository userRepo; private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); @@ -34,17 +28,79 @@ public class UserService { } } + /** modify the target data + * verify the permission of modifying from the poster + * + * @param poster the user wanting to modify target's data + * @param updates the changes to be made + * @param target the user to update + * @return if the changes were done or not + */ + public boolean modifyData(User poster, Map updates, User target){ + + if (poster.getRegNo().equals(target.getRegNo())){ + for (Map.Entry entry : updates.entrySet()){ + + if ( entry.getKey().equals("regNo") || entry.getKey().equals("role")) {return false;} + + switch (entry.getKey()){ + case "firstName": + target.setFirstName((String) entry.getValue()); + break; + case "lastName": + target.setLastName((String) entry.getValue()); + break; + case "email": + target.setEmail((String) entry.getValue()); + break; + case "address": + target.setAddress((String) entry.getValue()); + break; + case "country": + target.setCountry((String) entry.getValue()); + break; + case "birthDate": + target.setBirthDate((Date) entry.getValue()); + break; + case "profilePictureUrl": + target.setProfilePictureUrl((String) entry.getValue()); + break; + case "password": + target.setPassword(passwordEncoder.encode((String) entry.getValue())); + break; + } + } + userRepo.save(target); + return true; + } + // the secretary can change roles (for example if a student becomes a teacher) + else if (poster.getRole() == Role.Secretary) + { + for (Map.Entry entry : updates.entrySet()){ + + if ( !entry.getKey().equals("role")) {return false;} + + if (entry.getValue() == Role.Admin){return false;} + + target.setRole((Role) entry.getValue()); + userRepo.save(target); + return true; + } + } + return false; + } + public boolean checkPassword(User user, String tryingPassword){ return passwordEncoder.matches(tryingPassword, user.getPassword()); } public void save(User user){ + user.setPassword(passwordEncoder.encode(user.getPassword())); userRepo.save(user); } public Iterable getAll(){ return userRepo.findAll(); } - } \ No newline at end of file diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Cursus.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Cursus.java index 5167197..172ec7d 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/Cursus.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Cursus.java @@ -13,6 +13,12 @@ public class Cursus { private int year; private String option; + public static Cursus infoBab1 = new Cursus(1,"info"); + + public static Cursus chemistryBab1 = new Cursus(1,"chemistry"); + + public static Cursus psychologyBab1 = new Cursus(1,"psychology"); + public Cursus(int year, String option){ this.year = year; this.option = option; diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/CursusType.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/CursusType.java new file mode 100644 index 0000000..5e9c50f --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/CursusType.java @@ -0,0 +1,8 @@ +package ovh.herisson.Clyde.Tables; + +public enum CursusType { + + infoBab1, + chemistryBab1, + psychologyBab1; +} 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/InscriptionRequest.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java new file mode 100644 index 0000000..aecebe2 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/InscriptionRequest.java @@ -0,0 +1,115 @@ +package ovh.herisson.Clyde.Tables; + +import jakarta.persistence.*; + +import java.util.Date; + + +@Entity +public class InscriptionRequest { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String firstName; + private String lastName; + private String address; + private String email; + private String country; + private Date birthDate; + + @ManyToOne + @JoinColumn(name="Cursus") + private Cursus cursus; + private RequestState state; + private String profilePicture; + + private String password; + public InscriptionRequest(){} + public InscriptionRequest(String lastName, String firstName, String address, String email, String country, Date birthDate, RequestState state, String profilePicture, String password){ + this.lastName = lastName; + this.firstName = firstName; + this.address = address; + this.email = email; + this.country = country; + this.birthDate = birthDate; + this.state = state; + this.profilePicture = profilePicture; + this.password = password; + } + + 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 getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + 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..c7c5569 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/ReinscriptionRequest.java @@ -0,0 +1,75 @@ +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 = false; + + 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 ReinscriptionRequest(User user, Cursus newCursus, RequestState state){ + this.user = user; + this.newCursus = newCursus; + this.state = state; + } + + 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/Role.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Role.java index bb14f3f..4e4469b 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/Role.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/Role.java @@ -4,5 +4,6 @@ public enum Role { Teacher, Student, Admin, + InscriptionService, Secretary; } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/Secretary.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Secretary.java deleted file mode 100644 index cc34841..0000000 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/Secretary.java +++ /dev/null @@ -1,42 +0,0 @@ -package ovh.herisson.Clyde.Tables; - -import jakarta.persistence.*; - -@Entity -public class Secretary { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private int id; - - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "Users") - private User user; - private String faculty; - - public Secretary(User user, String faculty){ - this.user = user; - this.faculty = faculty; - } - - public Secretary() {} - - public int getId() { - return id; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getFaculty() { - return faculty; - } - - public void setFaculty(String faculty) { - this.faculty = faculty; - } -} 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..afa7985 --- /dev/null +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/StorageFile.java @@ -0,0 +1,60 @@ +package ovh.herisson.Clyde.Tables; + +import jakarta.persistence.*; + + +@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/Token.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/Token.java index 5b61cb9..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 { @@ -8,17 +12,20 @@ public class Token { @Id private int id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.EAGER) @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 95467a4..1f6aa3b 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/User.java @@ -8,14 +8,14 @@ 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 @GeneratedValue(strategy = GenerationType.AUTO) - private int regNo; + private Long regNo; private String lastName; private String firstName; + @Column(unique = true) private String email; private String address; private String country; @@ -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; @@ -35,9 +37,34 @@ 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(){ + public Long getRegNo(){ return this.regNo; } public String getLastName() { diff --git a/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCursus.java b/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCursus.java index a5c5153..6590b2d 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCursus.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Tables/UserCursus.java @@ -9,11 +9,11 @@ public class UserCursus { private int id; //Un étudiant peut avoir plusieurs cursus - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "Users") private User user; - @OneToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "Cursus") private Cursus cursus; diff --git a/frontend/build.gradle.kts b/frontend/build.gradle.kts index 0d3dcd1..0726d4b 100644 --- a/frontend/build.gradle.kts +++ b/frontend/build.gradle.kts @@ -18,8 +18,3 @@ var dev = tasks.register("dev") { tasks.register("run") { dependsOn(dev) } - -tasks.register("test") { - dependsOn(tasks.npmInstall) - args.set(listOf("run", "test:unit")) -} diff --git a/frontend/public/i18n/EN.txt b/frontend/public/i18n/EN.txt index bc4eb40..90a001d 100644 --- a/frontend/public/i18n/EN.txt +++ b/frontend/public/i18n/EN.txt @@ -1,11 +1,9 @@ -# English translations (some examples to remove) - login.guest.signin=Sign in login.guest.register=Register login.guest.alregister=Already Registered login.guest.welcome=WELCOME TO THE UNIVERSITY login.guest.email=E-MAIL -login.guest.firstname= FIRSTNAME +login.guest.firstname=FIRSTNAME login.guest.surname=SURNAME login.guest.country=COUNTRY login.guest.address=ADDRESS @@ -15,6 +13,8 @@ login.guest.lastpage=Last Page login.guest.submit=Submit login.guest.birthday=BIRTHDAY login.guest.confirm=CONFIRM +login.cPassword=Confirm Password +login.password=Password app.home=Home app.login=Login app.notifications=Notifications @@ -23,8 +23,28 @@ app.messages=Messages app.forum=Forum app.schedules=Schedules app.inscription.requests=Inscription Requests +app.manage.courses=Manage Courses +app.language=Language +app.manage.profile=Manage profile request.moreInfos=More Infos request.accept=Accept request.refuse=Refuse -#===================================================== - +courses.createCourse=Create course +courses.deleteCourse=Delete course +courses.modify=Modify +courses.toDelete=Course to Delete +courses.confirm=Confirm +courses.back=Back +profile.modify.data=Modify personnal data +profile.reRegister=Re-register +profile.unRegister=Unregister +profile.course.list=Courses list +profile.address=Address +profile.picture=Profile picture +name=Name +teacher=Teacher +student=Student +secretary=Secretary +curriculum=curriculum +credits=Credits +faculty=Faculty diff --git a/frontend/public/i18n/FR.txt b/frontend/public/i18n/FR.txt index 42ab8bf..c2f7689 100644 --- a/frontend/public/i18n/FR.txt +++ b/frontend/public/i18n/FR.txt @@ -1,20 +1,20 @@ -# Traductions françaises (Quelques examples a enlever) - login.guest.signin=SE CONNECTER login.guest.register=S'enregistrer login.guest.alregister=Déjà Enregistré login.guest.welcome=BIENVENUE A L'UNIVERSITE login.guest.email=E-MAIL -login.guest.firstname= PRENOM -login.guest.surname= NOM -login.guest.country= PAYS +login.guest.firstname=PRENOM +login.guest.surname=NOM +login.guest.country=PAYS login.guest.address=ADRESSE -login.guest.password= MOT DE PASSE +login.guest.password=MOT DE PASSE login.guest.nextpage=Prochaine Page login.guest.lastpage=Derniere Page login.guest.submit=Envoyer login.guest.birthday=DATE DE NAISSANCE login.guest.confirm=CONFIRMER +login.cPassword=Confirmer mot de passe +login.password=Mot de passe app.home=Home app.login=Se connecter app.notifications=Notifications @@ -23,7 +23,28 @@ app.messages=Messages app.forum=Forum app.schedules=Horaires app.inscription.requests=Demandes d'Inscription +app.manage.courses=Gérer les cours +app.language=Langue +app.manage.profile=Gérer le profil request.moreInfos=Plus d'Infos request.accept=Accepter request.refuse=Refuser -#===================================================== +courses.createCourse=Créer un cours +courses.deleteCourse=Supprimer un cours +courses.modify=Modifier +courses.toDelete=Cours à supprimer +courses.confirm=Confirmer +courses.back=Retour +profile.modify.data=Modifier données personnelles +profile.reRegister=Réinsciption +profile.unRegister=Désinscription +profile.course.list=Liste des cours +profile.address=Adresse +profile.picture=Photo de profil +name=Nom +teacher=Enseignant +student=Etudiant +secretary=Secrétaire +curriculum=Cursus +credits=Credits +faculty=Faculté diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 51f8882..7b944de 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -7,17 +7,21 @@ // Liste des apps import LoginPage from './Apps/Login.vue' import Inscription from "./Apps/Inscription.vue" + import Profil from "./Apps/Profil.vue" + import Courses from "./Apps/ManageCourses.vue" const apps = { '/login': LoginPage, - '/inscription': Inscription + '/inscription': Inscription, + '/profil': Profil, + '/manage-courses' : Courses, } const currentPath = ref(window.location.hash) window.addEventListener('hashchange', () => { currentPath.value = window.location.hash }) - + const currentView = computed(() => { return apps[currentPath.value.slice(1) || '/'] }) @@ -26,9 +30,8 @@ const notifications=ref(i18n("app.notifications")) const settings=ref(i18n("app.settings")) const login=ref(i18n("app.login")) + const active=ref(false) - -