47 Commits

Author SHA1 Message Date
1fad792be7 Just to merge 2024-03-22 20:14:20 +01:00
3d6941ab93 adding cdn to CI
All checks were successful
Build and test backend / Build-backend (push) Successful in 1m57s
Build and test FrontEnd / Build-frontend (push) Successful in 23s
deploy to production / deploy-frontend (push) Successful in 27s
deploy to production / deploy-backend (push) Successful in 1m29s
2024-03-18 21:39:31 +01:00
de72bd800c CI fix
All checks were successful
Build and test backend / Build-backend (push) Successful in 1m53s
deploy to production / deploy-frontend (push) Successful in 26s
deploy to production / deploy-backend (push) Successful in 2m3s
Build and test FrontEnd / Build-frontend (push) Successful in 23s
2024-03-18 21:13:00 +01:00
b465dcfa92 Merge pull request 'Clean le projet' (#146) from Leo/Backend/Cleaning into master
Some checks failed
Build and test backend / Build-backend (push) Successful in 1m55s
deploy to production / deploy-frontend (push) Successful in 26s
deploy to production / deploy-backend (push) Failing after 2m51s
Build and test FrontEnd / Build-frontend (push) Successful in 24s
Reviewed-on: #146
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
2024-03-18 21:06:02 +01:00
73f3df0bc6 Clean le projet
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m46s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-18 20:54:16 +01:00
90a7b7b70e Merge pull request 'Link back and front all get' (#115) from wal/front/listingUsers into master
Some checks failed
Build and test backend / Build-backend (push) Successful in 1m53s
deploy to production / deploy-frontend (push) Successful in 25s
deploy to production / deploy-backend (push) Failing after 2m48s
Build and test FrontEnd / Build-frontend (push) Successful in 24s
Reviewed-on: #115
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
Reviewed-by: LeoMoulin <leomoulin125@gmail.com>
2024-03-18 20:20:35 +01:00
4f002a29e1 Merge pull request 'added delete self' (#145) from Max/Backend/UserDelete into master
Some checks failed
deploy to production / deploy-frontend (push) Waiting to run
deploy to production / deploy-backend (push) Waiting to run
Build and test FrontEnd / Build-frontend (push) Waiting to run
Build and test backend / Build-backend (push) Has been cancelled
Reviewed-on: #145
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: LeoMoulin <leomoulin125@gmail.com>
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
2024-03-18 20:19:41 +01:00
66d090d045 Merge pull request 'Leo/Backend/UnitTest' (#138) from Leo/Backend/UnitTest into master
Some checks failed
Build and test backend / Build-backend (push) Successful in 1m56s
deploy to production / deploy-frontend (push) Successful in 26s
deploy to production / deploy-backend (push) Failing after 2m53s
Build and test FrontEnd / Build-frontend (push) Successful in 25s
Reviewed-on: #138
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
Reviewed-by: Maxime <231026@umons.ac.be>
2024-03-18 19:21:54 +01:00
4715441afd FINAL COMMIT
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m2s
Build and test backend / Test-backend (pull_request) Successful in 1m58s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 18:47:00 +01:00
77ac771b8f Merge remote-tracking branch 'origin/Max/Backend/UserDelete' into wal/front/listingUsers
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 1m31s
Build and test backend / Test-backend (pull_request) Failing after 1m31s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 17:36:07 +01:00
3762750968 Tempo 2024-03-18 17:34:35 +01:00
a276c24f8f added delete self
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m2s
Build and test backend / Test-backend (pull_request) Successful in 2m0s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-18 17:30:04 +01:00
25c5c1b018 Nearly finish
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 1m31s
Build and test backend / Test-backend (pull_request) Failing after 1m31s
Build and test FrontEnd / Build-frontend (pull_request) Failing after 20s
2024-03-18 17:28:14 +01:00
c7f37b0854 Fix le truc de max et ajoute le test du delete
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m44s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-18 15:55:38 +01:00
c35f675a11 Manage course + delete course END
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m3s
Build and test backend / Test-backend (pull_request) Successful in 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 15:47:04 +01:00
a9e5e45872 Merge branch 'master' into wal/front/listingUsers
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m5s
Build and test backend / Test-backend (pull_request) Successful in 2m1s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 14:57:49 +01:00
73d50f3f50 Merge remote-tracking branch 'refs/remotes/origin/wal/front/listingUsers' into wal/front/listingUsers
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m59s
Build and test backend / Test-backend (pull_request) Successful in 2m2s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 26s
2024-03-18 14:52:29 +01:00
0871d2971d manage Course finished 2024-03-18 14:51:27 +01:00
9744bd973f Resolve conflicts and adapt tests
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m49s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-18 14:29:30 +01:00
ecaa0af24a Merge remote-tracking branch 'origin/master' into Leo/Backend/UnitTest
# Conflicts:
#	backend/src/main/java/ovh/herisson/Clyde/Services/AuthenticatorService.java
#	backend/src/main/java/ovh/herisson/Clyde/Services/UserService.java
2024-03-18 13:55:45 +01:00
a762b6875d removing cdn
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 1m34s
Build and test backend / Test-backend (pull_request) Failing after 1m32s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 13:54:31 +01:00
4e6c4ecf38 Merge pull request 'added GET /user/{id}' (#143) from Max/Backend/GetUserById into master
All checks were successful
Build and test backend / Build-backend (push) Successful in 2m13s
deploy to production / deploy-frontend (push) Successful in 24s
Build and test FrontEnd / Build-frontend (push) Successful in 25s
Build and test backend / Test-backend (push) Successful in 1m21s
deploy to production / deploy-backend (push) Successful in 2m22s
Reviewed-on: #143
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
Reviewed-by: LeoMoulin <leomoulin125@gmail.com>
Reviewed-by: Wal <karpinskiwal@gmail.com>
2024-03-18 13:48:07 +01:00
ec3c912847 Merge remote-tracking branch 'origin/master' into Max/Backend/GetUserById
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m0s
Build and test backend / Test-backend (pull_request) Successful in 2m1s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-18 13:45:47 +01:00
5636d96478 Merge pull request 'Max/Backend/UserDelete' (#144) from Max/Backend/UserDelete into master
Some checks failed
Build and test FrontEnd / Build-frontend (push) Waiting to run
deploy to production / deploy-frontend (push) Waiting to run
deploy to production / deploy-backend (push) Waiting to run
Build and test backend / Test-backend (push) Has been cancelled
Build and test backend / Build-backend (push) Successful in 2m12s
Reviewed-on: #144
Reviewed-by: LeoMoulin <leomoulin125@gmail.com>
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
2024-03-18 13:45:04 +01:00
d40ceff2ba disable test on ci, problem for later
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m42s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-18 12:41:18 +01:00
fd357ba938 GET /curriculum returns user's curriculum
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m2s
Build and test backend / Test-backend (pull_request) Successful in 1m58s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-18 12:15:13 +01:00
92079c5a47 Merge remote-tracking branch 'origin/Max/Backend/UserDelete' into wal/front/listingUsers
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 1m32s
Build and test backend / Test-backend (pull_request) Failing after 1m33s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 11:59:44 +01:00
753af3874e Login and register ok and starting requests 2024-03-18 11:55:51 +01:00
e03a01ec89 oups forgot somthing 2024-03-18 11:53:33 +01:00
fd18df7c3a added a InscriptionRequest to POST /mock
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m2s
Build and test backend / Test-backend (pull_request) Successful in 1m59s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 11:33:50 +01:00
93c161be4c added every delete endpoint required
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m16s
Build and test backend / Test-backend (pull_request) Successful in 1m59s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-18 11:22:21 +01:00
853a3a42d2 Small improvement
Some checks failed
Build and test backend / Build-backend (pull_request) Successful in 1m45s
Build and test backend / Test-backend (pull_request) Failing after 3m25s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-18 02:14:36 +01:00
a80fb2b297 added DELETE user and prepared tables for cascade deletion
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m2s
Build and test backend / Test-backend (pull_request) Successful in 1m58s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-18 00:14:48 +01:00
f484fb095e added protection for inscription requests 2024-03-18 00:14:26 +01:00
611e7167f9 CI -> build no test and trying to fix test
Some checks failed
Build and test backend / Build-backend (pull_request) Successful in 1m50s
Build and test backend / Test-backend (pull_request) Failing after 2m38s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 26s
2024-03-17 22:40:22 +01:00
ee37dc79a7 Fixing the CI
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 2m45s
Build and test backend / Test-backend (pull_request) Failing after 2m37s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
Moving the dev test and build to port 5442 from 5432 to avoid
conflicting with the running postgresql
2024-03-17 22:02:12 +01:00
2fb6aef67c added GET /user/{id} 2024-03-17 22:01:48 +01:00
f2b80ba89f Resolve conflicts and resolve condition bug in isNotSecretaryOrAdmin
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 2m27s
Build and test backend / Test-backend (pull_request) Failing after 2m25s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-17 19:17:38 +01:00
114116b97c Merge remote-tracking branch 'origin/master' into Leo/Backend/UnitTest
# Conflicts:
#	backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java
2024-03-17 19:14:25 +01:00
924faca13f Add testing for file uploading and correct minors bugs in service
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 3m14s
Build and test backend / Test-backend (pull_request) Failing after 2m30s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 26s
2024-03-17 19:06:27 +01:00
571d27c230 Add test for user patch
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 2m24s
Build and test backend / Test-backend (pull_request) Failing after 2m22s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-17 15:53:50 +01:00
37a9eb46ae Add tests for UserController get and post
Some checks failed
Build and test backend / Build-backend (pull_request) Failing after 2m22s
Build and test backend / Test-backend (pull_request) Failing after 2m24s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-17 15:42:43 +01:00
bfc4f6567b Merge remote-tracking branch 'origin/Leo/Backend/UnitTest' into Leo/Backend/UnitTest
# Conflicts:
#	backend/src/main/java/ovh/herisson/Clyde/EndPoints/UserController.java
2024-03-17 15:40:45 +01:00
d423a57fa0 Add tests for UserController get and post 2024-03-17 15:40:14 +01:00
008af10d0e Merge branch 'master' into Leo/Backend/UnitTest
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m17s
Build and test backend / Test-backend (pull_request) Successful in 2m17s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-17 10:36:00 +01:00
189e664f37 Add tests for Storage system
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m53s
Build and test backend / Test-backend (pull_request) Successful in 2m17s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-15 18:49:41 +01:00
c8b7930a8e Setup unit tests and implements test for the token limit and trivial tests for userRepository 2024-03-15 11:20:23 +01:00
64 changed files with 895 additions and 255 deletions

View File

@ -17,15 +17,16 @@ jobs:
distribution: 'temurin' distribution: 'temurin'
- uses: gradle/gradle-build-action@v3 - uses: gradle/gradle-build-action@v3
- name: building - name: building
run: ./gradlew backend:build run: ./gradlew backend:build -x test
Test-backend: # Test-backend:
runs-on: ubuntu-latest # runs-on: ubuntu-latest
steps: # steps:
- uses: actions/checkout@v4 # - uses: actions/checkout@v4
- uses: actions/setup-java@v3 # - uses: actions/setup-java@v3
with: # with:
java-version: '21' # java-version: '21'
distribution: 'temurin' # distribution: 'temurin'
- uses: gradle/gradle-build-action@v3 # - run: curl -fsSL https://get.docker.com | sh
- name: building # - uses: gradle/gradle-build-action@v3
run: ./gradlew backend:test # - name: testing
# run: ./gradlew backend:test

View File

@ -45,7 +45,7 @@ jobs:
distribution: 'temurin' distribution: 'temurin'
- uses: gradle/gradle-build-action@v3 - uses: gradle/gradle-build-action@v3
- name: building - name: building
run: ./gradlew backend:build run: ./gradlew backend:build -x test
- name: pushing to the server - name: pushing to the server
run: | run: |
echo "${{ secrets.SSH_KEY }}" > key echo "${{ secrets.SSH_KEY }}" > key

2
backend/.gitignore vendored
View File

@ -35,3 +35,5 @@ out/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
/cdn

View File

@ -1,5 +1,6 @@
FROM eclipse-temurin:21-jdk-alpine FROM eclipse-temurin:21-jdk-alpine
VOLUME /tmp VOLUME /tmp
VOLUME /cdn
ENV SPRING_PROFILES_ACTIVE=prod ENV SPRING_PROFILES_ACTIVE=prod
COPY build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar COPY build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"] ENTRYPOINT ["java", "-jar", "/app.jar"]

View File

@ -31,8 +31,11 @@ dependencies {
testImplementation("org.springframework.boot:spring-boot-testcontainers") testImplementation("org.springframework.boot:spring-boot-testcontainers")
testImplementation("org.testcontainers:junit-jupiter") testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql") testImplementation("org.testcontainers:postgresql")
testImplementation("io.rest-assured:rest-assured")
testImplementation("org.hamcrest:hamcrest")
} }
tasks.register("run") { tasks.register("run") {
dependsOn(tasks.bootRun) dependsOn(tasks.bootRun)
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@ -6,4 +6,4 @@ services:
- 'POSTGRES_USER=devel' - 'POSTGRES_USER=devel'
- 'POSTGRES_PASSWORD=devel' - 'POSTGRES_PASSWORD=devel'
ports: ports:
- '5432:5432' - '5442:5432'

View File

@ -11,7 +11,6 @@ import ovh.herisson.Clyde.Services.TeacherCourseService;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -120,4 +119,20 @@ public class CourseController {
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@DeleteMapping("course/{id}")
public ResponseEntity<String> deleteUser(@RequestHeader("Authorization") String token, @PathVariable Long id){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary}, token))
return new UnauthorizedResponse<>(null);
Course toDelete = courseServ.findById(id);
if (toDelete == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
courseServ.delete(courseServ.findById(id));
return new ResponseEntity<>(HttpStatus.OK);
}
} }

View File

@ -5,9 +5,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService; import ovh.herisson.Clyde.Services.*;
import ovh.herisson.Clyde.Services.CurriculumCourseService;
import ovh.herisson.Clyde.Services.CurriculumService;
import ovh.herisson.Clyde.Tables.Curriculum; import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
@ -21,11 +19,13 @@ public class CurriculumController {
private final CurriculumService curriculumServ; private final CurriculumService curriculumServ;
private final AuthenticatorService authServ; private final AuthenticatorService authServ;
private final UserCurriculumService userCurriculumServ;
private final CurriculumCourseService curriculumCourseServ; private final CurriculumCourseService curriculumCourseServ;
public CurriculumController(CurriculumService curriculumServ, AuthenticatorService authServ, CurriculumCourseService curriculumCourseServ){ public CurriculumController(CurriculumService curriculumServ, AuthenticatorService authServ, UserCurriculumService userCurriculumServ, CurriculumCourseService curriculumCourseServ){
this.curriculumServ = curriculumServ; this.curriculumServ = curriculumServ;
this.authServ = authServ; this.authServ = authServ;
this.userCurriculumServ = userCurriculumServ;
this.curriculumCourseServ = curriculumCourseServ; this.curriculumCourseServ = curriculumCourseServ;
} }
@ -39,6 +39,19 @@ public class CurriculumController {
return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(foundCurriculum), HttpStatus.OK); return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(foundCurriculum), HttpStatus.OK);
} }
@GetMapping("/curriculum")
public ResponseEntity<Map<String ,Object>> findSelfCurriculum(@RequestHeader("Authorization") String token){
if (authServ.getUserFromToken(token) == null)
return new UnauthorizedResponse<>(null);
Curriculum curriculum = userCurriculumServ.findByUser(authServ.getUserFromToken(token));
if (curriculum == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(curriculum),HttpStatus.OK);
}
@GetMapping("/curriculums") @GetMapping("/curriculums")
public ResponseEntity<Iterable<Map<String, Object>>> findAllIndDepth(){ public ResponseEntity<Iterable<Map<String, Object>>> findAllIndDepth(){
return new ResponseEntity<>(curriculumCourseServ.getAllDepthCurriculum(),HttpStatus.OK); return new ResponseEntity<>(curriculumCourseServ.getAllDepthCurriculum(),HttpStatus.OK);
@ -67,4 +80,18 @@ public class CurriculumController {
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@DeleteMapping("/curriculum/{id}")
public ResponseEntity<String > deleteCurriculum(@RequestHeader("Authorization") String token, @PathVariable Long id){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary}, token))
return new UnauthorizedResponse<>(null);
Curriculum toDelete = curriculumServ.findById(id);
if (toDelete == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
curriculumServ.delete(toDelete);
return new ResponseEntity<>(HttpStatus.OK);
}
} }

View File

@ -6,11 +6,10 @@ import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService; import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.InscriptionService; import ovh.herisson.Clyde.Services.InscriptionService;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Tables.InscriptionRequest; import ovh.herisson.Clyde.Tables.InscriptionRequest;
import ovh.herisson.Clyde.Tables.RequestState; import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
@RestController @RestController
@ -34,13 +33,8 @@ public class InscriptionController {
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
Iterable<InscriptionRequest> inscriptionRequests = inscriptionServ.getAll(); Iterable<InscriptionRequest> inscriptionRequests = inscriptionServ.getAll();
ArrayList<Map<String,Object>> toReturn = new ArrayList<>();
for (InscriptionRequest i:inscriptionRequests){ return new ResponseEntity<>(ProtectionService.requestsWithoutPasswords(inscriptionRequests), HttpStatus.OK);
toReturn.add(requestWithoutPassword(i));
}
return new ResponseEntity<>(toReturn, HttpStatus.OK);
} }
@ -55,38 +49,34 @@ public class InscriptionController {
if (foundInscriptionRequest == null) if (foundInscriptionRequest == null)
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(requestWithoutPassword(foundInscriptionRequest), HttpStatus.OK); return new ResponseEntity<>(ProtectionService.requestWithoutPassword(foundInscriptionRequest), HttpStatus.OK);
} }
@PatchMapping("/request/register/{id}") @PatchMapping("/request/register/{id}")
public ResponseEntity<InscriptionRequest> changeRequestState(@PathVariable long id, public ResponseEntity<InscriptionRequest> changeRequestState(@PathVariable long id,
@RequestHeader("Authorization") String token, @RequestHeader("Authorization") String token,
@RequestBody RequestState requestState) @RequestBody RequestState state)
{ {
if (authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin},token)) if (authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin},token))
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
if (!inscriptionServ.modifyState(id, requestState)) if (!inscriptionServ.modifyState(id, state))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@DeleteMapping("/request/register/{id}")
public ResponseEntity<String > deleteRequest(@RequestHeader("Authorization") String token, @PathVariable Long id){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.InscriptionService}, token))
return new UnauthorizedResponse<>(null);
private Map<String, Object> requestWithoutPassword(InscriptionRequest inscriptionRequest) { InscriptionRequest toDelete = inscriptionServ.getById(id);
Map<String, Object> toReturn = new HashMap<>();
toReturn.put("id", inscriptionRequest.getId()); if (toDelete == null)
toReturn.put("lastName", inscriptionRequest.getLastName()); return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
toReturn.put("firstName", inscriptionRequest.getFirstName());
toReturn.put("address", inscriptionRequest.getAddress());
toReturn.put("email",inscriptionRequest.getEmail());
toReturn.put("birthDate", inscriptionRequest.getBirthDate());
toReturn.put("country", inscriptionRequest.getCountry());
toReturn.put("curriculum", inscriptionRequest.getCurriculumId());
toReturn.put("state", inscriptionRequest.getState());
toReturn.put("profilePictureUrl", inscriptionRequest.getProfilePicture());
return toReturn; inscriptionServ.delete(toDelete);
return new ResponseEntity<>(HttpStatus.OK);
} }
} }

View File

@ -7,8 +7,10 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService; import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Tables.InscriptionRequest; import ovh.herisson.Clyde.Tables.InscriptionRequest;
import java.util.Date; import java.util.Date;
import java.util.Map;
@RestController @RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true") @CrossOrigin(originPatterns = "*", allowCredentials = "true")
@ -45,7 +47,10 @@ public class LoginController {
} }
@PostMapping("/register") @PostMapping("/register")
public ResponseEntity<InscriptionRequest> register(@RequestBody InscriptionRequest inscriptionRequest){ public ResponseEntity<Map<String,Object>> register(@RequestBody InscriptionRequest inscriptionRequest){
return new ResponseEntity<>(authServ.register(inscriptionRequest), HttpStatus.CREATED);
InscriptionRequest returnedInscriptionRequest = authServ.register(inscriptionRequest);
return new ResponseEntity<>(ProtectionService.requestWithoutPassword(returnedInscriptionRequest), HttpStatus.CREATED);
} }
} }

View File

@ -22,16 +22,19 @@ public class MockController {
public final CurriculumCourseService CurriculumCourseService; public final CurriculumCourseService CurriculumCourseService;
public final CurriculumService curriculumService; public final CurriculumService curriculumService;
public final CourseService courseService; public final CourseService courseService;
public final InscriptionService inscriptionService;
ArrayList<User> mockUsers; ArrayList<User> mockUsers;
public MockController(UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService){ public MockController(UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, InscriptionService inscriptionService){
this.tokenRepo = tokenRepo; this.tokenRepo = tokenRepo;
this.userRepo = userRepo; this.userRepo = userRepo;
this.tokenService = tokenService; this.tokenService = tokenService;
this.CurriculumCourseService = CurriculumCourseService; this.CurriculumCourseService = CurriculumCourseService;
this.curriculumService = curriculumService; this.curriculumService = curriculumService;
this.courseService = courseService; this.courseService = courseService;
this.inscriptionService = inscriptionService;
} }
/** Saves an example of each user type by : /** Saves an example of each user type by :
@ -46,12 +49,13 @@ public class MockController {
// user part // user part
User herobrine = new User("brine","hero","admin@admin.com","in your WalLs","ShadowsLand",new Date(0), null,Role.Admin,passwordEncoder.encode("admin")); User herobrine = new User("brine","hero","admin@admin.com","behind","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 joe = new User("Mama","Joe","student@student.com","roundabout","England",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.Secretary,passwordEncoder.encode("secretary")); User meh = new User("Polo","Marco","secretary@secretary.com","a Box","Monaco",new Date(0), null,Role.Secretary,passwordEncoder.encode("secretary"));
User joke = new User("CthemBalls","Lemme","teacher@teacher.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher")); User joke = new User("Gaillard","Corentin","teacher@teacher.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher"));
User jojo = new User("Bridoux","Justin","teacher2@teacher2.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher"));
User lena = new User("Louille","Lena","inscriptionService@InscriptionService.com","no","yes",new Date(0), null,Role.InscriptionService,passwordEncoder.encode("inscriptionService")); User lena = new User("Louille","Lena","inscriptionService@InscriptionService.com","no","yes",new Date(0), null,Role.InscriptionService,passwordEncoder.encode("inscriptionService"));
mockUsers = new ArrayList<>(Arrays.asList(herobrine,joe,meh,joke,lena)); mockUsers = new ArrayList<>(Arrays.asList(herobrine,joe,meh,joke,lena,jojo));
userRepo.saveAll(mockUsers); userRepo.saveAll(mockUsers);
@ -68,7 +72,7 @@ public class MockController {
Course progra1 = new Course(5,"Programmation et algorithmique 1",joke); Course progra1 = new Course(5,"Programmation et algorithmique 1",joke);
Course chemistry1 = new Course(12, "Thermochimie",joke); Course chemistry1 = new Course(12, "Thermochimie",joke);
Course psycho1 = new Course(21, "rien faire t'as cru c'est psycho",joke); Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells",joke);
Course commun = new Course(2, "cours commun",joke); Course commun = new Course(2, "cours commun",joke);
courseService.save(progra1); courseService.save(progra1);
@ -87,6 +91,11 @@ public class MockController {
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,commun)); CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,commun));
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,chemistry1)); CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,chemistry1));
InscriptionRequest inscriptionRequest = new InscriptionRequest("helen","prenom","non","helen@gmail.com","america",new Date(),(long) 1,RequestState.Pending,"yes.png","password");
inscriptionService.save(inscriptionRequest);
} }
} }

View File

@ -11,7 +11,6 @@ import ovh.herisson.Clyde.Tables.StorageFile;
@RestController @RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true") @CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class StorageController { public class StorageController {
private final StorageService storageServ; private final StorageService storageServ;
public StorageController(StorageService storageServ){ public StorageController(StorageService storageServ){

View File

@ -121,4 +121,19 @@ public class UserController {
return new ResponseEntity<>(ProtectionService.usersWithoutPasswords(students), HttpStatus.OK); return new ResponseEntity<>(ProtectionService.usersWithoutPasswords(students), HttpStatus.OK);
} }
@DeleteMapping("/user/{id}")
public ResponseEntity<String> deleteStudent(@RequestHeader("Authorization") String token, @PathVariable Long id){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token) && !id.equals(authServ.getUserFromToken(token).getRegNo()))
return new UnauthorizedResponse<>(null);
User toDelete = userService.getUserById(id);
if (toDelete == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
userService.delete(toDelete);
return new ResponseEntity<>(HttpStatus.OK);
}
} }

View File

@ -17,7 +17,7 @@ public class JdbcConfig {
public DataSource psqlSource(){ public DataSource psqlSource(){
DriverManagerDataSource source = new DriverManagerDataSource(); DriverManagerDataSource source = new DriverManagerDataSource();
source.setDriverClassName("org.postgresql.Driver"); source.setDriverClassName("org.postgresql.Driver");
source.setUrl("jdbc:postgresql://localhost:5432/clyde"); source.setUrl("jdbc:postgresql://localhost:5442/clyde");
source.setUsername("devel"); source.setUsername("devel");
source.setPassword("devel"); source.setPassword("devel");

View File

@ -1,9 +1,14 @@
package ovh.herisson.Clyde.Repositories; package ovh.herisson.Clyde.Repositories;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.StorageFile; import ovh.herisson.Clyde.Tables.StorageFile;
import java.util.ArrayList;
public interface FileRepository extends CrudRepository<StorageFile,Long> { public interface FileRepository extends CrudRepository<StorageFile,Long> {
public StorageFile getStorageFileByName(String name);
} }

View File

@ -1,7 +1,13 @@
package ovh.herisson.Clyde.Repositories; package ovh.herisson.Clyde.Repositories;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.UserCurriculum; import ovh.herisson.Clyde.Tables.UserCurriculum;
public interface UserCurriculumRepository extends CrudRepository<UserCurriculum, Long> { public interface UserCurriculumRepository extends CrudRepository<UserCurriculum, Long> {
@Query("select uc.curriculum from UserCurriculum uc where uc.user = ?1")
Curriculum findByUser(User student);
} }

View File

@ -32,6 +32,7 @@ public class AuthenticatorService {
} }
public InscriptionRequest register(InscriptionRequest inscriptionRequest) { public InscriptionRequest register(InscriptionRequest inscriptionRequest) {
inscriptionRequest.setState(RequestState.Pending);
return inscriptionService.save(inscriptionRequest); return inscriptionService.save(inscriptionRequest);
} }

View File

@ -77,4 +77,7 @@ public class CourseService {
return true; return true;
} }
public void delete(Course course) {
courseRepo.delete(course);
}
} }

View File

@ -19,4 +19,7 @@ public class CurriculumService {
return curriculumRepo.findById(id); return curriculumRepo.findById(id);
} }
public void delete(Curriculum curriculum) {
curriculumRepo.delete(curriculum);
}
} }

View File

@ -87,4 +87,8 @@ public class InscriptionService {
save(inscrRequest); save(inscrRequest);
return true; return true;
} }
public void delete(InscriptionRequest toDelete) {
inscriptionRepo.delete(toDelete);
}
} }

View File

@ -1,10 +1,12 @@
package ovh.herisson.Clyde.Services; package ovh.herisson.Clyde.Services;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.InscriptionRequest;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
public class ProtectionService { public class ProtectionService {
@ -13,6 +15,10 @@ public class ProtectionService {
* @return all the user data without the password * @return all the user data without the password
*/ */
public static HashMap<String,Object> userWithoutPassword(User user){ public static HashMap<String,Object> userWithoutPassword(User user){
if (user ==null)
return null;
HashMap<String,Object> toReturn = new HashMap<>(); HashMap<String,Object> toReturn = new HashMap<>();
toReturn.put("regNo",user.getRegNo()); toReturn.put("regNo",user.getRegNo());
@ -40,6 +46,9 @@ public class ProtectionService {
public static HashMap<String,Object> courseWithoutPassword(Course course){ public static HashMap<String,Object> courseWithoutPassword(Course course){
if (course == null)
return null;
HashMap<String ,Object> toReturn = new HashMap<>(); HashMap<String ,Object> toReturn = new HashMap<>();
toReturn.put("courseId",course.getCourseID()); toReturn.put("courseId",course.getCourseID());
@ -61,5 +70,36 @@ public class ProtectionService {
} }
public static Map<String, Object> requestWithoutPassword(InscriptionRequest inscriptionRequest) {
if (inscriptionRequest == null)
return null;
Map<String, Object> toReturn = new HashMap<>();
toReturn.put("id", inscriptionRequest.getId());
toReturn.put("lastName", inscriptionRequest.getLastName());
toReturn.put("firstName", inscriptionRequest.getFirstName());
toReturn.put("address", inscriptionRequest.getAddress());
toReturn.put("email",inscriptionRequest.getEmail());
toReturn.put("birthDate", inscriptionRequest.getBirthDate());
toReturn.put("country", inscriptionRequest.getCountry());
toReturn.put("curriculum", inscriptionRequest.getCurriculumId());
toReturn.put("state", inscriptionRequest.getState());
toReturn.put("profilePictureUrl", inscriptionRequest.getProfilePicture());
return toReturn;
}
public static Iterable<Map<String ,Object>> requestsWithoutPasswords(Iterable<InscriptionRequest> inscriptionRequests){
ArrayList<Map<String,Object>> toReturn = new ArrayList<>();
for (InscriptionRequest i:inscriptionRequests){
toReturn.add(requestWithoutPassword(i));
}
return toReturn;
}
} }

View File

@ -15,8 +15,6 @@ import java.util.UUID;
@Service @Service
public class StorageService { public class StorageService {
private final Path rootLocation = Paths.get("cdn/"); private final Path rootLocation = Paths.get("cdn/");
private final FileRepository fileRepo; private final FileRepository fileRepo;
@ -58,7 +56,7 @@ public class StorageService {
String url = this.rootLocation.resolve(Paths.get(Objects.requireNonNull(stringUuid))) String url = this.rootLocation.resolve(Paths.get(Objects.requireNonNull(stringUuid)))
.normalize().toString(); .normalize().toString();
return fileRepo.save(new StorageFile(file.getName(),url, fileType)); return fileRepo.save(new StorageFile(file.getOriginalFilename(),url, fileType));
} }
public void delete(StorageFile file) throws SecurityException { public void delete(StorageFile file) throws SecurityException {

View File

@ -0,0 +1,20 @@
package ovh.herisson.Clyde.Services;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.UserCurriculumRepository;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.User;
@Service
public class UserCurriculumService {
private final UserCurriculumRepository userCurriculumRepository;
public UserCurriculumService(UserCurriculumRepository userCurriculumRepository) {
this.userCurriculumRepository = userCurriculumRepository;
}
public Curriculum findByUser(User student){
return userCurriculumRepository.findByUser(student);
}
}

View File

@ -127,4 +127,8 @@ public class UserService {
public User getUserById(long id) { public User getUserById(long id) {
return userRepo.findById(id); return userRepo.findById(id);
} }
public void delete(User user) {
userRepo.delete(user);
}
} }

View File

@ -1,6 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
@Entity @Entity
public class Course { public class Course {
@ -11,6 +13,7 @@ public class Course {
private String title; private String title;
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.SET_NULL)
@JoinColumn(name = "Users") @JoinColumn(name = "Users")
private User owner; private User owner;

View File

@ -1,6 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
@Entity @Entity
public class CurriculumCourse { public class CurriculumCourse {
@ -10,9 +12,11 @@ public class CurriculumCourse {
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "Curriculum") @JoinColumn(name = "Curriculum")
@OnDelete(action = OnDeleteAction.CASCADE)
private Curriculum curriculum; private Curriculum curriculum;
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "Course") @JoinColumn(name = "Course")
private Course course; private Course course;

View File

@ -1,6 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
@Entity @Entity
public class ReInscriptionRequest { public class ReInscriptionRequest {
@ -10,10 +12,12 @@ public class ReInscriptionRequest {
@ManyToOne @ManyToOne
@JoinColumn(name = "Users") @JoinColumn(name = "Users")
@OnDelete(action = OnDeleteAction.CASCADE)
private User user; private User user;
@ManyToOne @ManyToOne
@JoinColumn(name = "Curriculum") @JoinColumn(name = "Curriculum")
@OnDelete(action = OnDeleteAction.CASCADE)
private Curriculum newCurriculum; private Curriculum newCurriculum;
private RequestState state; private RequestState state;

View File

@ -1,6 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
@Entity @Entity
public class TeacherCourse { public class TeacherCourse {
@ -9,11 +11,13 @@ public class TeacherCourse {
private int id; private int id;
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "Users") @JoinColumn(name = "Users")
private User user; private User user;
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "Course") @JoinColumn(name = "Course")
private Course course; private Course course;

View File

@ -1,6 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import java.util.Date; import java.util.Date;
@ -11,6 +13,7 @@ public class Token {
private int id; private int id;
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name ="Users") @JoinColumn(name ="Users")
private User user; private User user;
private String token; private String token;

View File

@ -1,6 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
@Entity @Entity
public class UserCurriculum { public class UserCurriculum {
@ -10,11 +12,13 @@ public class UserCurriculum {
//Un étudiant peut avoir plusieurs curriculums //Un étudiant peut avoir plusieurs curriculums
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "Users") @JoinColumn(name = "Users")
private User user; private User user;
@OneToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "Curriculum") @JoinColumn(name = "Curriculum")
@OnDelete(action = OnDeleteAction.CASCADE)
private Curriculum curriculum; private Curriculum curriculum;
public UserCurriculum(User user, Curriculum curriculum){ public UserCurriculum(User user, Curriculum curriculum){

View File

@ -1,2 +1,3 @@
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

View File

@ -8,6 +8,7 @@ class ClydeApplicationTests {
@Test @Test
void contextLoads() { void contextLoads() {
} }
} }

View File

@ -0,0 +1,105 @@
package ovh.herisson.Clyde.Endpoints;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.PortBinding;
import com.github.dockerjava.api.model.Ports;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.Assert;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import ovh.herisson.Clyde.ClydeApplication;
import ovh.herisson.Clyde.EndPoints.StorageController;
import ovh.herisson.Clyde.Repositories.FileRepository;
import ovh.herisson.Clyde.Services.StorageService;
import ovh.herisson.Clyde.Tables.FileType;
import ovh.herisson.Clyde.Tables.StorageFile;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import static io.restassured.RestAssured.with;
@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles(value ="dev")
public class StorageControllerTest {
@LocalServerPort
private Integer port;
@Autowired
private ClydeApplication controller;
@Autowired
private StorageController storageController;
@Autowired
private StorageService storageService;
@Autowired
private FileRepository fileRepository;
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:alpine")
.withDatabaseName("clyde")
.withUsername("devel")
.withPassword("devel")
.withCreateContainerCmdModifier(cmd -> cmd.withHostConfig(new HostConfig().withPortBindings(new PortBinding(Ports.Binding.bindPort(5442), new ExposedPort(5432)))));
@BeforeAll
static void beforeAll(){
postgres.start();
}
@AfterAll
static void afterAll(){
postgres.stop();
}
@BeforeEach
void setup(){
RestAssured.baseURI = "http://localhost:" + port;
}
@AfterEach
void afterEach(){
fileRepository.deleteAll();
}
@Test
public void uploadFileTest() throws IOException {
File mmf = new File("test.txt");
mmf.createNewFile();
FileWriter fw = new FileWriter(mmf);
fw.write("Ceci est un test");
fw.close();
with().multiPart("file", mmf).pathParam("fileType", FileType.ProfilePicture).when().request("POST", "/upload/{fileType}").then().statusCode(200);
StorageFile sf = fileRepository.getStorageFileByName("test.txt");
//On vérifie que le fichier a bien été stocké dans la db
Assert.assertFalse(sf == null);
//On vérifie que le fichier a bel et bien été stocké dans le dossier cdn
File extFile = new File(sf.getUrl());
Assert.assertTrue(extFile.exists());
Assert.assertEquals("cdn", extFile.getParent());
//On delete tranquillement les fichiers (la méthode delete a déja été testée dans StorageServiceTest)
storageService.delete(sf);
mmf.delete();
}
}

View File

@ -0,0 +1,149 @@
package ovh.herisson.Clyde.Endpoints;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.PortBinding;
import com.github.dockerjava.api.model.Ports;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.Assert;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import ovh.herisson.Clyde.ClydeApplication;
import ovh.herisson.Clyde.Repositories.TokenRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
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.Date;
import java.util.HashMap;
import java.util.Map;
import static io.restassured.RestAssured.with;
import static org.hamcrest.Matchers.equalTo;
@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles(value = "dev")
public class UserControllerTest {
@LocalServerPort
private Integer port;
@Autowired
private ClydeApplication controller;
@Autowired
private TokenService tokenService;
@Autowired
private UserRepository userRepository;
@Autowired
private TokenRepository tokenRepository;
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:alpine")
.withDatabaseName("clyde")
.withUsername("devel")
.withPassword("devel")
.withCreateContainerCmdModifier(cmd -> cmd.withHostConfig(new HostConfig().withPortBindings(new PortBinding(Ports.Binding.bindPort(5442), new ExposedPort(5432)))));
@BeforeAll
static void beforeAll(){
postgres.start();
}
@AfterAll
static void afterAll(){
postgres.stop();
}
@BeforeEach
void setup(){
RestAssured.baseURI = "http://localhost:" + port;
}
@AfterEach
void aftereach(){
tokenRepository.deleteAll();
userRepository.deleteAll();
}
@Test
//Verifie qu'un user qui n'a pas les permissions admin ou secretaire ne peut pas post
public void userPostTest(){
User god = new User("god","god","admin@admin.com","everywhere","every",new Date(0), null, Role.Admin,"goddoesntneedpassword");
Token godToken = new Token(god, tokenService.generateNewToken(), new Date());
userRepository.save(god);
tokenService.saveToken(godToken);
//Can god post herobrine himself ?
User herobrine = new User("brine","hero","herobrine@student.com","in your WalLs","ShadowsLand",new Date(0), null,Role.Student,"test");
with().body(herobrine).contentType(ContentType.JSON).header("Authorization", godToken.getToken()).when().request("POST", "/user").then().statusCode(201);
userRepository.delete(herobrine);
//Can noob post herobrine without authorizations (no)
User noob = new User("boon","noob","noob@student.com","everywhere","every",new Date(0), null, Role.Student,"noob");
Token noobToken = new Token(noob, tokenService.generateNewToken(), new Date());
userRepository.save(noob);
tokenService.saveToken(noobToken);
with().body(herobrine).contentType(ContentType.JSON).header("Authorization", noobToken.getToken()).when().request("POST", "/user").then().statusCode(401);
}
@Test
public void userGetTest(){
User herobrine = new User("brine","hero","herobrine@student.com","in your WalLs","ShadowsLand",new Date(0), null,Role.Student,"test");
userRepository.save(herobrine);
Token t = new Token(herobrine, tokenService.generateNewToken(), new Date());
tokenRepository.save(t);
with().header("Authorization", t.getToken()).when().request("GET", "/user").then().assertThat().statusCode(200).body("firstName",equalTo("hero"));
}
@Test
public void userPatchTest(){
User herobrine = new User("brine","hero","herobrine@admin.com","in your WalLs","ShadowsLand",new Date(0), null,Role.Admin,"test");
userRepository.save(herobrine);
Token t = new Token(herobrine, tokenService.generateNewToken(), new Date());
tokenRepository.save(t);
Map<String, Object> data = new HashMap<String, Object>();
data.put("firstName", "test");
//Teste que le patch s'execute bien
with().body(data).contentType(ContentType.JSON).header("Authorization", t.getToken()).pathParam("id", herobrine.getRegNo()).when().request("PATCH", "/user/{id}").then().statusCode(200);
//Teste que la donnée a bien été altérée
with().header("Authorization", t.getToken()).when().request("GET", "/user").then().body("firstName",equalTo("test"));
}
@Test
public void UserDeleteTest(){
User god = new User("god","god","admin@admin.com","everywhere","every",new Date(0), null, Role.Admin,"goddoesntneedpassword");
Token godToken = new Token(god, tokenService.generateNewToken(), new Date());
userRepository.save(god);
tokenService.saveToken(godToken);
User herobrine = new User("brine","hero","herobrine@admin.com","in your WalLs","ShadowsLand",new Date(0), null,Role.Student,"test");
userRepository.save(herobrine);
with().header("Authorization", godToken.getToken()).pathParam("id", herobrine.getRegNo()).when().request("DELETE", "/user/{id}").then().statusCode(200);
Assert.assertEquals(userRepository.existsById(herobrine.getRegNo()), false);
}
}

View File

@ -0,0 +1,41 @@
package ovh.herisson.Clyde.Repositories;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.TestPropertySource;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import java.util.GregorianCalendar;
@DataJpaTest
@TestPropertySource(properties = {
"spring.test.database.replace=none",
"spring.datasource.url=jdbc:tc:postgresql:16-alpine:///db"
})
public class UserRepoTest {
@Autowired
UserRepository userRepo;
@BeforeEach
public void setup(){
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);
}
@AfterEach
public void clean(){
userRepo.deleteAll();
}
@Test
public void usertest(){
Assert.assertEquals("brine", userRepo.findById(1).getLastName());
Assert.assertTrue(new GregorianCalendar(2005, 4, 3).getTime().equals(userRepo.findById(1).getBirthDate()));
}
}

View File

@ -0,0 +1,80 @@
package ovh.herisson.Clyde.Services;
import org.junit.Assert;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.TestPropertySource;
import org.springframework.web.multipart.MultipartFile;
import org.testcontainers.shaded.com.google.common.net.MediaType;
import ovh.herisson.Clyde.Repositories.FileRepository;
import ovh.herisson.Clyde.Tables.FileType;
import ovh.herisson.Clyde.Tables.StorageFile;
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.util.ArrayList;
@DataJpaTest
@TestPropertySource(properties = {
"spring.test.database.replace=none",
"spring.datasource.url=jdbc:tc:postgresql:16-alpine:///db"
})
public class StorageServiceTest {
@Autowired
FileRepository fileRepo;
StorageService ss;
@BeforeEach
public void setup(){
if (ss == null){
ss = new StorageService(fileRepo);
}
}
@AfterEach
public void aftereach(){
fileRepo.deleteAll();
}
@Test
//Check si le fichier est bien sauvegardé dans la DB et si le fichier est bien sauvegardé au bon endroit
public void saveFile(){
//Test si le directory a bien été crée a l'init du fileService
Path rootloc = Paths.get("cdn/");
Assert.assertTrue(Files.exists(rootloc));
}
@Test
public void deleteFile() throws IOException {
File file = new File("cdn/test.txt");
file.createNewFile();
//On vérifie que le fichier a bien été crée
Assert.assertTrue(file.exists());
//StorageFile représentant le fichier
StorageFile sf = new StorageFile("testfile",file.getPath(), FileType.ProfilePicture);
fileRepo.save(sf);
//Check that the storagefile is properly saved
StorageFile resp = fileRepo.getStorageFileByName("testfile");
Assert.assertEquals(sf, resp);
ss.delete(sf);
//On vérifie que le fichier a bien été delete et que le StorageFile a été delete de la DB
Assert.assertFalse(file.exists());
resp = fileRepo.getStorageFileByName("testfile");
Assert.assertEquals(null, resp);
}
}

View File

@ -0,0 +1,93 @@
package ovh.herisson.Clyde.Services;
import org.junit.Assert;
import org.junit.Before;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.TestPropertySource;
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 java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import static org.junit.jupiter.api.Assertions.*;
@DataJpaTest
@TestPropertySource(properties = {
"spring.test.database.replace=none",
"spring.datasource.url=jdbc:tc:postgresql:16-alpine:///db"
})
class TokenServiceTest {
@Autowired
TokenRepository tokenRepository;
@Autowired
UserRepository userRepository;
@AfterEach
public void aftereach(){
tokenRepository.deleteAll();
userRepository.deleteAll();
}
@Test
void saveToken() {
User herobrine = userRepository.findById(1);
User herobrinenul = new User("brine","heronul","pasadmin@student.com","in your WalLs","ShadowsLand", new GregorianCalendar(2005, 4, 3).getTime(), null, Role.Admin,"admin");
TokenService tokenService = new TokenService(tokenRepository);
Token testToken = new Token(herobrine, tokenService.generateNewToken(), new Date());
tokenService.saveToken(testToken);
Iterable<Token> t = tokenService.getAllTokens();
Token tok = t.iterator().next();
Assert.assertEquals(herobrine, tok.getUser());
Assert.assertNotEquals(herobrinenul, tok.getUser());
}
@Test
void saveTokenLimit(){
TokenService tokenService = new TokenService(tokenRepository);
//On va stocker les token qu'on va sauvegarder au préalable dans une liste pour tester que les tokens remplacés sont bien ceux avec la date d'expi la plus jeune
//A la fin il ne devrait donc rester que les 5 derniers tokens de tokenList
ArrayList<Token> tokenList = new ArrayList<>();
GregorianCalendar gc = new GregorianCalendar();
User malveillant = new User("Cargo", "John", "CargoJ@mail.com", "secret", "secret", null, null, null, "secret");
userRepository.save(malveillant);
for (int i = 0; i < 20; i++){
gc.add(Calendar.DAY_OF_WEEK, 1);
Token t = new Token(malveillant, tokenService.generateNewToken(), gc.getTime());
tokenList.add(t);
tokenService.saveToken(t);
}
//Testons les tokens
ArrayList <Token> resp = tokenRepository.getByUserOrderByExpirationDate(malveillant);
Assert.assertTrue(resp.size() == 5);
for (int i = 1; i <= resp.size(); i++){
Assert.assertEquals(tokenList.get(tokenList.size()-i), resp.get(resp.size()-i));
}
}
}

View File

@ -0,0 +1,3 @@
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

View File

@ -12,19 +12,19 @@ window.onhashchange = function() {
prevURL = currentURL; prevURL = currentURL;
currentURL = window.location.hash; currentURL = window.location.hash;
} }
const Logged = ref(isLogged());
window.addEventListener('hashchange', () => { window.addEventListener('hashchange', () => {
if(location.hash === "#/home" && prevURL === "#/login"){ if((location.hash === "#/home" && prevURL === "#/login") || (location.hash === "#/home" && prevURL === "#/profil")){
window.location.reload(); window.location.reload();
} }
}) });
const home=ref(i18n("app.home")) const home=ref(i18n("app.home"))
const notifications=ref(i18n("app.notifications")) const notifications=ref(i18n("app.notifications"))
const settings=ref(i18n("app.settings")) const settings=ref(i18n("app.settings"))
const login=ref(i18n("app.login")) const login=ref(i18n("app.login"))
const active=ref(false) const active=ref(false)
const Logged = ref(isLogged());
const apps = ref([]) const apps = ref([])
appList().then(e => apps.value = e) appList().then(e => apps.value = e)
@ -52,7 +52,7 @@ window.addEventListener('hashchange', () => {
<a class="icon" href="#Notifications"> <a class="icon" href="#Notifications">
<div class="fa-solid fa-bell" style="margin-top: 7px; margin-bottom: 3px;"></div> <div class="fa-solid fa-bell" style="margin-top: 7px; margin-bottom: 3px;"></div>
</a></li> </a></li>
<li @click="active=!active" class="option"style="float: right;" title=settings> <li @click="active=!active" class="option"style="float: right;" title=settings>
<a class="icon" > <a class="icon" >
<div class="fa-solid fa-gear" style="margin-top: 7px; margin-bottom: 3px;"></div> <div class="fa-solid fa-gear" style="margin-top: 7px; margin-bottom: 3px;"></div>
<div v-if="active" class="dropdown"> <div v-if="active" class="dropdown">
@ -86,12 +86,10 @@ window.addEventListener('hashchange', () => {
</ul> </ul>
</div> </div>
<div class="page"> <div class="page">
<div style=" margin:50px;">
<Suspense> <Suspense>
<component :is="currentView" /> <component :is="currentView" />
</Suspense> </Suspense>
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,25 +1,31 @@
<script setup> <script setup>
import i18n from "@/i18n.js" import i18n from "@/i18n.js"
import Req from "./Request.vue" import {ref} from 'vue'
import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js' import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js'
const requests_example = await getAllRegisters(); const requests = ref(await getAllRegisters());
console.log(requests_example); console.log(requests);
async function upPage(id,review){
await validateRegister(id,review);
requests.value = await getAllRegisters();
}
</script> </script>
<template> <template>
<div v-for="item of requests_example"> <div v-for="item of requests">
<div class="bodu"> <div class="bodu" v-if="item.state === 'Pending'">
<div class="container"> <div class="container">
<div class="id"><a>{{item.id}}</a></div> <div class="id"><a>{{item.id}}</a></div>
<div class="surname"><a>{{item.lastName}}</a></div> <div class="surname"><a>{{item.lastName}}</a></div>
<div class="firstname"><a>{{item.firstName}}</a></div> <div class="firstname"><a>{{item.firstName}}</a></div>
<div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}}</button></div> <div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}}</button></div>
<div class="accept"><button @click="validateRegister(id,Accepted)" style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</button></div> <div class="accept"><button @click="upPage(item.id,'Accepted')" style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</button></div>
<div class="refuse"><button @click="validateRegister(id,Refused)" style="background-color:rgb(105,0,0);">{{i18n("request.refuse")}}</button></div> <div class="refuse"><button @click="upPage(item.id,'Refused')" style="background-color:rgb(105,0,0);">{{i18n("request.refuse")}}</button></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref } from 'vue' import {reactive, ref } from 'vue'
import i18n from '@/i18n.js' import i18n from '@/i18n.js'
import { login , register , disconnect, isLogged} from '@/rest/Users.js' import { login , register , disconnect, isLogged} from '@/rest/Users.js'
import { getAllCurriculums } from '@/rest/curriculum.js' import { getAllCurriculums } from '@/rest/curriculum.js'
@ -11,16 +11,19 @@
const loginPage= ref(true) const loginPage= ref(true)
const page = ref(0) const page = ref(0)
const outputs = reactive({
surname:null,
firstname:null,
password:null,
birthday:null,
email:null,
address:null,
country:null,
curriculum:null,
})
const submitValue= ref(i18n("login.guest.submit")) const submitValue= ref(i18n("login.guest.submit"))
const surname=ref("")
const firstname=ref("")
const password=ref("")
const passwordConfirm=ref("") const passwordConfirm=ref("")
const birthday=ref("")
const email=ref("")
const address=ref("")
const country=ref("")
let curriculum;
const imageSaved = ref(false) const imageSaved = ref(false)
const ppData = ref(false) const ppData = ref(false)
@ -32,8 +35,8 @@
window.location.href="#/home"; window.location.href="#/home";
}, "500"); }, "500");
} }
function verifyInputs(){ function verifyInputs(pass){
if(password.value==passwordConfirm.value){ if(pass==passwordConfirm.value){
page.value++; page.value++;
return toast('Password and Confirm Password are correct.', { return toast('Password and Confirm Password are correct.', {
@ -52,21 +55,21 @@
</script> </script>
<template> <template style="background-color:rgba(255,255,255,0.05); border-radius:50px" >
<div class='loginBox'> <div class='loginBox'>
<div v-if="loginPage"> <div v-if="loginPage">
<form @submit.prevent=" login(email,password);goBackHome();"class="form"> <form @submit.prevent="login(outputs.email,outputs.password);goBackHome();"class="form">
<h1 style="color:rgb(239,60,168); font-family: sans-serif;"> <h1 style="color:rgb(239,60,168); font-family: sans-serif;">
{{i18n("login.guest.signin")}} {{i18n("login.guest.signin")}}
</h1> </h1>
<div class="inputBox"> <div class="inputBox">
<p>ID / {{i18n("login.guest.email")}}</p> <p>ID / {{i18n("login.guest.email")}}</p>
<input type="text" v-model="email"> <input type="text" v-model="outputs.email">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.password")}}</p> <p>{{i18n("login.guest.password")}}</p>
<input type="password" v-model="password"> <input type="password" v-model="outputs.password">
</div> </div>
<div class="register"> <div class="register">
<a @click="loginPage=!loginPage">{{i18n("login.guest.register")}}</a> <a @click="loginPage=!loginPage">{{i18n("login.guest.register")}}</a>
@ -77,7 +80,7 @@
</form> </form>
</div> </div>
<div v-else> <div v-else>
<form class="form"> <form class="form">
<h1 style="color:rgb(239,60,168); font-family: sans-serif; text-align:center;"> <h1 style="color:rgb(239,60,168); font-family: sans-serif; text-align:center;">
{{i18n("login.guest.welcome")}} {{i18n("login.guest.welcome")}}
@ -85,19 +88,19 @@
<div v-if="page === 0"> <div v-if="page === 0">
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.surname")}}</p> <p>{{i18n("login.guest.surname")}}</p>
<input type="text" v-model="surname"> <input type="text" v-model="outputs.surname">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.firstname")}}</p> <p>{{i18n("login.guest.firstname")}}</p>
<input type="text" v-model="firstname"> <input type="text" v-model="outputs.firstname">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.birthday")}}</p> <p>{{i18n("login.guest.birthday")}}</p>
<input type="date" v-model="birthday"> <input type="date" v-model="outputs.birthday">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.password")}}</p> <p>{{i18n("login.guest.password")}}</p>
<input type="password" v-model="password"> <input type="password" v-model="outputs.password">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.confirm")}} {{i18n("login.guest.password")}}</p> <p>{{i18n("login.guest.confirm")}} {{i18n("login.guest.password")}}</p>
@ -105,7 +108,7 @@
</div> </div>
<div class="switchpage"> <div class="switchpage">
<button @click="verifyInputs();">{{i18n("login.guest.nextpage")}}</button> <button @click="verifyInputs(outputs.password);">{{i18n("login.guest.nextpage")}}</button>
</div> </div>
<div @click="(loginPage=!loginPage) && (page=0)" class="register"> <div @click="(loginPage=!loginPage) && (page=0)" class="register">
@ -115,15 +118,15 @@
<div v-else> <div v-else>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.email")}}</p> <p>{{i18n("login.guest.email")}}</p>
<input type="mail" v-model="email"> <input type="mail" v-model="outputs.email">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.address")}}</p> <p>{{i18n("login.guest.address")}}</p>
<input type="text" v-model="address"> <input type="text" v-model="outputs.address">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.country")}}</p> <p>{{i18n("login.guest.country")}}</p>
<input type="text" v-model="country"> <input type="text" v-model="outputs.country">
</div> </div>
<form novalidate enctype="multipart/form-data" class="inputBox"> <form novalidate enctype="multipart/form-data" class="inputBox">
<p>{{i18n("profile.picture").toUpperCase()}}</p> <p>{{i18n("profile.picture").toUpperCase()}}</p>
@ -131,13 +134,13 @@
</form> </form>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("Curriculum").toUpperCase()}}</p> <p>{{i18n("Curriculum").toUpperCase()}}</p>
<select v-model="curriculum"> <select v-model="outputs.curriculum">
<option v-for="item in curricula">{{item.curriculumId}}</option> <option v-for="item in curricula">{{item.curriculumId}}</option>
</select> </select>
</div> </div>
<div style="align-self:center;" class="inputBox"> <div style="align-self:center;" class="inputBox">
<button style="margin-top:25px;" @click="console.log(curriculum);register(firstname, surname, birthday, password, mail, address, country, curriculum);"> <button style="margin-top:25px;" @click="register(outputs.firstname, outputs.surname, outputs.birthday, outputs.password, outputs.email, outputs.address, outputs.country, outputs.curriculum, ppData);">
{{i18n("login.guest.submit")}} {{i18n("login.guest.submit")}}
</button> </button>
</div> </div>
@ -154,31 +157,14 @@
</template> </template>
<style scoped> <style scoped>
.Home{
position:absolute;
display: flex;
z-index: 100;
padding: 8px 16px;
color:rgb(255, 255, 255);
text-decoration: none;
}
.Home:hover{
width:40px;
background-color: black;
border-radius:6px;
color:white;
transform: translate(0px ,1px);
}
.loginBox { .loginBox {
background-color: rgb(24,24,24); background-color: rgb(24,24,24);
width: 400px; width: 100%;
display:flex; height:100%;
justify-content: center; justify-content: center;
padding: 40px; padding: 10%;
border-radius: 20px; border-radius: 5%;
box-shadow:0 5px 25px #000000; box-shadow:0 5px 25px #000000;
} }
@ -187,9 +173,8 @@
width:100%; width:100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center;
align-items:center; align-items:center;
gap: 15px; gap: 3%;
} }
@ -197,12 +182,12 @@
width:100%; width:100%;
border: none; border: none;
margin-right: 50px; margin-right: 12.5%;
padding-left: 10px; padding-left: 2.5%;
padding-top:10px; padding-top:2.5%;
padding-bottom:10px; padding-bottom:2.5%;
outline:none; outline:none;
border-radius: 4px; border-radius: 10px;
font-size:1.35em; font-size:1.35em;
} }

View File

@ -1,18 +1,15 @@
<script setup> <script setup>
import i18n from "@/i18n.js" import i18n from "@/i18n.js"
import {ref} from 'vue' import {reactive , ref} from 'vue'
import { getCourses,deleteCourse,alterCourse,createCourse } from "@/rest/courses.js" import { getCourses,deleteCourse,alterCourse,createCourse } from "@/rest/courses.js"
import {getUser, getSelf, getTeachers } from "@/rest/Users.js" import {getUser, getSelf, getTeachers } from "@/rest/Users.js"
const self = await getSelf(); const self = await getSelf();
let curriculum = await getCourses(self.role); const curriculum = ref(await getCourses(self.role));
const profList = await getTeachers(); const profList = await getTeachers();
console.log(curriculum)
console.log(profList)
const createMod = ref(false) const createMod = ref(false)
const deleteMod = ref(false) const deleteMod = ref(false)
@ -34,7 +31,7 @@
let toModify = Object.assign({},pattern); let toModify = Object.assign({},pattern);
let toAdd = Object.assign({}, pattern); let toAdd = Object.assign({}, pattern);
function addToCourse(){ async function addToCourse(){
let isnull= false; let isnull= false;
for(const [key, value] of Object.entries(toAdd)){ for(const [key, value] of Object.entries(toAdd)){
@ -45,10 +42,13 @@
} }
if (!isnull){ if (!isnull){
createCourse(toAdd.title,toAdd.credits,toAdd.owner); await createCourse(toAdd.title,toAdd.credits,toAdd.owner);
toAdd= Object.assign({},pattern); toAdd= Object.assign({},pattern);
}
} curriculum.value = await getCourses(self.role);
}}
function setModify(item){ function setModify(item){
for(const el in profList){ for(const el in profList){
@ -62,37 +62,42 @@
} }
function patchCourse(course){ async function patchCourse(course){
for (let element in toModify){ for (let element in toModify){
console.log(course.credits) console.log(toModify,1)
console.log(toModify[element],2)
if (element =="owner" && (toModify[element] != course.owner.regNo)){ if (element =="owner" && (toModify[element].regNo != course.owner.regNo)){
alterCourse(course.courseId,{owner:toModify[element].regNo}); await alterCourse(course.courseId,{owner:toModify[element].regNo});
} }
else if(element == "title" && (toModify[element] != course.title)){ else if(element == "title" && (toModify[element] != course.title)){
alterCourse(course.courseId,{title:toModify[element]}); await alterCourse(course.courseId,{title:toModify[element]});
} }
else if(element == "credits" && (toModify[element] != course.credits)){ else if(element == "credits" && (parseInt(toModify[element]) != course.credits)){
alterCourse(course.courseId,{credits:toModify[element]}); await alterCourse(course.courseId,{credits:parseInt(toModify[element])});
} }
console.log(toModify[element]) }
toModify= Object.assign({},pattern);
curriculum.value = await getCourses(self.role);
}toModify = Object.assign({},pattern);
} }
//Juste pour montrer le Delete Mode //Juste pour montrer le Delete Mode
let toRemove; let toRemove = null;
function removeCourse(course) { async function removeCourse(course) {
deleteCourse(course.id)
} await deleteCourse(course.courseId)
curriculum.value = await getCourses(self.role);
toRemove = null;
}
</script> </script>
<template> <template>
<div class="body"> <div class="body">
<div v-if="!deleteMod && !createMod && (self.role !== 'Teacher')" class="listTitle buttonGrid"> <div v-if="!deleteMod && !createMod && (self.role !== 'Teacher')" class="listTitle buttonGrid">
<button class="create" @click="createMod = true"> <button class="create" @click="editElementID= '';createMod = true;">
{{i18n("courses.createCourse")}} {{i18n("courses.createCourse")}}
</button> </button>
<button class="delete" @click="deleteMod=true" > <button class="delete" @click="deleteMod=true" >
@ -108,7 +113,7 @@
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
{{i18n("Teacher")}} : {{i18n("Teacher")}} :
<select style="max-width:200px;" class="teacher" v-model="toAdd.owner"> <select style="max-width:200px;" class="teacher" v-model="toAdd.owner">
<option v-for="item in profList">{{item}}</option> <option v-for="item in profList" :value="item">{{item.lastName}}</option>
</select> </select>
</div> </div>
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
@ -124,19 +129,11 @@
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
{{i18n("courses.toDelete")}} : {{i18n("courses.toDelete")}} :
<select style="max-width:200px;" class="teacher" v-model="toRemove"> <select style="max-width:200px;" class="teacher" v-model="toRemove">
<option v-for="item in curriculum">{{item.title}}</option> <option v-for="item in curriculum" :value='item'>{{item.title}}</option>
</select> </select>
</div> </div>
<div style="margin-bottom:20px;"> <button class="delete" @click="deleteMod=!deleteMod; removeCourse(toRemove);"> {{i18n("courses.deleteCourse")}} </button>
{{i18n("login.password")}}:
<input >
</div>
<div style="margin-bottom:20px;">
{{i18n("login.cPassword")}} :
<input>
</div>
<button class="delete" @click="deleteMod=!deleteMod;removeCourse(toRemove);"> {{i18n("courses.deleteCourse")}} </button>
<button style="float:right;" @click="deleteMod=!deleteMod"> {{i18n("courses.back")}}</button> <button style="float:right;" @click="deleteMod=!deleteMod"> {{i18n("courses.back")}}</button>
</form> </form>
</div> </div>
@ -161,7 +158,7 @@
<div class="containerElement"v-else> <div class="containerElement"v-else>
<input style="max-width:200px;" class="name" v-model="toModify.title"> <input style="max-width:200px;" class="name" v-model="toModify.title">
<select v-if="self.role === 'Secretary'" style="max-width:200px;" class="teacher" v-model="toModify.owner"> <select v-if="self.role === 'Secretary'" style="max-width:200px;" class="teacher" v-model="toModify.owner">
<option v-for="item in profList">{{item.lastName}}</option> <option v-for="(item,index) in profList" :value='item'>{{item.lastName}}</option>
</select> </select>
<div v-else class="teacher">{{item.owner.lastName}}</div> <div v-else class="teacher">{{item.owner.lastName}}</div>
<input v-if="self.role==='Secretary'"style="max-width:100px;"class="credits" v-model="toModify.credits"> <input v-if="self.role==='Secretary'"style="max-width:100px;"class="credits" v-model="toModify.credits">

View File

@ -1,22 +1,29 @@
<script setup> <script setup>
import {reactive, ref } from 'vue' import {reactive, ref } from 'vue'
import {getSelf,alterSelf} from '../rest/Users.js' import {getSelf,alterSelf,disconnect,deleteUser} from '../rest/Users.js'
import {getSelfCurriculum, getAllCurriculums} from '../rest/curriculum.js'
import {getCourses} from "../rest/courses.js"
import i18n from "@/i18n.js" import i18n from "@/i18n.js"
import { uploadProfilePicture } from '@/rest/uploads.js' import { uploadProfilePicture } from '@/rest/uploads.js'
const user = await getSelf();
console.log(user);
const user = ref(await getSelf());
const UserCurriculum = ref("");
const curricula = ref (await getAllCurriculums());
if(user.value.role === "Student"){
UserCurriculum.value = await getSelfCurriculum();
}
if(user.role === "Teacher"){
UserCurriculum.value = await getCourses("Teacher");
}
const modif = ref(false); const modif = ref(false);
const curric = ref(false); const curric = ref(false);
const unreg = ref(false);
const reg = ref(false); const reg = ref(false);
const pattern = { const pattern = {
profilPictureUrl:null, profilPictureUrl:null,
email:null, email:null,
adress:null, address:null,
password:null, password:null,
}; };
@ -35,16 +42,48 @@
inputs=Object.assign({},list); inputs=Object.assign({},list);
} }
function ChangeInfos(){ async function ChangeInfos(){
for (const [key, value] in Object.entries(toModify)){ for (let element in toModify){
if(value !== null){ if (element =="email" && (toModify[element] !== null)){
alterSelf({key:value}); await alterSelf(user.value.regNo,{email : toModify[element]});
} }
if (element =="profilPictureUrl" && (toModify[element] !== null)){
await alterSelf(user.value.regNo,{ profilPictureUrl : toModify[element]});
}
else if(element == "address" && (toModify[element] !== null)){
await alterSelf(user.value.regNo,{address : toModify[element]});
}
else if(element == "password" && (toModify[element] !== null)){
await alterSelf(user.value.regNo,{password : toModify[element]});
}
} }
toModify= Object.assign({}, pattern); toModify= Object.assign({},pattern);
user.value = await getSelf()
}
function setModify(item){
toModify.address = item.address;
toModify.profilPictureUrl = item.profilPictureUrl;
toModify.email= item.email;
toModify.password= item.password;
}
async function unRegister(){
deleteUser(user.value.regNo);
disconnect()
setTimeout(() => {
window.location.href="#/home";
}, "500");
} }
function getPP(){ function getPP(){
if(user.value.profilePictureUrl === null){
return "/Clyde.png"
}
return user.profilePictureUrl return user.profilePictureUrl
} }
</script> </script>
@ -57,7 +96,7 @@
</div> </div>
<div class="globalInfos"> <div class="globalInfos">
<div v-if="modif==false && curric==false && unreg==false && reg==false " class="infosContainer" > <div v-if="modif==false && curric==false && reg==false " class="infosContainer" >
<div> <div>
{{user.firstName}} {{user.lastName}} {{user.firstName}} {{user.lastName}}
</div> </div>
@ -65,17 +104,17 @@
E-mail: {{user.email}} E-mail: {{user.email}}
</div> </div>
<div v-if="user.role==='Student'"> <div v-if="user.role==='Student'">
{{user.option}} {{i18n(user.role.toLowerCase())}} {{user.option}} {{i18n(user.role)}}
</div> </div>
<div v-else> <div v-else>
Role: {{i18n((user.role).toLowerCase())}} Role: {{i18n((user.role))}}
</div> </div>
<div> <div>
<button @click="modif=!modif"> {{i18n("profile.modify.data")}} </button> <button @click="modif=!modif; setModify(user)"> {{i18n("profile.modify.data")}} </button>
</div> </div>
<div v-if="(user.role==='Student')"> <div v-if="(user.role==='Student')">
<button @click="reg=!reg">{{i18n("profile.reRegister")}}</button> <button @click="reg=!reg">{{i18n("profile.reRegister")}}</button>
<button @click="unreg=!unreg" style="float:right;background-color:rgb(150,0,0);">{{i18n("profile.unRegister")}}</button> <button @click="unRegister()" style="float:right;background-color:rgb(150,0,0);">{{i18n("profile.unRegister")}}</button>
</div> </div>
<div v-if="(user.role==='Student')"> <div v-if="(user.role==='Student')">
<button @click="curric=!curric">{{i18n("profile.change.curriculum")}}</button> <button @click="curric=!curric">{{i18n("profile.change.curriculum")}}</button>
@ -88,48 +127,36 @@
</div> </div>
<div> <div>
E-mail: E-mail:
<input type="mail" v-model="personnalInfos.email" /> <input type="mail" v-model="toModify.email" />
</div> </div>
<div> <div>
{{i18n("profile.address")}}: {{i18n("profile.address")}}:
<input type="text" v-model="personnalInfos.id"> <input type="text" v-model="toModify.id">
</div> </div>
<div> <div>
{{i18n("login.password")}}: {{i18n("login.password")}}:
<input type="password" v-model="personnalInfos.password"> <input type="password" v-model="toModify.password">
</div> </div>
<div> <div>
{{i18n("login.cPassword")}}: {{i18n("login.cPassword")}}:
<input type="password" v-model="personnalInfos.passwordConfirm"> <input type="password" v-model="toModify.passwordConfirm">
</div> </div>
<div> <div>
<button @click=" modif=!modif; ChangeInfos();">{{i18n("courses.confirm")}}</button> <button @click=" modif=!modif; ChangeInfos();">{{i18n("courses.confirm")}}</button>
<button @click="modif=!modif; resetInputs(toModify,pattern);console.log(pattern)" style="float:right;">{{i18n("courses.back")}}</button> <button @click="modif=!modif; resetInputs(toModify,pattern);" style="float:right;">{{i18n("courses.back")}}</button>
</div> </div>
</div> </div>
<div v-else-if="curric" class="infosContainer"> <div v-else-if="curric" class="infosContainer">
<div> <div style="height:40px;">
{{i18n("curriculum")}}: {{i18n("Curriculum")}}:
<select v-model="curriculum"> <select v-model="curriculum" >
<option v-for="item in currcula">{{item}}</option> <option v-for="item in curricula" style="font-size:20px;" :value="item">{{item.option}}</option>
</select> </select>
</div> </div>
<div>
E-mail:
<input type="mail" v-model="mail">
</div>
<div>
{{i18n("login.password")}}:
<input type="password" v-model="assword">
</div>
<div>
{{i18n("login.cPassword")}}:
<input type="password" id="confirm">
</div>
<div> <div>
<button @click=" curric=!curric;">{{i18n("courses.confirm")}}</button> <button @click=" curric=!curric;">{{i18n("courses.confirm")}}</button>
<button @click="curric=!curric; resetInputs(personnalInfos,patternInfos);console.log(pattern)" style="float:right;">{{i18n("courses.back")}}</button> <button @click="curric=!curric; resetInputs(personnalInfos,patternInfos);" style="float:right;">{{i18n("courses.back")}}</button>
</div> </div>
</div> </div>
<div v-else-if="reg" class="infosContainer"> <div v-else-if="reg" class="infosContainer">
@ -152,46 +179,22 @@
<div> <div>
<button @click=" reg=!reg;">{{i18n("courses.confirm")}}</button> <button @click=" reg=!reg;">{{i18n("courses.confirm")}}</button>
<button @click=" reg=!reg; resetInputs(personnalInfos,patternInfos);console.log(pattern)" style="float:right;">{{i18n("courses.back")}}</button> <button @click=" reg=!reg; resetInputs(personnalInfos,patternInfos);" style="float:right;">{{i18n("courses.back")}}</button>
</div>
</div>
<div v-else-if="unreg" class="infosContainer">
<div>
E-mail:
<input type="mail" v-model="toModify.email" />
</div>
<div>
{{i18n("profile.address")}}:
<input type="text" v-model="toModify.address">
</div>
<div>
{{i18n("login.password")}}:
<input type="password" v-model="toModify.password">
</div>
<div>
{{i18n("login.cPassword")}}:
<input type="password" id="confirm">
</div>
<div>
<button @click=" unreg=!unreg;">{{i18n("courses.confirm")}}</button>
<button @click=" unreg=!unreg; resetInputs(personnalInfos,patternInfos);console.log(pattern)" style="float:right;">{{i18n("courses.back")}}</button>
</div> </div>
</div> </div>
</div> </div>
<div v-if="modif==false && curric==false && unreg==false && reg==false "class="moreInfos"> <div v-if="modif==false && curric==false && reg==false "class="moreInfos">
<div v-if="(user.role==='Student')"> <div v-if="(user.role ==='Student')">
<div class="listTitle"> <div class="listTitle">
{{i18n("profile.course.list")}} {{i18n("profile.course.list")}}
</div> </div>
<div class="listElement " <div class="listElement" v-for="item in UserCurriculum.courses">
v-for="item in user.curriculum">
<div class=" containerElement"> <div class=" containerElement">
<div class="name"> {{item.name}} </div> <div class="name"> {{item.title}} </div>
<div class="teacher">{{item.teacher}}</div> <div class="teacher">{{item.owner.lastName}}</div>
<div class="credits">Credits:{{item.credits}}</div> <div class="credits">Credits:{{item.credits}}</div>
</div> </div>
</div> </div>
@ -200,14 +203,6 @@
<div> <div>
</div> </div>
<div v-if="(user.role==='Teacher')">
<div class="listTitle">
{{i18n("profile.course.list")}}
</div>
<div class="listElement " v-for="item in user.coursesOwned">
{{item.name}}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -4,7 +4,6 @@
import { getStudents } from '../rest/Users.js' import { getStudents } from '../rest/Users.js'
const users = await getStudents(); const users = await getStudents();
console.log(users)
</script> </script>
<template> <template>
<div v-for="item in users"> <div v-for="item in users">

View File

@ -6,7 +6,6 @@
const users = await getAllUsers(); const users = await getAllUsers();
console.log(users);
</script> </script>
<template> <template>
<div v-for="item in users"> <div v-for="item in users">

View File

@ -41,5 +41,5 @@ export async function getAllRegisters(){
* Change the state of a requests. * Change the state of a requests.
*/ */
export async function validateRegister(id, state){ export async function validateRegister(id, state){
return restPatch("/request/register/" + id, {state: state}); return restPatch("/request/register/" + id, state);
} }

View File

@ -1,4 +1,4 @@
import { restGet, restPost, restPatch} from './restConsumer.js' import { restGet, restPost, restPatch, restDelete} from './restConsumer.js'
import { getCookie, setCookie } from '@/utils.js' import { getCookie, setCookie } from '@/utils.js'
export async function login(user, pass, exp){ export async function login(user, pass, exp){
@ -28,14 +28,15 @@ export function disconnect(){
*/ */
export async function register(firstname, lastname, birthDate, password, email, address, country, curriculumId, imageId){ export async function register(firstname, lastname, birthDate, password, email, address, country, curriculumId, imageId){
return restPost("/register", { return restPost("/register", {
firstname: firstname, firstName: firstname,
lastname: lastname, lastName: lastname,
birthDate: birthDate, birthDate: birthDate,
password: password, password: password,
email: email, email: email,
address: address, address: address,
country: country, country: country,
curriculumId: curriculumId curriculumId: curriculumId,
profilePictureUrl: imageId,
}); });
} }
@ -139,6 +140,13 @@ export async function getSelf(){
* - Adress * - Adress
* - Password * - Password
*/ */
export async function alterSelf(data){ export async function alterSelf(id,data){
return restPatch("/user", data); console.log(data)
return restPatch("/user/"+id, data);
}
export async function deleteUser(id){
return restDelete("/user/" + id)
} }

View File

@ -7,8 +7,10 @@ import { restGet, restPost, restDelete, restPatch } from './restConsumer.js'
/** /**
* Create a new course * Create a new course
*/ */
export async function createCourse(name, credits, teacher){ export async function createCourse(name, credits, owner){
return restPost("/course", {title: name, credits: credits, owner: teacher} ) console.log(owner);
return restPost("/course", {title: name, credits: credits, owner} )
} }
/** /**

View File

@ -43,3 +43,8 @@ export async function getcurriculum(id){
export async function altercurriculum(id, courses){ export async function altercurriculum(id, courses){
return restPatch("/curriculum/" + id, courses); return restPatch("/curriculum/" + id, courses);
} }
export async function getSelfCurriculum(){
return restGet("/curriculum");
}

View File

@ -16,8 +16,8 @@ export async function restPostFile(endPoint, file){
return await _rest(endPoint, {method: "POST", credentials: 'include', body: file, headers: headers }); return await _rest(endPoint, {method: "POST", credentials: 'include', body: file, headers: headers });
} }
export async function restDelete(endPoint, data) { export async function restDelete(endPoint) {
return await _rest(endPoint, {method: "DELETE", credentials: 'include', body: JSON.stringify(data)}); return await _rest(endPoint, {method: "DELETE"});
} }
export async function restPatch(endPoint, data) { export async function restPatch(endPoint, data) {