Compare commits
15 Commits
a27cf63daf
...
8a5a26e2ab
Author | SHA1 | Date | |
---|---|---|---|
8a5a26e2ab | |||
c9556e1eea | |||
78507f798f | |||
f9b12a5061 | |||
8724748642 | |||
f19236b3f7 | |||
cba11d54ff | |||
b9d7950e12 | |||
c0233fce57 | |||
451944e4fb | |||
61eac8959a | |||
3761fa6f49 | |||
cb36aa8a30 | |||
2e2837fec4 | |||
0e26e1a0db |
29
README.md
29
README.md
@ -9,10 +9,33 @@ Projet du groupe 01:
|
|||||||
- William Karpinski: Extension gestion des horaires
|
- William Karpinski: Extension gestion des horaires
|
||||||
- Léo Moulin: Extension inscription des étudiants
|
- Léo Moulin: Extension inscription des étudiants
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
Le projet peut être lancé grace à docker compose.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ docker compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
Dans le cas ou vous modifiers des fichiers, pour éviter que les images de docker soient recrées avec les changement
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ docker compose up --force-recreate --build
|
||||||
|
```
|
||||||
|
|
||||||
## Dévelopement
|
## Dévelopement
|
||||||
|
|
||||||
```
|
Dans le cas ou vous êtes dans une phase de développement, il est plus simple d'utiliser gradle pour lancer le backend et frontend dans un mode de développement.
|
||||||
$ ./gradlew backend:run frontend:run --parallel
|
**Attention**: Ce mode n'est pas fait pour être utilisé en production!
|
||||||
```
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ ./gradlew run --parallel
|
||||||
|
```
|
||||||
permet de lancer le frontend sur [http://localhost:5173](http://localhost:5173) ansi que le frontend sur [http://localhost:8080](http://localhost:8080)
|
permet de lancer le frontend sur [http://localhost:5173](http://localhost:5173) ansi que le frontend sur [http://localhost:8080](http://localhost:8080)
|
||||||
|
|
||||||
|
Ceci requière également docker pour lancer une instance de postgresql pris en charge par spring.
|
||||||
|
|
||||||
|
Il est possible de se passer entièrement de docker en supprimant la dépendance dans le fichier `backend/build.gradle.kts`: ~~`developmentOnly("org.springframework.boot:spring-boot-docker-compose")`~~
|
||||||
|
Il est alors nécéssaire d'avoir une instance de postgresql tournant sur `localhost:5432` avec une table `clyde`, utilisateur: `devel` et password: `devel`
|
||||||
|
(cette configuration peut également être changée dans le fichier resources/application.properties de spring)
|
||||||
|
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
|
## Building phase
|
||||||
|
FROM gradle:jdk21-alpine AS BUILD
|
||||||
|
WORKDIR /backend
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN gradle build -x test
|
||||||
|
|
||||||
|
## Running Phase
|
||||||
FROM eclipse-temurin:21-jdk-alpine
|
FROM eclipse-temurin:21-jdk-alpine
|
||||||
VOLUME /tmp
|
WORKDIR /backend
|
||||||
VOLUME /cdn
|
VOLUME /cdn
|
||||||
ENV SPRING_PROFILES_ACTIVE=prod
|
# ENV SPRING_PROFILES_ACTIVE=prod
|
||||||
COPY build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar
|
COPY --from=BUILD /backend/build/libs/Clyde-0.0.1-SNAPSHOT.jar /backend/app.jar
|
||||||
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
EXPOSE 8080
|
||||||
|
ENTRYPOINT ["java", "-jar", "/backend/app.jar"]
|
||||||
|
13
backend/settings.gradle.kts
Normal file
13
backend/settings.gradle.kts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* This file was generated by the Gradle 'init' task.
|
||||||
|
*
|
||||||
|
* The settings file is used to specify which projects to include in your build.
|
||||||
|
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.6/userguide/multi_project_builds.html in the Gradle documentation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
// Apply the foojay-resolver plugin to allow automatic download of JDKs
|
||||||
|
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "Clyde"
|
@ -20,6 +20,7 @@ import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest;
|
|||||||
import ovh.herisson.Clyde.Tables.Inscription.UnregisterRequest;
|
import ovh.herisson.Clyde.Tables.Inscription.UnregisterRequest;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -196,4 +197,58 @@ public class RequestsController {
|
|||||||
|
|
||||||
return new ResponseEntity<>(HttpStatus.OK);
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/changecurriculumreq")
|
||||||
|
public ResponseEntity<ArrayList <ChangeCurriculumRequest>> getAllChangeCurrReq(@RequestHeader("Authorization") String token){
|
||||||
|
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
|
||||||
|
return new UnauthorizedResponse<>(null);
|
||||||
|
|
||||||
|
ArrayList<ChangeCurriculumRequest> toReturn = new ArrayList<>();
|
||||||
|
|
||||||
|
changeCurriculumRequestRepository.findAll().forEach(toReturn::add);
|
||||||
|
|
||||||
|
return new ResponseEntity<>(toReturn, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/changecurriculumreq/{id}")
|
||||||
|
public ResponseEntity<ChangeCurriculumRequest> getCCrbyId(@RequestHeader("Authorization") String token, @PathVariable long id){
|
||||||
|
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
|
||||||
|
return new UnauthorizedResponse<>(null);
|
||||||
|
|
||||||
|
ChangeCurriculumRequest toReturn = changeCurriculumRequestRepository.findById(id);
|
||||||
|
return new ResponseEntity<>(toReturn, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PatchMapping("/changecurriculumreq/{id}/{newState}")
|
||||||
|
public ResponseEntity<String> editCCReq(@RequestHeader("Authorization") String token, @PathVariable long id, @PathVariable RequestState newState){
|
||||||
|
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
|
||||||
|
return new UnauthorizedResponse<>(null);
|
||||||
|
|
||||||
|
ChangeCurriculumRequest toEdit = changeCurriculumRequestRepository.findById(id);
|
||||||
|
|
||||||
|
toEdit.setState(newState);
|
||||||
|
|
||||||
|
if (newState == RequestState.Accepted){
|
||||||
|
//If actual curriculum is not null then we need to set that the user doesn't follow it anymore
|
||||||
|
User u = toEdit.getUser();
|
||||||
|
if (toEdit.getActualCurriculum() != null){
|
||||||
|
ArrayList<UserCurriculum> listcurr = userCurriculumRepository.findByUserOrderByCurriculum(u);
|
||||||
|
|
||||||
|
for (int i = 0; i < listcurr.size(); i++){
|
||||||
|
if (listcurr.get(i).getCurriculum() == toEdit.getActualCurriculum()){
|
||||||
|
listcurr.get(i).setActual(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userCurriculumRepository.saveAll(listcurr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Calendar c = Calendar.getInstance();
|
||||||
|
UserCurriculum userCurriculum = new UserCurriculum(u, toEdit.getDestinationCurriculum(), c.get(Calendar.YEAR), true);
|
||||||
|
userCurriculumRepository.save(userCurriculum);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeCurriculumRequestRepository.save(toEdit);
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
public class MockController {
|
public class MockController {
|
||||||
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
|
public final UserService userService;
|
||||||
public final UserRepository userRepo;
|
public final UserRepository userRepo;
|
||||||
public final TokenRepository tokenRepo;
|
public final TokenRepository tokenRepo;
|
||||||
public final TokenService tokenService;
|
public final TokenService tokenService;
|
||||||
@ -39,7 +39,8 @@ public class MockController {
|
|||||||
public final ScholarshipRequestRepository scholarshipRequestRepository;
|
public final ScholarshipRequestRepository scholarshipRequestRepository;
|
||||||
|
|
||||||
public final UnregisterRequestRepository uninscriptionRequestRepository;
|
public final UnregisterRequestRepository uninscriptionRequestRepository;
|
||||||
public MockController(UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, ExternalCurriculumRepository externalCurriculumRepository, InscriptionService inscriptionService, UserCurriculumRepository ucr, MinervalRepository minervalRepository, ScholarshipRequestRepository scholarshipRequestRepository, UnregisterRequestRepository unregisterRequestRepository){
|
public MockController(UserService userService, UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, ExternalCurriculumRepository externalCurriculumRepository, InscriptionService inscriptionService, UserCurriculumRepository ucr, MinervalRepository minervalRepository, ScholarshipRequestRepository scholarshipRequestRepository, UnregisterRequestRepository unregisterRequestRepository){
|
||||||
|
this.userService = userService;
|
||||||
this.tokenRepo = tokenRepo;
|
this.tokenRepo = tokenRepo;
|
||||||
this.userRepo = userRepo;
|
this.userRepo = userRepo;
|
||||||
this.tokenService = tokenService;
|
this.tokenService = tokenService;
|
||||||
@ -73,7 +74,7 @@ public class MockController {
|
|||||||
User popo = new User("Smith", "Paul", "paulsmith@gmail.com", "306 rue du poulet", "belgique", new Date(0), null, Role.Student, passwordEncoder.encode("jesuispaulleroi"));
|
User popo = new User("Smith", "Paul", "paulsmith@gmail.com", "306 rue du poulet", "belgique", new Date(0), null, Role.Student, passwordEncoder.encode("jesuispaulleroi"));
|
||||||
mockUsers = new ArrayList<>(Arrays.asList(herobrine,joe,meh,joke,lena,jojo, popo));
|
mockUsers = new ArrayList<>(Arrays.asList(herobrine,joe,meh,joke,lena,jojo, popo));
|
||||||
|
|
||||||
userRepo.saveAll(mockUsers);
|
userService.saveAll(mockUsers);
|
||||||
|
|
||||||
Minerval minerval = new Minerval(joe.getRegNo(), 0, 852, 2023);
|
Minerval minerval = new Minerval(joe.getRegNo(), 0, 852, 2023);
|
||||||
minervalRepository.save(minerval);
|
minervalRepository.save(minerval);
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
package ovh.herisson.Clyde;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
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
|
|
||||||
@Profile("!prod")
|
|
||||||
public DataSource psqlSource(){
|
|
||||||
DriverManagerDataSource source = new DriverManagerDataSource();
|
|
||||||
source.setDriverClassName("org.postgresql.Driver");
|
|
||||||
source.setUrl("jdbc:postgresql://localhost:5442/clyde");
|
|
||||||
source.setUsername("devel");
|
|
||||||
source.setPassword("devel");
|
|
||||||
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Profile("prod")
|
|
||||||
public DataSource psqlSourceProd(){
|
|
||||||
DriverManagerDataSource source = new DriverManagerDataSource();
|
|
||||||
source.setDriverClassName("org.postgresql.Driver");
|
|
||||||
source.setUrl("jdbc:postgresql:clyde?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432");
|
|
||||||
source.setUsername("clyde");
|
|
||||||
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,4 +4,6 @@ import org.springframework.data.repository.CrudRepository;
|
|||||||
import ovh.herisson.Clyde.Tables.ChangeCurriculumRequest;
|
import ovh.herisson.Clyde.Tables.ChangeCurriculumRequest;
|
||||||
|
|
||||||
public interface ChangeCurriculumRequestRepository extends CrudRepository<ChangeCurriculumRequest, Long> {
|
public interface ChangeCurriculumRequestRepository extends CrudRepository<ChangeCurriculumRequest, Long> {
|
||||||
|
ChangeCurriculumRequest findById(long id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,4 +15,5 @@ public interface UserCurriculumRepository extends CrudRepository<UserCurriculum,
|
|||||||
|
|
||||||
ArrayList<UserCurriculum> findByUserOrderByCurriculum(User student);
|
ArrayList<UserCurriculum> findByUserOrderByCurriculum(User student);
|
||||||
UserCurriculum findByUserAndCurriculumAndActual(User user, Curriculum curriculum, boolean actual);
|
UserCurriculum findByUserAndCurriculumAndActual(User user, Curriculum curriculum, boolean actual);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import ovh.herisson.Clyde.Repositories.*;
|
|||||||
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
|
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
|
||||||
import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository;
|
import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository;
|
||||||
import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository;
|
import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository;
|
||||||
|
import ovh.herisson.Clyde.Services.UserService;
|
||||||
import ovh.herisson.Clyde.Tables.*;
|
import ovh.herisson.Clyde.Tables.*;
|
||||||
import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum;
|
import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum;
|
||||||
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
|
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
|
||||||
@ -28,14 +29,15 @@ public class InscriptionService {
|
|||||||
private final MinervalRepository minervalRepository;
|
private final MinervalRepository minervalRepository;
|
||||||
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
private final ExternalCurriculumRepository externalCurriculumRepository;
|
private final ExternalCurriculumRepository externalCurriculumRepository;
|
||||||
|
private final UserService userService;
|
||||||
public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo, MinervalRepository minervalRepository, ExternalCurriculumRepository externalCurriculumRepository){
|
public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo, MinervalRepository minervalRepository, ExternalCurriculumRepository externalCurriculumRepository, UserService userService){
|
||||||
this.inscriptionRepo = inscriptionRepo;
|
this.inscriptionRepo = inscriptionRepo;
|
||||||
this.userRepo = userRepo;
|
this.userRepo = userRepo;
|
||||||
this.userCurriculumRepo = userCurriculumRepo;
|
this.userCurriculumRepo = userCurriculumRepo;
|
||||||
this.curriculumRepo = curriculumRepo;
|
this.curriculumRepo = curriculumRepo;
|
||||||
this.minervalRepository = minervalRepository;
|
this.minervalRepository = minervalRepository;
|
||||||
this.externalCurriculumRepository = externalCurriculumRepository;
|
this.externalCurriculumRepository = externalCurriculumRepository;
|
||||||
|
this.userService = userService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InscriptionRequest save(InscriptionRequest inscriptionRequest){
|
public InscriptionRequest save(InscriptionRequest inscriptionRequest){
|
||||||
@ -85,7 +87,7 @@ public class InscriptionService {
|
|||||||
inscrRequest.getPassword()
|
inscrRequest.getPassword()
|
||||||
);
|
);
|
||||||
|
|
||||||
userRepo.save(userFromRequest);
|
userService.save(userFromRequest);
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
userCurriculumRepo.save(new UserCurriculum(userFromRequest, curriculumRepo.findById(inscrRequest.getCurriculumId()),c.get(Calendar.YEAR), true));
|
userCurriculumRepo.save(new UserCurriculum(userFromRequest, curriculumRepo.findById(inscrRequest.getCurriculumId()),c.get(Calendar.YEAR), true));
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package ovh.herisson.Clyde.Services;
|
|||||||
|
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import ovh.herisson.Clyde.Tables.RegNoGenerator;
|
||||||
import ovh.herisson.Clyde.Repositories.UserRepository;
|
import ovh.herisson.Clyde.Repositories.UserRepository;
|
||||||
import ovh.herisson.Clyde.Tables.Role;
|
import ovh.herisson.Clyde.Tables.Role;
|
||||||
import ovh.herisson.Clyde.Tables.User;
|
import ovh.herisson.Clyde.Tables.User;
|
||||||
@ -106,10 +107,17 @@ public class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public User save(User user){
|
public User save(User user){
|
||||||
|
RegNoGenerator.resetCount();
|
||||||
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||||
return userRepo.save(user);
|
return userRepo.save(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveAll(ArrayList<User> list){
|
||||||
|
//S'assure que le compteur est bien a 0
|
||||||
|
RegNoGenerator.resetCount();
|
||||||
|
userRepo.saveAll(list);
|
||||||
|
}
|
||||||
|
|
||||||
public Iterable<User> getAll(){
|
public Iterable<User> getAll(){
|
||||||
return userRepo.findAll();
|
return userRepo.findAll();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package ovh.herisson.Clyde.Tables;
|
||||||
|
|
||||||
|
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
public class RegNoGenerator implements IdentifierGenerator {
|
||||||
|
private static int count = 0;
|
||||||
|
@Override
|
||||||
|
public Object generate(SharedSessionContractImplementor session, Object object) {
|
||||||
|
try{
|
||||||
|
JdbcConnectionAccess jdbccon = session.getJdbcConnectionAccess();
|
||||||
|
Connection conn = jdbccon.obtainConnection();
|
||||||
|
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
|
||||||
|
Calendar c = new GregorianCalendar();
|
||||||
|
int y = c.get(Calendar.YEAR);
|
||||||
|
String query = "select count(reg_no) + "+count+" from Users where reg_no/10000 = " + y%1000;
|
||||||
|
|
||||||
|
ResultSet set = statement.executeQuery(query);
|
||||||
|
long resp = 0;
|
||||||
|
if(set.next()){
|
||||||
|
resp = set.getLong(1)+((y%1000)*10000);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.close();
|
||||||
|
statement.close();
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetCount(){
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,22 @@
|
|||||||
package ovh.herisson.Clyde.Tables;
|
package ovh.herisson.Clyde.Tables;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import org.hibernate.annotations.OnDelete;
|
import org.hibernate.annotations.OnDelete;
|
||||||
import org.hibernate.annotations.OnDeleteAction;
|
import org.hibernate.annotations.OnDeleteAction;
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
import ovh.herisson.Clyde.Tables.Msg.Discussion;
|
import ovh.herisson.Clyde.Tables.Msg.Discussion;
|
||||||
import ovh.herisson.Clyde.Tables.Msg.Message;
|
import ovh.herisson.Clyde.Tables.Msg.Message;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "Users")
|
@Table(name = "Users")
|
||||||
public class User {
|
public class User {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GenericGenerator(name = "userGen", type = ovh.herisson.Clyde.Tables.RegNoGenerator.class)
|
||||||
|
@GeneratedValue(generator = "userGen")
|
||||||
private Long regNo;
|
private Long regNo;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
private String firstName;
|
private String firstName;
|
||||||
@ -24,7 +26,9 @@ public class User {
|
|||||||
private String country;
|
private String country;
|
||||||
private Date birthDate;
|
private Date birthDate;
|
||||||
private String profilePictureUrl;
|
private String profilePictureUrl;
|
||||||
private ovh.herisson.Clyde.Tables.Role role;
|
private Role role;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
////// Extension Messagerie /////
|
////// Extension Messagerie /////
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
spring.jpa.hibernate.ddl-auto=create-drop
|
spring.jpa.hibernate.ddl-auto=create-drop
|
||||||
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
|
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
|
||||||
spring.sql.init.mode=always
|
spring.sql.init.mode=always
|
||||||
|
|
||||||
|
# spring.datasource.url=jdbc:postgresql://localhost:5442/clyde
|
||||||
|
spring.datasource.url=jdbc:postgresql://db:5432/clyde
|
||||||
|
spring.datasource.username=devel
|
||||||
|
spring.datasource.password=devel
|
||||||
|
|
||||||
|
# spring.config.activate.on-profile=prod
|
||||||
|
# spring.datasource.url=jdbc:postgresql:clyde?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432
|
||||||
|
# spring.datasource.username=clyde
|
||||||
|
@ -24,6 +24,7 @@ public class UserRepoTest {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setup(){
|
public void setup(){
|
||||||
|
userRepo.deleteAll();
|
||||||
User herobrine = new User("brine","hero","admin@admin.com","in your WalLs","ShadowsLand", new GregorianCalendar(2005, 4, 3).getTime(), null, Role.Admin,"admin");
|
User herobrine = new User("brine","hero","admin@admin.com","in your WalLs","ShadowsLand", new GregorianCalendar(2005, 4, 3).getTime(), null, Role.Admin,"admin");
|
||||||
userRepo.save(herobrine);
|
userRepo.save(herobrine);
|
||||||
}
|
}
|
||||||
@ -34,8 +35,8 @@ public class UserRepoTest {
|
|||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void usertest(){
|
public void usertest(){
|
||||||
Assert.assertEquals("brine", userRepo.findById(1).getLastName());
|
Assert.assertEquals("brine", userRepo.findByEmail("admin@admin.com").getLastName());
|
||||||
Assert.assertTrue(new GregorianCalendar(2005, 4, 3).getTime().equals(userRepo.findById(1).getBirthDate()));
|
Assert.assertTrue(new GregorianCalendar(2005, 4, 3).getTime().equals(userRepo.findByEmail("admin@admin.com").getBirthDate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
29
compose.yaml
Normal file
29
compose.yaml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: 'postgres:16'
|
||||||
|
environment:
|
||||||
|
- 'POSTGRES_DB=clyde'
|
||||||
|
- 'POSTGRES_USER=devel'
|
||||||
|
- 'POSTGRES_PASSWORD=devel'
|
||||||
|
# Uncomment this to allow connections to the db from outside the container
|
||||||
|
# ports:
|
||||||
|
# - '5442:5432'
|
||||||
|
back:
|
||||||
|
build: backend/.
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- cdn:/backend/cdn
|
||||||
|
ulimits:
|
||||||
|
nofile:
|
||||||
|
soft: 65536
|
||||||
|
hard: 65536
|
||||||
|
front:
|
||||||
|
build: frontend/.
|
||||||
|
volumes:
|
||||||
|
- cdn:/app/front/dist/cdn
|
||||||
|
ports:
|
||||||
|
- "8000:8080"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
cdn:
|
11
frontend/Dockerfile
Normal file
11
frontend/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# https://v2.vuejs.org/v2/cookbook/dockerize-vuejs-app
|
||||||
|
FROM node:lts-alpine
|
||||||
|
RUN npm install -g http-server
|
||||||
|
WORKDIR /app/front
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY . .
|
||||||
|
ENV VITE_CLYDE_MODE=container
|
||||||
|
RUN npm run build
|
||||||
|
EXPOSE 8080
|
||||||
|
CMD [ "http-server", "dist" ]
|
@ -96,20 +96,19 @@ window.addEventListener('hashchange', () => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display:grid;
|
display:grid;
|
||||||
grid-template-columns:[firstCol-start]70px[firstCol-end secondCol-start]auto[endCol];
|
|
||||||
grid-template-rows:[firstRow-start]61px[firstRow-end secondRow-start] auto [endRow];
|
grid-template-columns:[firstCol-start]70px[firstCol-end secondCol-start] auto [endCol];
|
||||||
|
grid-template-rows:[firstRow-start] var(--header-size) [firstRow-end secondRow-start] calc(100% - var(--header-size)) [endRow];
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"topBar topBar"
|
"topBar topBar"
|
||||||
"leftBar page";
|
"leftBar page";
|
||||||
row-gap:0px;
|
|
||||||
column-gap:0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
grid-area:page;
|
grid-area:page;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
place-self:center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.topBar{
|
.topBar{
|
||||||
@ -152,7 +151,7 @@ window.addEventListener('hashchange', () => {
|
|||||||
|
|
||||||
ul.vertical{
|
ul.vertical{
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin-top: 61px;
|
margin-top: var(--header-size);
|
||||||
top:0;
|
top:0;
|
||||||
left:0;
|
left:0;
|
||||||
padding: 25px 0 0;
|
padding: 25px 0 0;
|
||||||
@ -200,7 +199,7 @@ window.addEventListener('hashchange', () => {
|
|||||||
left:0;
|
left:0;
|
||||||
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height:61px;
|
height:var(--header-size);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: rgb(24, 24, 24);
|
background-color: rgb(24, 24, 24);
|
||||||
}
|
}
|
||||||
|
115
frontend/src/Apps/Inscription/AboutChangeCurriculum.vue
Normal file
115
frontend/src/Apps/Inscription/AboutChangeCurriculum.vue
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
import {
|
||||||
|
addUninscReq, editChangeCurrReq,
|
||||||
|
editScholarshipReq,
|
||||||
|
editUnregReq, getChangeCurrReqById,
|
||||||
|
getScholarshipReqById,
|
||||||
|
getUnregisterbyId
|
||||||
|
} from "@/rest/requests.js";
|
||||||
|
import i18n from "@/i18n.js";
|
||||||
|
import {getUser} from "@/rest/Users.js";
|
||||||
|
import {reactive, ref} from "vue";
|
||||||
|
import AboutStudent from "@/Apps/Inscription/AboutStudent.vue";
|
||||||
|
|
||||||
|
const props = defineProps(["reqId"])
|
||||||
|
const req = ref(await getChangeCurrReqById(props.reqId))
|
||||||
|
|
||||||
|
|
||||||
|
//0 liste, 1 profil
|
||||||
|
const windowstate = ref(0);
|
||||||
|
|
||||||
|
const tag = req.value.user.regNo
|
||||||
|
|
||||||
|
async function uploadandrefreshChangeRequest(state){
|
||||||
|
await editChangeCurrReq(req.value.id, state);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="body" v-if="windowstate === 0">
|
||||||
|
<div class="container">
|
||||||
|
<div class="globalInfos">
|
||||||
|
<div class="infosContainer">
|
||||||
|
<div>
|
||||||
|
Firstname/Name : {{req.user.firstName}} {{req.user.lastName}}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
regNo : {{req.user.regNo}}
|
||||||
|
</div>
|
||||||
|
<div v-if="req.actualCurriculum !== null">
|
||||||
|
From : Bac {{req.actualCurriculum.year}} {{req.actualCurriculum.option}}
|
||||||
|
To : Bac {{req.destinationCurriculum.year}} {{req.destinationCurriculum.option}}
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
Wanted cursus : Bac {{req.destinationCurriculum.year}} {{req.destinationCurriculum.option}}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button @click="windowstate++"> See profile </button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button v-if="req.state === 'Pending'" @click="req.state='Accepted';uploadandrefreshChangeRequest('Accepted')">Accept</button>
|
||||||
|
<button v-if="req.state === 'Pending'" @click="req.state='Refused';uploadandrefreshChangeRequest('Refused')" style="margin-left: 2%;">Refuse</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="windowstate === 1">
|
||||||
|
<AboutStudent :target="tag"></AboutStudent>
|
||||||
|
<button @click="windowstate--;">Return to request</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container{
|
||||||
|
min-width:675px;
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns:10vw 50vw;
|
||||||
|
grid-template-rows:200px auto;
|
||||||
|
column-gap:2.7%;
|
||||||
|
row-gap:45px;
|
||||||
|
grid-template-areas:
|
||||||
|
"profilPic globalInfos"
|
||||||
|
"minfos minfos";
|
||||||
|
}
|
||||||
|
|
||||||
|
.profilPic{
|
||||||
|
width:100%;
|
||||||
|
grid-area:profilPic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.globalInfos {
|
||||||
|
grid-area:globalInfos;
|
||||||
|
align-self :center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
min-width:960px;
|
||||||
|
width:100%;
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
margin-top:7%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subContainter{
|
||||||
|
width:100%;
|
||||||
|
background-color:rgb(50,50,50);
|
||||||
|
border-radius:20px;
|
||||||
|
border:4px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infosContainer {
|
||||||
|
min-width:350px;
|
||||||
|
padding-bottom:50px;
|
||||||
|
border:2px solid black;
|
||||||
|
font-size:25px;
|
||||||
|
color:white;
|
||||||
|
padding:20px;
|
||||||
|
background-color:rgb(50,50,50);
|
||||||
|
border-radius:20px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,9 +3,15 @@
|
|||||||
import {ref} from 'vue'
|
import {ref} from 'vue'
|
||||||
import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js'
|
import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js'
|
||||||
import AboutRequest from "@/Apps/Inscription/AboutRequest.vue";
|
import AboutRequest from "@/Apps/Inscription/AboutRequest.vue";
|
||||||
import {getAllExemptionsRequest, getAllScholarShipsRequest, getAllUnregisters} from "@/rest/requests.js";
|
import {
|
||||||
|
getAllChangeCurrReq,
|
||||||
|
getAllExemptionsRequest,
|
||||||
|
getAllScholarShipsRequest,
|
||||||
|
getAllUnregisters
|
||||||
|
} from "@/rest/requests.js";
|
||||||
import AboutScholarship from "@/Apps/Inscription/AboutScholarship.vue";
|
import AboutScholarship from "@/Apps/Inscription/AboutScholarship.vue";
|
||||||
import AboutUnregister from "@/Apps/Inscription/AboutUnregister.vue";
|
import AboutUnregister from "@/Apps/Inscription/AboutUnregister.vue";
|
||||||
|
import AboutChangeCurriculum from "@/Apps/Inscription/AboutChangeCurriculum.vue";
|
||||||
|
|
||||||
const requests = ref(await getAllRegisters());
|
const requests = ref(await getAllRegisters());
|
||||||
let targetId = "";
|
let targetId = "";
|
||||||
@ -13,7 +19,7 @@
|
|||||||
const requestType = ref("inscription");
|
const requestType = ref("inscription");
|
||||||
const filterType = ref("None");
|
const filterType = ref("None");
|
||||||
|
|
||||||
//0 = liste, 1 = détails, 2 = sure?, 3 = manage scholarship, 4 manage unregister
|
//0 = liste, 1 = détails, 2 = sure?, 3 = manage scholarship, 4 manage unregister, 5 = manage curriculum change
|
||||||
let windowsState = ref(0);
|
let windowsState = ref(0);
|
||||||
|
|
||||||
async function upPage(id,review){
|
async function upPage(id,review){
|
||||||
@ -35,6 +41,9 @@
|
|||||||
break;
|
break;
|
||||||
case "unregister":
|
case "unregister":
|
||||||
requests.value = await getAllUnregisters();
|
requests.value = await getAllUnregisters();
|
||||||
|
break;
|
||||||
|
case "curriculum change":
|
||||||
|
requests.value = await getAllChangeCurrReq();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -53,6 +62,7 @@
|
|||||||
<option>scholarship</option>
|
<option>scholarship</option>
|
||||||
<option>exemption</option>
|
<option>exemption</option>
|
||||||
<option>unregister</option>
|
<option>unregister</option>
|
||||||
|
<option>curriculum change</option>
|
||||||
</select>
|
</select>
|
||||||
<span style="margin-left: 5%">
|
<span style="margin-left: 5%">
|
||||||
Filter :
|
Filter :
|
||||||
@ -104,6 +114,13 @@
|
|||||||
<div class="reqState">{{item.state}}</div>
|
<div class="reqState">{{item.state}}</div>
|
||||||
<div class="infos"><button @click="windowsState=4;targetId=item.id">More infos</button></div>
|
<div class="infos"><button @click="windowsState=4;targetId=item.id">More infos</button></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="container" v-if="requestType === 'curriculum change'" style="grid-template-columns:17% 15% 12% 15%;grid-template-areas:'date reqState regno studentfirstname studentlastname infos';">
|
||||||
|
<div class="date" v-if="item.date != undefined">{{item.date.slice(0,10)}}</div>
|
||||||
|
<div class="studentfirstname">{{item.user.firstName}}</div>
|
||||||
|
<div class="studentlastname">{{item.user.lastName}}</div>
|
||||||
|
<div class="reqState">{{item.state}}</div>
|
||||||
|
<div class="infos"><button @click="windowsState=5;targetId=item.id">More infos</button></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -121,6 +138,9 @@
|
|||||||
<div v-if="windowsState === 4">
|
<div v-if="windowsState === 4">
|
||||||
<AboutUnregister :req-id="targetId"></AboutUnregister>
|
<AboutUnregister :req-id="targetId"></AboutUnregister>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="windowsState === 5">
|
||||||
|
<AboutChangeCurriculum :req-id="targetId"></AboutChangeCurriculum>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
:root {
|
||||||
|
--header-size: 61px;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: rgb(53, 25, 60);
|
background-color: rgb(53, 25, 60);
|
||||||
margin:0;
|
margin:0;
|
||||||
|
@ -51,3 +51,15 @@ export async function getAllPayments(){
|
|||||||
export async function postChangeCurrReq(item){
|
export async function postChangeCurrReq(item){
|
||||||
return restPost("/changecurriculumreq", item)
|
return restPost("/changecurriculumreq", item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getAllChangeCurrReq(){
|
||||||
|
return restGet("/changecurriculumreq")
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getChangeCurrReqById(id){
|
||||||
|
return restGet("/changecurriculumreq/"+id)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function editChangeCurrReq(id, newState){
|
||||||
|
return restPatch("/changecurriculumreq/"+id+"/"+newState)
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import { getCookie } from '../utils.js'
|
import { getCookie } from '../utils.js'
|
||||||
import { toast } from 'vue3-toastify'
|
import { toast } from 'vue3-toastify'
|
||||||
|
|
||||||
const restURL = import.meta.env.PROD ? "https://clyde.herisson.ovh/api" : "http://localhost:8080"
|
const restURL = import.meta.env.VITE_CLYDE_MODE === 'container' ? "http://localhost:8080": import.meta.env.DEV ? "http://localhost:8080" : "https://clyde.herisson.ovh/api"
|
||||||
|
|
||||||
export async function restGet(endPoint) {
|
export async function restGet(endPoint) {
|
||||||
return await _rest(endPoint, {method: "GET"});
|
return await _rest(endPoint, {method: "GET"});
|
||||||
|
Loading…
Reference in New Issue
Block a user