121 Commits

Author SHA1 Message Date
b8b193f344 proposition of some fixes 2024-04-05 09:44:41 +02:00
3d78851b29 moving file into extensions directory 2024-04-04 21:27:51 +02:00
dbe28a7fed making the chart responsive 2024-04-04 16:14:19 +02:00
bd7d2c2d51 adding colors to piechart 2024-04-04 15:01:10 +02:00
91c7f42521 finished mock researcher profile 2024-04-02 19:52:38 +02:00
bd27ffd3cb search bar not working (to be shared with william) 2024-04-01 19:13:39 +02:00
91ee3adbcd adding the dependance 2024-03-30 13:10:11 +01:00
c1b2742a8f better select buttons 2024-03-30 12:38:18 +01:00
2805fede4b researcher profile page separations 2024-03-30 12:38:18 +01:00
951feed3c8 Full screen apps 2024-03-30 12:38:18 +01:00
95054fa973 Login 'fixed' 2024-03-30 12:38:18 +01:00
3af83a58d3 Just to merge 2024-03-30 12:38:17 +01:00
47c5c14862 Make app use full space 2024-03-30 12:38:17 +01:00
db895a6091 added temporary fix to docker issue 2024-03-23 14:38:26 +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
8ff29ca34e Register
Some checks failed
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) Failing after 23s
2024-03-17 23:19:36 +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
7e7cec2f6c Merge branch 'Max/Backend/GetUserById' into wal/front/listingUsers
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 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-17 22:00:56 +01:00
345599888d added GET /user/{id}
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 1m56s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-17 21:48:58 +01:00
19b4950be4 Merge branch 'master' into wal/front/listingUsers
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m4s
Build and test backend / Test-backend (pull_request) Successful in 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-17 21:39:04 +01:00
d9307753c4 trop de truc
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m58s
Build and test backend / Test-backend (pull_request) Successful in 1m56s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-17 21:38:10 +01:00
7a23dcc96a Merge pull request 'Max/Backend/ReturnUserPasswordIssue' (#137) from Max/Backend/ReturnUserPasswordIssue into master
All checks were successful
Build and test backend / Test-backend (push) Successful in 1m20s
deploy to production / deploy-frontend (push) Successful in 23s
Build and test backend / Build-backend (push) Successful in 2m12s
deploy to production / deploy-backend (push) Successful in 2m18s
Build and test FrontEnd / Build-frontend (push) Successful in 23s
Reviewed-on: #137
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: LeoMoulin <leomoulin125@gmail.com>
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
2024-03-17 21:36:53 +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
ea4a0745e0 creation of the user when request accepted
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m42s
Build and test backend / Test-backend (pull_request) Successful in 2m30s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 33s
2024-03-17 17:15:33 +01:00
76f5a39a8f GET /users doesn't return Admins if the poster isn't an admin
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m1s
Build and test backend / Test-backend (pull_request) Successful in 2m0s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-17 16:26:30 +01:00
37f8a3ac4e removed an unused variable 2024-03-17 16:25:00 +01:00
ea46dd664c added a todo to send an email for every state changement of request
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m58s
Build and test backend / Test-backend (pull_request) Successful in 1m59s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-17 16:02:30 +01:00
b2d0be014c UserList and Student List part1
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 1m56s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-17 15:59:12 +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
210fda0401 Merge branch 'master' into wal/front/listingUsers 2024-03-17 13:33:47 +01:00
b67b25b4a4 Login Finished, add curricula and apps
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 23s
2024-03-17 13:24:24 +01:00
385290d1a2 Merge branch 'master' into Max/Backend/ReturnUserPasswordIssue
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m4s
Build and test backend / Test-backend (pull_request) Successful in 1m58s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-17 13:07:20 +01:00
cf2deb983d added security to assistant posting and Get courses/owned for owners
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 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-17 12:13:03 +01:00
dcec45acf5 Merge pull request 'added /students endpoint' (#135) from Max/Backend/StudentEndPoin into master
All checks were successful
Build and test backend / Build-backend (push) Successful in 2m11s
Build and test backend / Test-backend (push) Successful in 1m19s
deploy to production / deploy-frontend (push) Successful in 24s
deploy to production / deploy-backend (push) Successful in 2m20s
Build and test FrontEnd / Build-frontend (push) Successful in 24s
Reviewed-on: #135
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
Reviewed-by: Wal <karpinskiwal@gmail.com>
2024-03-17 12:00:57 +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
f7df234312 moved portective method to Static ProtectiveService
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 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-17 03:06:19 +01:00
d855bbe911 Merge branch 'Max/Backend/CourseInCurriculum' into Max/Backend/ReturnUserPasswordIssue 2024-03-17 02:50:12 +01:00
f2507ddcdd forgot the return statement 2024-03-17 02:46:33 +01:00
a70b05a0ef protected course'owner password 2024-03-17 02:45:49 +01:00
1d793cef4e moved UserWithouPaswword to authenticatorService 2024-03-17 02:40:05 +01:00
4cf2ac1aa8 fixed an issue with the getting of curriculums
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m1s
Build and test backend / Test-backend (pull_request) Successful in 1m58s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-17 02:34:00 +01:00
6e6bd285af added security to the post of course and GET /courses 2024-03-17 02:15:08 +01:00
474a8d3f31 added POST /curriculum/{id} endopoint to post courses 2024-03-17 02:00:42 +01:00
4379794dba added /students endpoint
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m1s
Build and test backend / Test-backend (pull_request) Successful in 1m56s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-16 23:05:26 +01:00
c5d7ce4178 cleaned the Entities
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m4s
Build and test backend / Test-backend (pull_request) Successful in 2m1s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 20:31:03 +01:00
382d3c203a cleaned the services 2024-03-16 20:25:35 +01:00
5a7934b2a3 Merge branch 'master' into wal/front/listingUsers
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m14s
Build and test backend / Test-backend (pull_request) Successful in 2m7s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 27s
2024-03-16 19:57:53 +01:00
8476563678 profil part3 2024-03-16 19:54:42 +01:00
97b57b361d cleaned all controllers 2024-03-16 19:13:57 +01:00
069466ef5f Max/Backend/CoursesEndpoints (#129)
All checks were successful
Build and test backend / Build-backend (push) Successful in 2m16s
Build and test backend / Test-backend (push) Successful in 1m24s
deploy to production / deploy-frontend (push) Successful in 26s
deploy to production / deploy-backend (push) Successful in 2m22s
Build and test FrontEnd / Build-frontend (push) Successful in 26s
PLZ FIX

Reviewed-on: #129
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
Co-authored-by: Bartha Maxime <231026@umons.ac.be>
Co-committed-by: Bartha Maxime <231026@umons.ac.be>
2024-03-16 17:17:07 +01:00
d5f6656e2b added the GET /teachers (#130)
Some checks failed
Build and test backend / Build-backend (push) Has been cancelled
Build and test backend / Test-backend (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 FrontEnd / Build-frontend (push) Waiting to run
had to fix the mock and the UserController isAdminOrSecretary

Reviewed-on: #130
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
Co-authored-by: Bartha Maxime <231026@umons.ac.be>
Co-committed-by: Bartha Maxime <231026@umons.ac.be>
2024-03-16 17:16:46 +01:00
32e26f35cb Merge pull request 'show apps by role' (#131) from tonitch/front/apps into master
Some checks failed
Build and test backend / Build-backend (push) Has been cancelled
Build and test backend / Test-backend (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 FrontEnd / Build-frontend (push) Waiting to run
Reviewed-on: #131
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: Maxime <231026@umons.ac.be>
2024-03-16 17:16:34 +01:00
36fc33c3e9 Profil part.2/?
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m4s
Build and test backend / Test-backend (pull_request) Successful in 2m4s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-16 17:01:26 +01:00
17ab241250 show map by role
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m7s
Build and test backend / Test-backend (pull_request) Successful in 2m4s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 16:57:52 +01:00
36ce5a553b Profil, merge Master and corrections
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 1m59s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-16 15:21:10 +01:00
a5807148e1 And again we continue
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 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 15:06:21 +01:00
53e478b05c Merge pull request 'added ApplicationController and Application enum' (#119) from Max/Backend/AppsController into master
All checks were successful
Build and test backend / Build-backend (push) Successful in 2m12s
Build and test backend / Test-backend (push) Successful in 1m19s
deploy to production / deploy-backend (push) Successful in 2m18s
Build and test FrontEnd / Build-frontend (push) Successful in 25s
deploy to production / deploy-frontend (push) Successful in 26s
Reviewed-on: #119
Reviewed-by: Debucquoy Anthony <d.tonitch@gmail.com>
Reviewed-by: Wal <karpinskiwal@gmail.com>
2024-03-16 14:51:56 +01:00
182be8ac7b Merge branch 'master' into Max/Backend/AppsController
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 1m58s
Build and test backend / Test-backend (pull_request) Successful in 1m59s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-16 14:48:03 +01:00
beba199f60 Merge pull request 'Login indication' (#127) from tonitch/front/loginIndication into master
All checks were successful
Build and test backend / Test-backend (push) Successful in 1m17s
deploy to production / deploy-frontend (push) Successful in 24s
Build and test FrontEnd / Build-frontend (push) Successful in 24s
deploy to production / deploy-backend (push) Successful in 2m21s
Build and test backend / Build-backend (push) Successful in 2m12s
Reviewed-on: #127
Reviewed-by: Wal <karpinskiwal@gmail.com>
Reviewed-by: Maxime <231026@umons.ac.be>
2024-03-16 14:45:02 +01:00
8d1235be92 again links
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 1m58s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-16 14:31:44 +01:00
04f64f505e Indicated that you are logged by coloring the icon in orange and disconnect if clicked on it
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 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 13:56:29 +01:00
e84e34d735 login 2024-03-16 12:47:49 +01:00
847936b799 fix tokens characters
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m6s
Build and test backend / Test-backend (pull_request) Successful in 2m0s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-16 12:36:17 +01:00
0b27d2e8d8 Merge branch 'master' into tonitch/front/pagesAPI
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-16 12:35:15 +01:00
Wal
ca6f676fb7 Merge pull request 'tonitch/front/manageCourses/LinkToBackend' (#125) from tonitch/front/manageCourses/LinkToBackend 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 1m57s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 26s
Reviewed-on: #125
2024-03-16 12:26:57 +01:00
cc8530621d Merge branch 'master' into tonitch/front/manageCourses/LinkToBackend
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 1m56s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 12:01:44 +01:00
abff9aef3a Merge branch 'master' into Max/Backend/AppsController
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 1m56s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 11:58:03 +01:00
41288258c9 Merge branch 'master' into wal/front/listingUsers
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m1s
Build and test backend / Test-backend (pull_request) Successful in 2m2s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 11:56:37 +01:00
47a0c97f3d small commit but its for the big merge+ verif psswrd and confirm in login
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m1s
Build and test backend / Test-backend (pull_request) Successful in 2m1s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 25s
2024-03-16 11:52:31 +01:00
b7b2eafb93 removed the GET /Apps/{id} frontend just iterates on the /apps list
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 2m2s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 00:44:11 +01:00
0860567e1b fixed the GetAuthorizedApps method
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m4s
Build and test backend / Test-backend (pull_request) Successful in 1m59s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-16 00:42:46 +01:00
d5e4387303 Merge branch 'master' 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 2m0s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-15 22:49:26 +01:00
1903a6c9be "trying functions"
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m4s
Build and test backend / Test-backend (pull_request) Successful in 2m1s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-15 22:47:40 +01:00
77a170be6d Merge branch 'master' into tonitch/front/pagesAPI
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m1s
Build and test backend / Test-backend (pull_request) Successful in 1m58s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-15 22:37:37 +01:00
ae4ad036a8 Merge remote-tracking branch 'origin/master' into tonitch/front/manageCourses/LinkToBackend 2024-03-15 22:32:21 +01:00
3996765c8a Simple hook for when the backend is ready
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-15 22:25:26 +01:00
b047c4de35 Listing users and students
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-15 20:23:33 +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
385640c10e Merge branch 'master' 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 1m59s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 23s
2024-03-15 15:14:18 +01:00
a0c38a8d59 adding list of user PROTO 2024-03-15 15:12:01 +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
160cfb0bbf Page api stub
All checks were successful
Build and test backend / Build-backend (pull_request) Successful in 2m1s
Build and test backend / Test-backend (pull_request) Successful in 1m55s
Build and test FrontEnd / Build-frontend (pull_request) Successful in 24s
2024-03-09 18:41:20 +01:00
73 changed files with 2546 additions and 765 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

@ -25,14 +25,17 @@ dependencies {
implementation("com.kohlschutter.junixsocket:junixsocket-core:2.9.0") implementation("com.kohlschutter.junixsocket:junixsocket-core:2.9.0")
// implementation("org.springframework.session:spring-session-jdbc") // implementation("org.springframework.session:spring-session-jdbc")
developmentOnly("org.springframework.boot:spring-boot-devtools") developmentOnly("org.springframework.boot:spring-boot-devtools")
developmentOnly("org.springframework.boot:spring-boot-docker-compose") // developmentOnly("org.springframework.boot:spring-boot-docker-compose")
runtimeOnly("org.postgresql:postgresql") runtimeOnly("org.postgresql:postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-starter-test")
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)
} }

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

@ -2,6 +2,7 @@ package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
@ -9,10 +10,12 @@ import org.springframework.web.bind.annotation.RestController;
import ovh.herisson.Clyde.Services.AuthenticatorService; import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Tables.Applications; import ovh.herisson.Clyde.Tables.Applications;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList; import java.util.ArrayList;
@RestController @RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class ApplicationsController { public class ApplicationsController {
AuthenticatorService authServ; AuthenticatorService authServ;
@ -27,7 +30,6 @@ public class ApplicationsController {
*/ */
@GetMapping("/apps") @GetMapping("/apps")
public ResponseEntity<Iterable<Applications>> getAuthorizedApps(@RequestHeader("Authorization") String token){ public ResponseEntity<Iterable<Applications>> getAuthorizedApps(@RequestHeader("Authorization") String token){
return new ResponseEntity<>(getAuthorizedApplications(token), HttpStatus.OK); return new ResponseEntity<>(getAuthorizedApplications(token), HttpStatus.OK);
} }
@ -41,22 +43,33 @@ public class ApplicationsController {
} }
public ArrayList<Applications> getAuthorizedApplications(String token){ public ArrayList<Applications> getAuthorizedApplications(String token){
Role posterRole = authServ.getUserFromToken(token).getRole();
ArrayList<Applications> authorizedApps = new ArrayList<>(); ArrayList<Applications> authorizedApps = new ArrayList<>();
//if unAuthed
authorizedApps.add(Applications.Login); authorizedApps.add(Applications.Login);
User user = authServ.getUserFromToken(token);
if(user == null)
return authorizedApps;
// if authed
authorizedApps.add(Applications.Profile); authorizedApps.add(Applications.Profile);
if (!authServ.isNotIn(new Role[]{Role.Teacher,Role.Student,Role.Admin},token)) {
authorizedApps.add(Applications.Msg); authorizedApps.add(Applications.Msg);
authorizedApps.add(Applications.Forum); authorizedApps.add(Applications.Forum);
authorizedApps.add(Applications.Rdv); authorizedApps.add(Applications.Rdv);
if (posterRole == Role.Student || posterRole == Role.Admin) return authorizedApps;
if (posterRole == Role.Teacher || posterRole == Role.Secretary || posterRole == Role.Admin) authorizedApps.add(Applications.ManageCourses);
if (posterRole == Role.InscriptionService || posterRole == Role.Admin) authorizedApps.add(Applications.Inscription);
return authorizedApps;
} }
//if Teacher or Secretary or Admin add ManageCourses App
if (!authServ.isNotIn(new Role[]{Role.Teacher,Role.Secretary,Role.Admin},token))
authorizedApps.add(Applications.ManageCourses);
if (!authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin},token)){
authorizedApps.add(Applications.Inscription);
authorizedApps.add(Applications.StudentsList);}
if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token)){
authorizedApps.add(Applications.UsersList);}
return authorizedApps;
}
} }

View File

@ -0,0 +1,138 @@
package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.CourseService;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Services.TeacherCourseService;
import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import java.util.HashMap;
import java.util.Map;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class CourseController {
private final CourseService courseServ;
private final TeacherCourseService teacherCourseServ;
private final AuthenticatorService authServ;
public CourseController(CourseService courseServ, TeacherCourseService teacherCourseServ, AuthenticatorService authServ) {
this.courseServ = courseServ;
this.teacherCourseServ = teacherCourseServ;
this.authServ = authServ;
}
@GetMapping("/course/{id}")
public ResponseEntity<HashMap<String,Object>> getCourse(@RequestHeader("Authorization") String token, @PathVariable long id){
if (authServ.getUserFromToken(token) == null)
return new UnauthorizedResponse<>(null);
Course foundCourse = courseServ.findById(id);
if (foundCourse == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(ProtectionService.courseWithoutPassword(foundCourse), HttpStatus.OK);
}
@GetMapping("/courses")
public ResponseEntity<Iterable<HashMap<String,Object>>> getAllCourses(@RequestHeader("Authorization") String token){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token))
return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(ProtectionService.coursesWithoutPasswords(courseServ.findAll()),HttpStatus.OK);
}
@GetMapping("/courses/owned")
public ResponseEntity<Iterable<HashMap<String ,Object>>> getOwnedCourses(@RequestHeader("Authorization") String token){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Teacher},token))
return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(ProtectionService.coursesWithoutPasswords(courseServ.findOwnedCourses(authServ.getUserFromToken(token))),HttpStatus.OK);
}
@GetMapping("/course/{id}/assistants")
public ResponseEntity<Iterable<HashMap<String,Object>>> getCourseAssistants(@RequestHeader("Authorization")String token, @PathVariable long id){
if (authServ.getUserFromToken(token) == null)
return new UnauthorizedResponse<>(null);
Iterable<User> assistants = teacherCourseServ.findCourseAssistants(courseServ.findById(id));
return new ResponseEntity<>(ProtectionService.usersWithoutPasswords(assistants),HttpStatus.OK);
}
@PostMapping("/course")
public ResponseEntity<Map<String ,Object>> postCourse(@RequestHeader("Authorization") String token,
@RequestBody Course course)
{
System.out.println(course);
System.out.println(token);
if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token))
return new UnauthorizedResponse<>(null);
Course createdCourse = courseServ.save(course);
if (createdCourse == null)
return new ResponseEntity<>(null,HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(ProtectionService.courseWithoutPassword(createdCourse), HttpStatus.CREATED);
}
@PatchMapping("/course/{id}")
public ResponseEntity<Course> patchCourse(@RequestHeader("Authorization") String token,
@RequestBody Map<String,Object> updates,
@PathVariable long id)
{
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Teacher,Role.Secretary}, token))
return new UnauthorizedResponse<>(null);
if (!courseServ.modifyData(id, updates, authServ.getUserFromToken(token).getRole()))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(HttpStatus.OK);
}
@PostMapping("/course/{id}")
public ResponseEntity<String> postTeachers(@RequestHeader("Authorization") String token,
@RequestBody Iterable<Long> teacherIds,
@PathVariable Long id)
{
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary}, token))
return new UnauthorizedResponse<>(null);
if (!teacherCourseServ.saveAll(teacherIds,courseServ.findById(id)))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
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

@ -4,43 +4,94 @@ package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus; 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.Services.AuthenticatorService; import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.CurriculumCourseService; import ovh.herisson.Clyde.Services.*;
import ovh.herisson.Clyde.Services.CurriculumService;
import ovh.herisson.Clyde.Tables.Curriculum; import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.CurriculumCourse;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import java.util.Map; import java.util.Map;
@RestController @RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class CurriculumController { 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;
} }
@GetMapping("/curriculum/{id}") @GetMapping("/curriculum/{id}")
public ResponseEntity<Curriculum> findById(@PathVariable long id){ public ResponseEntity<Map<String,Object>> findById(@PathVariable long id){
return new ResponseEntity<>(curriculumServ.findById(id), HttpStatus.OK); Curriculum foundCurriculum = curriculumServ.findById(id);
}
@GetMapping("/curriculums") if (foundCurriculum == null)
public ResponseEntity<Iterable<Map<String, Object>>> findAllindDepth(){ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(curriculumCourseServ.getAllDepthCurriculum(),HttpStatus.OK);
return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(foundCurriculum), HttpStatus.OK);
} }
@GetMapping("/curriculum") @GetMapping("/curriculum")
public ResponseEntity<Iterable<CurriculumCourse>> findAll(){ public ResponseEntity<Map<String ,Object>> findSelfCurriculum(@RequestHeader("Authorization") String token){
return new ResponseEntity<>(curriculumCourseServ.findAll(),HttpStatus.OK); 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")
public ResponseEntity<Iterable<Map<String, Object>>> findAllIndDepth(){
return new ResponseEntity<>(curriculumCourseServ.getAllDepthCurriculum(),HttpStatus.OK);
}
@PostMapping("/curriculum")
public ResponseEntity<Curriculum> postCurriculum(@RequestHeader("Authorization") String token,@RequestBody Curriculum curriculum){
if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token))
return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(curriculumServ.save(curriculum),HttpStatus.CREATED);
}
@PostMapping("/curriculum/{id}")
public ResponseEntity<String> postCoursesToCurriculum(@RequestHeader("Authorization") String token,
@RequestBody Iterable<Long> coursesIds,
@PathVariable long id)
{
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token))
return new UnauthorizedResponse<>(null);
if (!curriculumCourseServ.saveAll(coursesIds, curriculumServ.findById(id)))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
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,17 +6,14 @@ 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 ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
@RestController @RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true") @CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class InscriptionController { public class InscriptionController {
@ -32,55 +29,54 @@ public class InscriptionController {
@GetMapping("/requests/register") @GetMapping("/requests/register")
public ResponseEntity<Iterable<Map<String,Object>>> getAllRequests(@RequestHeader("Authorization") String token){ public ResponseEntity<Iterable<Map<String,Object>>> getAllRequests(@RequestHeader("Authorization") String token){
if (authServ.isNotSecretaryOrAdmin(token)){return new UnauthorizedResponse<>(null);} if (authServ.isNotIn(new Role[]{Role.Admin,Role.InscriptionService},token))
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);
} }
@GetMapping("/request/register/{id}") @GetMapping("/request/register/{id}")
public ResponseEntity<Map<String,Object>> getById(@PathVariable long id){ public ResponseEntity<Map<String,Object>> getById(@RequestHeader("Authorization") String token, @PathVariable long id){
InscriptionRequest inscriptionRequest = inscriptionServ.getById(id);
if (inscriptionRequest == null) {return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);}
return new ResponseEntity<>(requestWithoutPassword(inscriptionRequest), HttpStatus.OK); if (authServ.isNotIn(new Role[]{Role.Admin,Role.InscriptionService},token))
} return new UnauthorizedResponse<>(null);
@GetMapping("request/user/{id}") InscriptionRequest foundInscriptionRequest = inscriptionServ.getById(id);
public ResponseEntity<InscriptionRequest> getUserInscriptionRequest(@PathVariable long id, @RequestHeader("Authorize") String token){
//todo return l'inscriptionRequest ACTUELLE du user (check si le poster est bien le même que id target ou secretariat) if (foundInscriptionRequest == null)
return null; return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
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("Authorize") String token, @RequestHeader("Authorization") String token,
@RequestBody RequestState requestState) @RequestBody RequestState state)
{ {
if (authServ.isNotSecretaryOrAdmin(token)) return new UnauthorizedResponse<>(null); if (authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin},token))
inscriptionServ.modifyState(id, requestState); return new UnauthorizedResponse<>(null);
return null;
if (!inscriptionServ.modifyState(id, state))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
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);
InscriptionRequest toDelete = inscriptionServ.getById(id);
if (toDelete == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
inscriptionServ.delete(toDelete);
return new ResponseEntity<>(HttpStatus.OK);
} }
private Map<String, Object> requestWithoutPassword(InscriptionRequest inscriptionRequest) {
Map<String, Object> toReturn = new HashMap<>();
toReturn.put("id", inscriptionRequest.getId());
toReturn.put("firstName", inscriptionRequest.getFirstName());
toReturn.put("lastName", inscriptionRequest.getLastName());
toReturn.put("address", inscriptionRequest.getAddress());
toReturn.put("birthDate", inscriptionRequest.getBirthDate());
toReturn.put("country", inscriptionRequest.getCountry());
toReturn.put("curriculum", inscriptionRequest.getCurriculum());
toReturn.put("profilePictureUrl", inscriptionRequest.getProfilePicture());
toReturn.put("state", inscriptionRequest.getState());
return toReturn;
}
} }

View File

@ -1,4 +1,5 @@
package ovh.herisson.Clyde.EndPoints; package ovh.herisson.Clyde.EndPoints;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -6,9 +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")
@ -44,9 +46,11 @@ public class LoginController {
return ResponseEntity.ok().headers(responseHeaders).build(); return ResponseEntity.ok().headers(responseHeaders).build();
} }
@PostMapping("/request/register") @PostMapping("/register")
public ResponseEntity<String> register(@RequestBody InscriptionRequest inscriptionRequest){ public ResponseEntity<Map<String,Object>> register(@RequestBody InscriptionRequest inscriptionRequest){
authServ.register(inscriptionRequest);
return new ResponseEntity<>("Is OK", HttpStatus.OK); InscriptionRequest returnedInscriptionRequest = authServ.register(inscriptionRequest);
return new ResponseEntity<>(ProtectionService.requestWithoutPassword(returnedInscriptionRequest), HttpStatus.CREATED);
} }
} }

View File

@ -6,7 +6,6 @@ import ovh.herisson.Clyde.Repositories.TokenRepository;
import ovh.herisson.Clyde.Repositories.UserRepository; import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Services.*; import ovh.herisson.Clyde.Services.*;
import ovh.herisson.Clyde.Tables.*; import ovh.herisson.Clyde.Tables.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
@ -23,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 :
@ -47,16 +49,16 @@ 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.Teacher,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 lena = new User("Louille","Lena","inscriptionService@InscriptionService.com","no","yes",new Date(0), null,Role.Teacher,passwordEncoder.encode("inscriptionService")); User jojo = new User("Bridoux","Justin","teacher2@teacher2.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher"));
mockUsers = new ArrayList<>(Arrays.asList(herobrine,joe,meh,joke)); 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,jojo));
userRepo.saveAll(mockUsers); userRepo.saveAll(mockUsers);
// Course / Curriculum part // Course / Curriculum part
Curriculum infoBab1 = new Curriculum(1,"info"); Curriculum infoBab1 = new Curriculum(1,"info");
@ -68,10 +70,10 @@ public class MockController {
curriculumService.save(psychologyBab1); curriculumService.save(psychologyBab1);
Course progra1 = new Course(5,"Programmation et algorithimque 1","TODO DELETE"); Course progra1 = new Course(5,"Programmation et algorithmique 1",joke);
Course chemistry1 = new Course(12, "Thermochimie","TODO DELETE"); Course chemistry1 = new Course(12, "Thermochimie",joke);
Course psycho1 = new Course(21, "rien faire t'as cru c'est psycho", "TODO DELETE"); Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells",joke);
Course commun = new Course(2, "cours commun","TODO DELETE"); Course commun = new Course(2, "cours commun",joke);
courseService.save(progra1); courseService.save(progra1);
courseService.save(chemistry1); courseService.save(chemistry1);
@ -90,15 +92,10 @@ public class MockController {
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);
@DeleteMapping("/mock")
public void deleteMock(){
for (User user:mockUsers){
tokenRepo.deleteAll(tokenRepo.getByUser(user));
}
userRepo.deleteAll(mockUsers);
} }
} }

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){
@ -22,12 +21,13 @@ public class StorageController {
@PostMapping("/upload/{fileType}") @PostMapping("/upload/{fileType}")
public ResponseEntity<StorageFile> handleFileUpload(@RequestParam("file") MultipartFile file, @PathVariable FileType fileType) { public ResponseEntity<StorageFile> handleFileUpload(@RequestParam("file") MultipartFile file, @PathVariable FileType fileType) {
StorageFile fileEntry = null; StorageFile fileEntry;
try { try {
fileEntry = storageServ.store(file,fileType); fileEntry = storageServ.store(file,fileType);
} catch(Exception e){ } catch(Exception e){
e.printStackTrace(); e.printStackTrace();
return new ResponseEntity<>(null,HttpStatus.BAD_REQUEST);
} }

View File

@ -1,11 +1,15 @@
package ovh.herisson.Clyde.EndPoints; package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.TokenService; import ovh.herisson.Clyde.Services.TokenService;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.Token;
@RestController @RestController
@ -14,13 +18,20 @@ public class TokenController {
private final TokenService tokenServ; private final TokenService tokenServ;
public TokenController(TokenService tokenServ){ private final AuthenticatorService authServ;
public TokenController(TokenService tokenServ, AuthenticatorService authServ){
this.tokenServ = tokenServ; this.tokenServ = tokenServ;
this.authServ = authServ;
} }
@GetMapping("/tokens") @GetMapping("/tokens")
public Iterable<Token> getTokens(){ public ResponseEntity<Iterable<Token>> getTokens(@RequestHeader("Authorization")String token){
return tokenServ.getAllTokens();
if (authServ.isNotIn(new Role[]{Role.Admin},token))
return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(tokenServ.getAllTokens(), HttpStatus.OK);
} }
} }

View File

@ -1,14 +1,15 @@
package ovh.herisson.Clyde.EndPoints; package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus; 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.AuthenticatorService;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Services.UserService; import ovh.herisson.Clyde.Services.UserService;
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.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -25,67 +26,114 @@ public class UserController {
this.authServ = authServ; this.authServ = authServ;
} }
/** returns information about the connected user
*
* @param token the session token of the user
* @return the user information except his password
*/
@GetMapping("/user") @GetMapping("/user")
public ResponseEntity<HashMap<String,Object>> getUser(@RequestHeader("Authorization") String authorization){ public ResponseEntity<HashMap<String,Object>> getUser(@RequestHeader("Authorization") String token){
if (authorization == null) return new UnauthorizedResponse<>(null); User user = authServ.getUserFromToken(token);
User user = authServ.getUserFromToken(authorization);
if (user == null) return new UnauthorizedResponse<>(null); if (user == null) return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(userWithoutPassword(user), HttpStatus.OK); return new ResponseEntity<>(ProtectionService.userWithoutPassword(user), HttpStatus.OK);
}
@GetMapping("/user/{id}")
public ResponseEntity<HashMap<String ,Object>> getUserById(@RequestHeader("Authorization") String token, @PathVariable Long id){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(ProtectionService.userWithoutPassword(userService.getUserById(id)), HttpStatus.OK);
} }
@PostMapping("/user") @PostMapping("/user")
public ResponseEntity<String> postUser(@RequestBody User user,@RequestHeader("Authorization") String authorization){ public ResponseEntity<Map<String ,Object>> postUser(@RequestBody User user,@RequestHeader("Authorization") String token){
if (authServ.isNotSecretaryOrAdmin(authorization)) if (authServ.isNotIn(new Role[]{Role.Admin,Role.InscriptionService,Role.Secretary},token))
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
userService.save(user); return new ResponseEntity<>(ProtectionService.userWithoutPassword(userService.save(user)),HttpStatus.CREATED);
return new ResponseEntity<>(String.format("Account created with ID:%s",user.getRegNo()),HttpStatus.CREATED);
} }
@GetMapping("/users") @GetMapping("/users")
public ResponseEntity<Iterable<HashMap<String,Object>>> getAllUsers(@RequestHeader("Authorization") String authorization){ public ResponseEntity<Iterable<HashMap<String,Object>>> getAllUsers(@RequestHeader("Authorization") String token){
if (authServ.isNotSecretaryOrAdmin(authorization)) if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token))
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
Iterable<User> users = userService.getAll(); Role posterRole = authServ.getUserFromToken(token).getRole();
ArrayList<HashMap<String, Object>> withoutPassword = new ArrayList<>();
for (User u :users){ Iterable<User> users = new ArrayList<>();
withoutPassword.add(userWithoutPassword(u));
if (posterRole == Role.Admin)
users = userService.getAll();
else if (posterRole == Role.Secretary)
users = userService.getAllExceptAdmins();
return new ResponseEntity<>(ProtectionService.usersWithoutPasswords(users), HttpStatus.OK);
} }
return new ResponseEntity<>(withoutPassword, HttpStatus.OK);
}
@PatchMapping("/user")
public ResponseEntity<String> patchUser(@RequestBody Map<String,Object> updates, @RequestHeader("Authorization") String authorization) {
if (authorization == null) return new UnauthorizedResponse<>(null); /** changes the specified user's information
*
* @param updates the changes to be made
* @param token the session token of the user posting the change
* @param id the id of the user to change
* @return a string clarifying the issue (if there is any)
*/
@PatchMapping("/user/{id}")
public ResponseEntity<String> patchUser(@RequestHeader("Authorization") String token,
@RequestBody Map<String,Object> updates,
@PathVariable Long id) {
User poster = authServ.getUserFromToken(authorization); if (token == null) return new UnauthorizedResponse<>(null);
if (poster == null) {return new UnauthorizedResponse<>("bad authorization");}
if (!userService.modifyData(poster, updates, poster)) User poster = authServ.getUserFromToken(token);
if (poster == null) {return new UnauthorizedResponse<>("bad token");}
if (!userService.modifyData(id, updates, poster))
return new UnauthorizedResponse<>("there was an issue with the updates requested"); return new UnauthorizedResponse<>("there was an issue with the updates requested");
return new ResponseEntity<>("data modified", HttpStatus.OK); return new ResponseEntity<>(null, HttpStatus.OK);
} }
/** return user's data except password
* @param user the user to return @GetMapping("/teachers")
* @return all the user data without the password public ResponseEntity<Iterable<HashMap<String,Object>>> getAllTeachers(@RequestHeader("Authorization") String token){
*/ if (authServ.getUserFromToken(token) == null)
private HashMap<String,Object> userWithoutPassword(User user){ return new UnauthorizedResponse<>(null);
HashMap<String,Object> toReturn = new HashMap<>();
toReturn.put("regNo",user.getRegNo()); Iterable<User> teachers = userService.getAllTeachers();
toReturn.put("firstName",user.getFirstName());
toReturn.put("lastName",user.getLastName()); return new ResponseEntity<>(ProtectionService.usersWithoutPasswords(teachers), HttpStatus.OK);
toReturn.put("birthDate",user.getBirthDate()); }
toReturn.put("country",user.getCountry());
toReturn.put("address",user.getAddress());
toReturn.put("role",user.getRole()); @GetMapping("/students")
return toReturn; public ResponseEntity<Iterable<HashMap<String,Object>>> getAllStudent(@RequestHeader("Authorization") String token){
if (authServ.getUserFromToken(token) == null)
return new UnauthorizedResponse<>(null);
Iterable<User> students = userService.getAllStudents();
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,8 +1,15 @@
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.Course; import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.User;
public interface CourseRepository extends CrudRepository<Course,Long> { public interface CourseRepository extends CrudRepository<Course,Long> {
Course findById(long id); Course findById(long id);
@Query("select c from Course c where c.owner = ?1")
Iterable<Course> findAllOwnedCoures(User teacher);
} }

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

@ -0,0 +1,14 @@
package ovh.herisson.Clyde.Repositories;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.TeacherCourse;
import ovh.herisson.Clyde.Tables.User;
public interface TeacherCourseRepository extends CrudRepository<TeacherCourse, Long> {
@Query("select tc.user from TeacherCourse tc where tc.course = ?1")
Iterable<User> findAllAssistantOfCourse(Course course);
}

View File

@ -10,7 +10,5 @@ public interface TokenRepository extends CrudRepository<Token,Long> {
Token getByToken(String token); Token getByToken(String token);
Iterable<Token> getByUser(User user);
ArrayList <Token> getByUserOrderByExpirationDate(User user); ArrayList <Token> getByUserOrderByExpirationDate(User user);
} }

View File

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

View File

@ -4,15 +4,20 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
import java.util.List;
public interface UserRepository extends CrudRepository<User, Long> { public interface UserRepository extends CrudRepository<User, Long> {
User findById(long id); User findById(long id);
User findByEmail(String email); User findByEmail(String email);
/**
@Query(value = "select a.* from Users a ",nativeQuery = true)
Iterable<User> findAllUsers();**/ @Query("select u from User u where u.role = ovh.herisson.Clyde.Tables.Role.Teacher")
Iterable<User> findAllTeachers();
@Query("select u from User u where u.role = ovh.herisson.Clyde.Tables.Role.Student")
Iterable<User> findAllStudents();
@Query("select u from User u where u.role <> ovh.herisson.Clyde.Tables.Role.Admin")
Iterable<User> findAllExceptAdmins();
} }

View File

@ -1,11 +1,7 @@
package ovh.herisson.Clyde.Services; package ovh.herisson.Clyde.Services;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Tables.InscriptionRequest; import ovh.herisson.Clyde.Tables.*;
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.Date;
@Service @Service
@ -35,20 +31,23 @@ public class AuthenticatorService {
return token; return token;
} }
public void register(InscriptionRequest inscriptionRequest) { public InscriptionRequest register(InscriptionRequest inscriptionRequest) {
inscriptionService.save(inscriptionRequest); inscriptionRequest.setState(RequestState.Pending);
return inscriptionService.save(inscriptionRequest);
} }
public boolean isNotIn(Role[] roles, String token){
public boolean isNotSecretaryOrAdmin(String authorization){ if (token == null)
if (authorization ==null)
return true; return true;
User poster = getUserFromToken(authorization); User poster = getUserFromToken(token);
if (poster == null) return true; if (poster == null) return true;
return poster.getRole() != Role.Secretary || poster.getRole() != Role.Admin; for (Role r:roles){
if (poster.getRole() == r)
return false;
}
return true;
} }
} }

View File

@ -3,6 +3,9 @@ package ovh.herisson.Clyde.Services;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.CourseRepository; import ovh.herisson.Clyde.Repositories.CourseRepository;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import java.util.Map;
@Service @Service
public class CourseService { public class CourseService {
@ -13,11 +16,68 @@ public class CourseService {
this.courseRepo = courseRepo; this.courseRepo = courseRepo;
} }
public void save(Course course){ public Course save(Course course){
courseRepo.save(course); if (course.getOwner().getRole() != Role.Teacher)
return null;
return courseRepo.save(course);
} }
public Course findById(long id){ public Course findById(long id){
return courseRepo.findById(id); return courseRepo.findById(id);
} }
public Iterable<Course> findAll() {
return courseRepo.findAll();
}
public Iterable<Course> findOwnedCourses(User userFromToken) {
return courseRepo.findAllOwnedCoures(userFromToken);
}
public boolean modifyData(long id, Map<String, Object> updates, Role role) {
Course target = courseRepo.findById(id);
if (target == null)
return false;
if (role == Role.Teacher){
for (Map.Entry<String, Object> entry : updates.entrySet()){
if (entry.getKey().equals("title")){
target.setTitle((String) entry.getValue());
courseRepo.save(target);
return true;
}
}
}
if (role != Role.Secretary)
return false;
for (Map.Entry<String ,Object> entry: updates.entrySet()){
switch (entry.getKey()){
case "title":
target.setTitle((String) entry.getValue());
break;
case "credits":
target.setCredits((Integer) entry.getValue());
break;
case "owner":
if (((User) entry.getValue() ).getRole() != Role.Teacher)
break;
target.setOwner((User) entry.getValue());
break;
}
}
courseRepo.save(target);
return true;
}
public void delete(Course course) {
courseRepo.delete(course);
}
} }

View File

@ -4,9 +4,7 @@ import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.CourseRepository; import ovh.herisson.Clyde.Repositories.CourseRepository;
import ovh.herisson.Clyde.Repositories.CurriculumCourseRepository; import ovh.herisson.Clyde.Repositories.CurriculumCourseRepository;
import ovh.herisson.Clyde.Repositories.CurriculumRepository; import ovh.herisson.Clyde.Repositories.CurriculumRepository;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.CurriculumCourse;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -31,17 +29,18 @@ public class CurriculumCourseService {
curriculumCourseRepo.save(curriculumCourse); curriculumCourseRepo.save(curriculumCourse);
} }
public Iterable<CurriculumCourse> findAll(){
return curriculumCourseRepo.findAll();
}
public Map<String, Object> getDepthCurriculum(Curriculum curriculum){ public Map<String, Object> getDepthCurriculum(Curriculum curriculum){
if (curriculum == null)
return null;
HashMap<String ,Object> toReturn = new HashMap<>(); HashMap<String ,Object> toReturn = new HashMap<>();
ArrayList<Course> courses = new ArrayList<>(); ArrayList<Map<String ,Object>> courses = new ArrayList<>();
for (Course c: curriculumCourseRepo.findCoursesByCurriculum(curriculum)){ Iterable<Course> foundCourses = curriculumCourseRepo.findCoursesByCurriculum(curriculum);
courses.add(c);
for (Course c: foundCourses){
courses.add(ProtectionService.courseWithoutPassword(c));
} }
toReturn.put("courses",courses); toReturn.put("courses",courses);
toReturn.put("curriculumId", curriculum.getCurriculumId()); toReturn.put("curriculumId", curriculum.getCurriculumId());
@ -56,13 +55,39 @@ public class CurriculumCourseService {
ArrayList<Map<String,Object>> toReturn = new ArrayList<>(); ArrayList<Map<String,Object>> toReturn = new ArrayList<>();
for (Curriculum curriculum : curriculumCourseRepo.findDistinctCurriculums()){ for (Curriculum curriculum : curriculumRepo.findAll()){
toReturn.add(getDepthCurriculum(curriculum)); toReturn.add(getDepthCurriculum(curriculum));
} }
return toReturn; return toReturn;
} }
/** tries to add all courses to the curriculum
*
* @param coursesIds the ids of the courses to be added
* @param curriculum the curriculum to add the courses to
* @return if the changes were made
*/
public boolean saveAll(Iterable<Long> coursesIds, Curriculum curriculum) {
if (curriculum == null || coursesIds == null)
return false;
ArrayList<Course> toAdd = new ArrayList<>();
for (Long courseId : coursesIds){
Course course = courseRepo.findById((long) courseId);
if (course == null)
return false;
if (!toAdd.contains(course))
toAdd.add(course);
}
for (Course course : toAdd){
curriculumCourseRepo.save(new CurriculumCourse(curriculum,course));
}
return true;
}
} }

View File

@ -1,7 +1,6 @@
package ovh.herisson.Clyde.Services; package ovh.herisson.Clyde.Services;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.CourseRepository;
import ovh.herisson.Clyde.Repositories.CurriculumRepository; import ovh.herisson.Clyde.Repositories.CurriculumRepository;
import ovh.herisson.Clyde.Tables.Curriculum; import ovh.herisson.Clyde.Tables.Curriculum;
@ -10,23 +9,17 @@ public class CurriculumService {
private final CurriculumRepository curriculumRepo; private final CurriculumRepository curriculumRepo;
private final CourseRepository courseRepo; public CurriculumService(CurriculumRepository curriculumRepo){
public CurriculumService(CurriculumRepository curriculumRepo, CourseRepository courseRepo){
this.curriculumRepo = curriculumRepo; this.curriculumRepo = curriculumRepo;
this.courseRepo = courseRepo;
} }
public Curriculum save(Curriculum curriculum){
return curriculumRepo.save(curriculum);
public void save(Curriculum curriculum){
curriculumRepo.save(curriculum);
} }
public Curriculum findById(long id){ public Curriculum findById(long id){
return curriculumRepo.findById(id); return curriculumRepo.findById(id);
} }
public Iterable<Curriculum> findAll(){ public void delete(Curriculum curriculum) {
return curriculumRepo.findAll(); curriculumRepo.delete(curriculum);
} }
} }

View File

@ -1,21 +1,40 @@
package ovh.herisson.Clyde.Services; package ovh.herisson.Clyde.Services;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.CurriculumRepository;
import ovh.herisson.Clyde.Repositories.InscriptionRepository; import ovh.herisson.Clyde.Repositories.InscriptionRepository;
import ovh.herisson.Clyde.Repositories.UserCurriculumRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
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.User;
import ovh.herisson.Clyde.Tables.UserCurriculum;
@Service @Service
public class InscriptionService { public class InscriptionService {
InscriptionRepository inscriptionRepo; private final InscriptionRepository inscriptionRepo;
public InscriptionService(InscriptionRepository inscriptionRepo){ private final UserRepository userRepo;
private final UserCurriculumRepository userCurriculumRepo;
private final CurriculumRepository curriculumRepo;
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo){
this.inscriptionRepo = inscriptionRepo; this.inscriptionRepo = inscriptionRepo;
this.userRepo = userRepo;
this.userCurriculumRepo = userCurriculumRepo;
this.curriculumRepo = curriculumRepo;
} }
public void save(InscriptionRequest inscriptionRequest){ public InscriptionRequest save(InscriptionRequest inscriptionRequest){
inscriptionRepo.save(inscriptionRequest); inscriptionRequest.setPassword(passwordEncoder.encode(inscriptionRequest.getPassword()));
return inscriptionRepo.save(inscriptionRequest);
} }
public InscriptionRequest getById(long id){ public InscriptionRequest getById(long id){
@ -26,9 +45,50 @@ public class InscriptionService {
return inscriptionRepo.findAll(); return inscriptionRepo.findAll();
} }
public void modifyState(long id, RequestState requestState) { public boolean modifyState(long id, RequestState requestState) {
InscriptionRequest inscriptionRequest = getById(id); InscriptionRequest inscrRequest = getById(id);
inscriptionRequest.setState(requestState);
save(inscriptionRequest); if (inscrRequest == null)
return false;
// if th state is the same we don't send an email
if (requestState == inscrRequest.getState())
return false;
/** todo send an email to tell the poster of the inscrRequest (inscrRequest.getEmail())
* to notify them that the state of their request changed
* FooEmailFormat toSend = (String.format("Your request state changed from %s to %s"),
* inscrRequest.getState(), requestState)
* FooEmailSender.send(toSend, inscrRequest.getEmail())
*/
//saves the user from the request if accepted
if (requestState == RequestState.Accepted)
{
if (curriculumRepo.findById(inscrRequest.getCurriculumId()) == null)
return false;
User userFromRequest = new User(
inscrRequest.getLastName(),
inscrRequest.getFirstName(),
inscrRequest.getEmail(),
inscrRequest.getAddress(),
inscrRequest.getCountry(),
inscrRequest.getBirthDate(),
inscrRequest.getProfilePicture(),
inscrRequest.getPassword()
);
userRepo.save(userFromRequest);
userCurriculumRepo.save(new UserCurriculum(userFromRequest, curriculumRepo.findById(inscrRequest.getCurriculumId())));
}
inscrRequest.setState(requestState);
save(inscrRequest);
return true;
}
public void delete(InscriptionRequest toDelete) {
inscriptionRepo.delete(toDelete);
} }
} }

View File

@ -0,0 +1,105 @@
package ovh.herisson.Clyde.Services;
import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.InscriptionRequest;
import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ProtectionService {
/** return user's data except password
* @param user the user to return
* @return all the user data without the password
*/
public static HashMap<String,Object> userWithoutPassword(User user){
if (user ==null)
return null;
HashMap<String,Object> toReturn = new HashMap<>();
toReturn.put("regNo",user.getRegNo());
toReturn.put("lastName",user.getLastName());
toReturn.put("firstName",user.getFirstName());
toReturn.put("email", user.getEmail());
toReturn.put("address",user.getAddress());
toReturn.put("birthDate",user.getBirthDate());
toReturn.put("country",user.getCountry());
toReturn.put("profilePictureUrl",user.getProfilePictureUrl());
toReturn.put("role",user.getRole());
return toReturn;
}
public static Iterable<HashMap<String ,Object>>usersWithoutPasswords(Iterable<User> users){
ArrayList<HashMap<String,Object>> toReturn = new ArrayList<>();
for (User u : users){
toReturn.add(userWithoutPassword(u));
}
return toReturn;
}
public static HashMap<String,Object> courseWithoutPassword(Course course){
if (course == null)
return null;
HashMap<String ,Object> toReturn = new HashMap<>();
toReturn.put("courseId",course.getCourseID());
toReturn.put("credits",course.getCredits());
toReturn.put("title", course.getTitle());
toReturn.put("owner", userWithoutPassword(course.getOwner()));
return toReturn;
}
public static Iterable<HashMap<String ,Object>> coursesWithoutPasswords(Iterable<Course> courses){
ArrayList<HashMap<String,Object>> toReturn = new ArrayList<>();
for (Course course: courses){
toReturn.add(ProtectionService.courseWithoutPassword(course));
}
return toReturn;
}
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;
@ -35,6 +33,9 @@ public class StorageService {
public StorageFile store(MultipartFile file, FileType fileType) { public StorageFile store(MultipartFile file, FileType fileType) {
if (file == null || file.getOriginalFilename() == null)
return null;
if (file.getOriginalFilename().isEmpty()){return null;} if (file.getOriginalFilename().isEmpty()){return null;}
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
@ -55,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,53 @@
package ovh.herisson.Clyde.Services;
import org.springframework.stereotype.Controller;
import ovh.herisson.Clyde.Repositories.TeacherCourseRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.TeacherCourse;
import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList;
@Controller
public class TeacherCourseService {
private final TeacherCourseRepository teacherCourseRepo;
private final UserRepository userRepo;
public TeacherCourseService(TeacherCourseRepository teacherCourseRepo, UserRepository userRepo) {
this.teacherCourseRepo = teacherCourseRepo;
this.userRepo = userRepo;
}
public Iterable<User> findCourseAssistants(Course course) {
if (course == null)
return null;
return teacherCourseRepo.findAllAssistantOfCourse(course);
}
public boolean saveAll(Iterable<Long> teacherIds, Course course){
if (course == null || teacherIds == null)
return false;
ArrayList<User> toAdd = new ArrayList<>();
for (Long teacherId : teacherIds){
User teacher = userRepo.findById((long) teacherId);
if ( teacher== null){
return false;
}
if (!toAdd.contains(teacher) && teacher.getRole() == Role.Teacher)
{
toAdd.add(teacher);
}
}
for (User teacher: toAdd){
teacherCourseRepo.save(new TeacherCourse(teacher,course));
}
return true;
}
}

View File

@ -40,16 +40,19 @@ public class TokenService {
public User getUserFromToken(String token) { public User getUserFromToken(String token) {
Token tokenRep = tokenRepo.getByToken(token); Token tokenRep = tokenRepo.getByToken(token);
if (tokenRep == null) return null; if (tokenRep == null)
return null;
return tokenRep.getUser(); return tokenRep.getUser();
} }
public void saveToken(Token token){ public void saveToken(Token token){
//Si l'utilisateur a déja 5 token delete celui qui devait expirer le plus vite //Si l'utilisateur a déja 5 token delete celui qui devait expirer le plus vite
ArrayList<Token> tokenList = tokenRepo.getByUserOrderByExpirationDate(token.getUser()); ArrayList<Token> tokenList = tokenRepo.getByUserOrderByExpirationDate(token.getUser());
while(tokenList.size() >= 5){ while(tokenList.size() >= 5){
tokenRepo.delete(tokenList.get(0)); tokenRepo.delete(tokenList.getFirst());
tokenList.remove(tokenList.get(0)); tokenList.remove(tokenList.getFirst());
} }
tokenRepo.save(token); tokenRepo.save(token);
} }
@ -67,5 +70,5 @@ public class TokenService {
tokenRepo.delete(t); tokenRepo.delete(t);
} }
} }
}; }
} }

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

@ -17,8 +17,15 @@ public class UserService {
} }
/** return the user identified by th identifier
*
* @param identifier can be an email or the RegNo
* @return the identified user
*/
public User getUser(String identifier){ public User getUser(String identifier){
if (identifier == null) return null; if (identifier == null)
return null;
try { try {
int id = Integer.parseInt(identifier); int id = Integer.parseInt(identifier);
return userRepo.findById(id); return userRepo.findById(id);
@ -33,16 +40,18 @@ public class UserService {
* *
* @param poster the user wanting to modify target's data * @param poster the user wanting to modify target's data
* @param updates the changes to be made * @param updates the changes to be made
* @param target the user to update * @param targetId the id of the user to update
* @return if the changes were done or not * @return if the changes were done or not
*/ */
public boolean modifyData(User poster, Map<String ,Object> updates, User target){ public boolean modifyData(long targetId, Map<String ,Object> updates, User poster){
User target = userRepo.findById(targetId);
if (target == null)
return false;
if (poster.getRegNo().equals(target.getRegNo())){ if (poster.getRegNo().equals(target.getRegNo())){
for (Map.Entry<String, Object> entry : updates.entrySet()){ for (Map.Entry<String, Object> entry : updates.entrySet()){
if ( entry.getKey().equals("regNo") || entry.getKey().equals("role")) {return false;}
switch (entry.getKey()){ switch (entry.getKey()){
case "firstName": case "firstName":
target.setFirstName((String) entry.getValue()); target.setFirstName((String) entry.getValue());
@ -78,15 +87,16 @@ public class UserService {
{ {
for (Map.Entry<String, Object> entry : updates.entrySet()){ for (Map.Entry<String, Object> entry : updates.entrySet()){
if ( !entry.getKey().equals("role")) {return false;} if ( entry.getKey().equals("role")) {
if (entry.getValue() == Role.Admin){return false;} if (entry.getValue() == Role.Admin) {return false;}
target.setRole((Role) entry.getValue()); target.setRole((Role) entry.getValue());
userRepo.save(target); userRepo.save(target);
return true; return true;
} }
} }
}
return false; return false;
} }
@ -95,12 +105,30 @@ public class UserService {
return passwordEncoder.matches(tryingPassword, user.getPassword()); return passwordEncoder.matches(tryingPassword, user.getPassword());
} }
public void save(User user){ public User save(User user){
user.setPassword(passwordEncoder.encode(user.getPassword())); user.setPassword(passwordEncoder.encode(user.getPassword()));
userRepo.save(user); return userRepo.save(user);
} }
public Iterable<User> getAll(){ public Iterable<User> getAll(){
return userRepo.findAll(); return userRepo.findAll();
} }
public Iterable<User> getAllExceptAdmins(){
return userRepo.findAllExceptAdmins();
}
public Iterable<User> getAllTeachers (){return userRepo.findAllTeachers();}
public Iterable<User> getAllStudents(){return userRepo.findAllStudents();}
public User getUserById(long id) {
return userRepo.findById(id);
}
public void delete(User user) {
userRepo.delete(user);
}
} }

View File

@ -15,7 +15,9 @@ public enum Applications {
// teachers and Secretary authorization // teachers and Secretary authorization
ManageCourses, ManageCourses,
UsersList,
// InscriptionService authorization // InscriptionService authorization
Inscription Inscription,
StudentsList
} }

View File

@ -1,9 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.Entity; import jakarta.persistence.*;
import jakarta.persistence.GeneratedValue; import org.hibernate.annotations.OnDelete;
import jakarta.persistence.GenerationType; import org.hibernate.annotations.OnDeleteAction;
import jakarta.persistence.Id;
@Entity @Entity
public class Course { public class Course {
@ -12,12 +11,16 @@ public class Course {
private int courseID; private int courseID;
private int credits; private int credits;
private String title; private String title;
private String faculty;
public Course(int credits, String title, String faculty){ @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.SET_NULL)
@JoinColumn(name = "Users")
private User owner;
public Course(int credits, String title, User owner){
this.credits = credits; this.credits = credits;
this.title = title; this.title = title;
this.faculty = faculty; this.owner = owner;
} }
public Course() {} public Course() {}
@ -34,14 +37,6 @@ public class Course {
this.credits = credits; this.credits = credits;
} }
public String getFaculty() {
return faculty;
}
public void setFaculty(String faculty){
this.faculty = faculty;
}
public String getTitle() { public String getTitle() {
return title; return title;
} }
@ -49,4 +44,12 @@ public class Course {
public void setTitle(String title){ public void setTitle(String title){
this.title = title; this.title = title;
} }
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = 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,7 +1,6 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.Date; import java.util.Date;
@ -17,21 +16,20 @@ public class InscriptionRequest {
private String country; private String country;
private Date birthDate; private Date birthDate;
@ManyToOne private Long curriculumId;
@JoinColumn(name="Curriculum")
private Curriculum curriculum;
private RequestState state; private RequestState state;
private String profilePicture; private String profilePicture;
private String password; private String password;
public InscriptionRequest(){} public InscriptionRequest(){}
public InscriptionRequest(String lastName, String firstName, String address, String email, String country, Date birthDate, RequestState state, String profilePicture, String password){ public InscriptionRequest(String lastName, String firstName, String address, String email, String country, Date birthDate,Long curriculumId, RequestState state, String profilePicture, String password){
this.lastName = lastName; this.lastName = lastName;
this.firstName = firstName; this.firstName = firstName;
this.address = address; this.address = address;
this.email = email; this.email = email;
this.country = country; this.country = country;
this.birthDate = birthDate; this.birthDate = birthDate;
this.curriculumId = curriculumId;
this.state = state; this.state = state;
this.profilePicture = profilePicture; this.profilePicture = profilePicture;
this.password = password; this.password = password;
@ -89,12 +87,12 @@ public class InscriptionRequest {
this.birthDate = birthDate; this.birthDate = birthDate;
} }
public Curriculum getCurriculum() { public long getCurriculumId() {
return curriculum; return curriculumId;
} }
public void setCurriculum(Curriculum curriculum) { public void setCurriculumId(long curriculum) {
this.curriculum = curriculum; this.curriculumId = curriculum;
} }
public RequestState getState() { public RequestState getState() {
@ -112,4 +110,12 @@ public class InscriptionRequest {
public void setProfilePicture(String profilePicture) { public void setProfilePicture(String profilePicture) {
this.profilePicture = profilePicture; this.profilePicture = profilePicture;
} }
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
} }

View File

@ -1,19 +1,23 @@
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 {
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
private int id; private int id;
@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;
@ -21,16 +25,16 @@ public class ReinscriptionRequest {
//Pour la réinscription on va le mettre a 0 //Pour la réinscription on va le mettre a 0
private boolean type = false; private boolean type = false;
public ReinscriptionRequest(){} public ReInscriptionRequest(){}
public ReinscriptionRequest(User user, Curriculum newCurriculum, RequestState state, boolean type){ public ReInscriptionRequest(User user, Curriculum newCurriculum, RequestState state, boolean type){
this.user = user; this.user = user;
this.newCurriculum = newCurriculum; this.newCurriculum = newCurriculum;
this.state = state; this.state = state;
this.type = type; this.type = type;
} }
public ReinscriptionRequest(User user, Curriculum newCurriculum, RequestState state){ public ReInscriptionRequest(User user, Curriculum newCurriculum, RequestState state){
this.user = user; this.user = user;
this.newCurriculum = newCurriculum; this.newCurriculum = newCurriculum;
this.state = state; this.state = state;

View File

@ -24,7 +24,6 @@ public class StorageFile {
public StorageFile(){} public StorageFile(){}
public void setId(Long id) { public void setId(Long id) {
this.id = id; this.id = id;
} }

View File

@ -1,32 +1,32 @@
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 TeacherGivenCourse { public class TeacherCourse {
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
private int id; private int id;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "Users") @JoinColumn(name = "Users")
private User user; private User user;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "Course") @JoinColumn(name = "Course")
private Course course; private Course course;
//This flag helps make the difference between an assistant or a Teacher (who owns the course) public TeacherCourse(User user, Course course){
private boolean owned;
public TeacherGivenCourse(User user, Course course, boolean owned){
this.user = user; this.user = user;
this.course = course; this.course = course;
this.owned = owned;
} }
public TeacherGivenCourse() {} public TeacherCourse() {}
public int getId() { public int getId() {
return id; return id;
@ -48,11 +48,4 @@ public class TeacherGivenCourse {
this.course = course; this.course = course;
} }
public boolean isOwned() {
return owned;
}
public void setOwned(boolean owned) {
this.owned = owned;
}
} }

View File

@ -1,8 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.springframework.scheduling.annotation.Scheduled; import org.hibernate.annotations.OnDelete;
import ovh.herisson.Clyde.Repositories.TokenRepository; import org.hibernate.annotations.OnDeleteAction;
import java.util.Date; import java.util.Date;
@ -13,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,11 +1,8 @@
package ovh.herisson.Clyde.Tables; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.Date; import java.util.Date;
//Classe représentant un utilisateur l'attribut password demande surement un peu de rafinement niveau sécurité
//et l'attribut tokenApi doit encore être ajouté vu qu'il faut en discuter
@Entity @Entity
@Table(name = "Users") @Table(name = "Users")
@ -37,18 +34,6 @@ public class User {
this.password = password; this.password = password;
} }
/** Constructor for the first registration request from a student (can't specify a Role)
*
* @param lastName
* @param firstName
* @param email
* @param address
* @param country
* @param birthDate
* @param profilePictureUrl
* @param password
*/
public User(String lastName, String firstName, String email, String address, public User(String lastName, String firstName, String email, String address,
String country, Date birthDate, String profilePictureUrl, String password) String country, Date birthDate, String profilePictureUrl, String password)
{ {
@ -95,8 +80,8 @@ public class User {
return address; return address;
} }
public void setAddress(String adress) { public void setAddress(String address) {
this.address = adress; this.address = address;
} }
public String getCountry() { public String getCountry() {

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

@ -8,6 +8,7 @@
"name": "clyde", "name": "clyde",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@canvasjs/vue-charts": "^1.0.4",
"vite-plugin-top-level-await": "^1.4.1", "vite-plugin-top-level-await": "^1.4.1",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue3-toastify": "^0.2.1" "vue3-toastify": "^0.2.1"
@ -29,6 +30,20 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/@canvasjs/charts": {
"version": "3.7.45",
"resolved": "https://registry.npmjs.org/@canvasjs/charts/-/charts-3.7.45.tgz",
"integrity": "sha512-FPMX8wn+PEHzAa/GLBsL5lWB81AzKZLw51t7SiSUjMbtUN5/OIrmDcwUTw+53/Bbdd9gm2LLmxAdZsQ75JI31g=="
},
"node_modules/@canvasjs/vue-charts": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@canvasjs/vue-charts/-/vue-charts-1.0.4.tgz",
"integrity": "sha512-PzOA8xeb/f68a39uoFZNn843dGPU36bsqmbO5DWjP7k6FwkK5AeGkYa/H3RHC02Xc6mG68vg9aFNj2Fyqhu4UQ==",
"dependencies": {
"@canvasjs/charts": "^3.7.5",
"vue": ">=3.0.0"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.19.12", "version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",

View File

@ -9,6 +9,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@canvasjs/vue-charts": "^1.0.4",
"vite-plugin-top-level-await": "^1.4.1", "vite-plugin-top-level-await": "^1.4.1",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue3-toastify": "^0.2.1" "vue3-toastify": "^0.2.1"

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -26,6 +26,8 @@ app.inscription.requests=Inscription Requests
app.manage.courses=Manage Courses app.manage.courses=Manage Courses
app.language=Language app.language=Language
app.manage.profile=Manage profile app.manage.profile=Manage profile
app.studentList=Students List
app.users=Users
request.moreInfos=More Infos request.moreInfos=More Infos
request.accept=Accept request.accept=Accept
request.refuse=Refuse request.refuse=Refuse
@ -41,10 +43,12 @@ profile.unRegister=Unregister
profile.course.list=Courses list profile.course.list=Courses list
profile.address=Address profile.address=Address
profile.picture=Profile picture profile.picture=Profile picture
profile.change.curriculum=Change curriculum
name=Name name=Name
teacher=Teacher Teacher=Teacher
student=Student Student=Student
secretary=Secretary Secretary=Secretary
curriculum=curriculum Curriculum=curriculum
credits=Credits Credits=Credits
InscriptionService=I.S.
faculty=Faculty faculty=Faculty

View File

@ -26,6 +26,8 @@ app.inscription.requests=Demandes d'Inscription
app.manage.courses=Gérer les cours app.manage.courses=Gérer les cours
app.language=Langue app.language=Langue
app.manage.profile=Gérer le profil app.manage.profile=Gérer le profil
app.studentList=Liste des étudiants
app.users=Utilisateurs
request.moreInfos=Plus d'Infos request.moreInfos=Plus d'Infos
request.accept=Accepter request.accept=Accepter
request.refuse=Refuser request.refuse=Refuser
@ -41,10 +43,12 @@ profile.unRegister=Désinscription
profile.course.list=Liste des cours profile.course.list=Liste des cours
profile.address=Adresse profile.address=Adresse
profile.picture=Photo de profil profile.picture=Photo de profil
profile.change.curriculum=Changer cursus
name=Nom name=Nom
teacher=Enseignant Teacher=Enseignant
student=Etudiant Student=Etudiant
secretary=Secrétaire Secretary=Secrétaire
curriculum=Cursus Curriculum=Cursus
credits=Credits Credits=Credits
InscriptionService=S.I.
faculty=Faculté faculty=Faculté

View File

@ -1,37 +1,34 @@
<script setup> <script setup>
import { toast } from 'vue3-toastify'; import { toast } from 'vue3-toastify';
import { ref, computed } from 'vue' import { ref } from 'vue'
import i18n, { setLang } from './i18n.js' import i18n, { setLang } from './i18n.js'
import { isLogged } from '@/rest/Users.js'
import { appList, currentView } from '@/rest/apps.js'
var prevURL;
var currentURL = window.location.hash;
// Liste des apps window.onhashchange = function() {
import LoginPage from './Apps/Login.vue' prevURL = currentURL;
import Inscription from "./Apps/Inscription.vue" currentURL = window.location.hash;
import Profil from "./Apps/Profil.vue" }
import Courses from "./Apps/ManageCourses.vue" const Logged = ref(isLogged());
const apps = { window.addEventListener('hashchange', () => {
'/login': LoginPage, if((location.hash === "#/home" && prevURL === "#/login") || (location.hash === "#/home" && prevURL === "#/profil")){
'/inscription': Inscription, window.location.reload();
'/profil': Profil,
'/manage-courses' : Courses,
} }
const currentPath = ref(window.location.hash) });
window.addEventListener('hashchange', () => {
currentPath.value = window.location.hash
})
const currentView = computed(() => {
return apps[currentPath.value.slice(1) || '/']
})
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 apps = ref([])
appList().then(e => apps.value = e)
</script> </script>
<template> <template>
@ -41,7 +38,7 @@
<ul class="horizontal"> <ul class="horizontal">
<li title=home> <li title=home>
<a class="icon" href="#home"> <a class="icon" href="#home">
<img class="clyde" src="./assets/Clyde.png" style="width: 40px; height: auto; margin-top:4px"> <img class="clyde" src="/Clyde.png" style="width: 40px; height: auto; margin-top:4px">
</a></li> </a></li>
<li title=home> <li title=home>
<a class="icon" href="#home"> <a class="icon" href="#home">
@ -49,7 +46,7 @@
</a></li> </a></li>
<li style="float: right;" title=login> <li style="float: right;" title=login>
<a class="icon" href="#/login"> <a class="icon" href="#/login">
<div class="fa-solid fa-user" style="margin-top: 7px; margin-bottom: 3px;"></div> <div class="fa-solid fa-user" :style="Logged ? 'color: orange' : 'haha'" style="margin-top: 7px; margin-bottom: 3px; "></div>
</a></li> </a></li>
<li style="float: right;" title=notifications> <li style="float: right;" title=notifications>
<a class="icon" href="#Notifications"> <a class="icon" href="#Notifications">
@ -80,38 +77,18 @@
<div class="leftBar"> <div class="leftBar">
<ul class="vertical"> <ul class="vertical">
<li style="margin-top: 25px;" > <li v-for="app in apps">
<a href="#Messages"> <a :href="app.path">
<div class="fa-solid fa-comment" style="font-size: 40px;"></div> <div class="fa-solid" :class="app.icon" style="font-size: 40px;"></div>
<div class="text">{{i18n("app.messages")}}</div> <div class="text">{{app.text}}</div>
</a></li> </a>
<li > </li>
<a href="#Notifications">
<div class="fa-solid fa-bell" style="font-size: 40px;" ></div>
<div class="text">{{i18n("app.notifications")}}</div>
</a></li>
<li >
<a href="#Schedule">
<div class="fa-solid fa-calendar-days" style="font-size: 40px;"></div>
<div class="text">{{i18n("app.schedules")}}</div>
</a></li>
<li ><a href="#Forum">
<div class="fa-solid fa-envelope" style="font-size: 40px;" ></div>
<div class="text">{{i18n("app.forum")}}</div></a></li>
<li><a href="#/inscription">
<div class="fa-solid fa-users" style="align-self:center;font-size: 40px;"></div>
<div class="text" style="top:0;">{{i18n("app.inscription.requests")}}</div></a></li>
<li><a href="#/manage-courses">
<div class="fa-solid fa-book" style="align-self:center;font-size: 40px;overflow:none;"></div>
<div class="text">{{i18n("app.manage.courses")}}</div></a></li>
</ul> </ul>
</div> </div>
<div class="page"> <div class="page">
<div style=" margin:50px;"> <Suspense>
<component :is="currentView" /> <component :is="currentView" />
</div> </Suspense>
</div> </div>
</div> </div>
</template> </template>
@ -119,6 +96,8 @@
<style scoped> <style scoped>
.container{ .container{
height: 100%;
width: 100%;
display:grid; display:grid;
grid-template-columns:[firstCol-start]70px[firstCol-end secondCol-start]auto[endCol]; grid-template-columns:[firstCol-start]70px[firstCol-end secondCol-start]auto[endCol];
grid-template-rows:[firstRow-start]61px[firstRow-end secondRow-start] auto [endRow]; grid-template-rows:[firstRow-start]61px[firstRow-end secondRow-start] auto [endRow];
@ -131,6 +110,8 @@
.page { .page {
grid-area:page; grid-area:page;
height: 100%;
width: 100%;
place-self:center; place-self:center;
} }
@ -273,3 +254,5 @@
} }
</style> </style>
<!-- vim:set noet sts=0 sw=4 ts=2: -->

View File

@ -1,10 +1,111 @@
<script setup> <script setup>
import Req from "./Request.vue" import i18n from "@/i18n.js"
import { getRegisters } from '@/rest/ServiceInscription.js' import {ref} from 'vue'
import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js'
const requests_example = getRegisters(); const requests = ref(await getAllRegisters());
console.log(requests);
async function upPage(id,review){
await validateRegister(id,review);
requests.value = await getAllRegisters();
}
</script> </script>
<template> <template>
<Req v-for="item of requests_example"/> <div style='display:flex; justify-content:center; min-width:1140px;' v-for="item of requests">
<div class="bodu" v-if="item.state === 'Pending'">
<div class="container">
<div class="id"><a>{{item.id}}</a></div>
<div class="surname"><a>{{item.lastName}}</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="accept"><button @click="upPage(item.id,'Accepted')" style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</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>
</template> </template>
<style scoped>
.container{
color:white;
height:100px;
font-size:20px;
display:grid;
grid-template-columns:10% 14.2% 19% 14.2% 14.2% 14.2% 14.2%;
grid-template-areas:
"id type surname firstname infos accept refuse";
}
.infos {
grid-area:infos;
align-self:center;
}
.accept{
grid-area:accept;
align-self:center;
}
.refuse{
grid-area:refuse;
align-self:center;
}
.titles {
grid-area:titles;
background-color:rgb(215,215,215);
}
.id{
grid-area:id;
margin-left:40px;
align-self:center;
}
.type{
grid-area:type;
align-self:center;
}
.surname{
grid-area:surname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
.firstname{
grid-area:firstname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
button{
font-size:15px;
height:50px;
width:100px;
border:none;
border-radius:20px;
}
.bodu {
margin-top:2%;
width:66%;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -1,83 +1,115 @@
<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 } from '@/rest/Users.js' import { login , register , disconnect, isLogged} from '@/rest/Users.js'
import { getAllCurriculums } from '@/rest/curriculum.js'
import { uploadProfilePicture } from '@/rest/uploads.js' import { uploadProfilePicture } from '@/rest/uploads.js'
import {toast} from 'vue3-toastify'
import 'vue3-toastify/dist/index.css';
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("")
const curriculum=ref("")
const imageSaved = ref(false) const imageSaved = ref(false)
const ppData = ref(false) const ppData = ref(false)
const curricula= await getAllCurriculums();
function goBackHome(){
setTimeout(() => {
window.location.href="#/home";
}, "500");
}
function verifyInputs(pass){
if(pass==passwordConfirm.value){
page.value++;
return toast('Password and Confirm Password are correct.', {
type: "success",});
}
else{
return toast('Password and Confirm Password are different',{type: "error",});
}
}
if (isLogged()){
disconnect();
window.location.reload();}
</script> </script>
<template> <template>
<div class='loginBox'> <div class="setup">
<div v-if="loginPage"> <div v-if="loginPage">
<form @submit.prevent="login(email, password)"class="form"> <div class='loginBox' style="margin-top:30%;">
<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>
</div> </div>
<div class="inputBox"> <div class="inputBox" style="margin-bottom:35px;">
<input type="submit" v-model="submitValue"> <input type="submit" v-model="submitValue">
</div> </div>
</form> </form>
</div> </div>
</div>
<div v-else> <div v-else>
<form @submit.prevent="register(firstname, surname, birthday, password, mail, address, country, curriculum)" class="form"> <div class='loginBox' style="margin-top:30%; margin-bottom:50%;">
<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")}}
</h1> </h1>
<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>
<input type="password" v-model="passwordConfirm"> <input type="password" v-model="passwordConfirm">
<!-- TODO: Verify password is same as passwordConfirm -->
</div> </div>
<div class="switchpage"> <div class="switchpage">
<button @click="page++">{{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">
@ -87,30 +119,34 @@
<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 class="inputBox"novalidate enctype="multipart/form-data">
<p>ProfilePicture</p> <p>{{i18n("profile.picture").toUpperCase()}}</p>
<label class="browser">
Parcourir . . .
<input type="file" :disabled="imageSaved" @change="ppData = uploadProfilePicture($event.target.files); imageSaved = true;" accept="image/*"> <input type="file" :disabled="imageSaved" @change="ppData = uploadProfilePicture($event.target.files); imageSaved = true;" accept="image/*">
</label>
</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 value="Chemistry">Chemistry</option> <option v-for="item in curricula">{{item.curriculumId}}</option>
<option value="Psycho">Psychology</option>
<option value="IT">IT</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(outputs)">{{i18n("login.guest.submit")}}</button> <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")}}
</button>
</div> </div>
<div class="switchpage"> <div class="switchpage">
<button @click="page--">{{i18n("login.guest.lastpage")}}</button> <button @click="page--">{{i18n("login.guest.lastpage")}}</button>
@ -122,34 +158,25 @@
</form> </form>
</div> </div>
</div> </div>
</div>
</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{ .setup {
width:40px; margin-left: auto;
background-color: black; margin-right:auto;
border-radius:6px; min-width:400px;
color:white;
transform: translate(0px ,1px);
}
width:25%;
height:60%;
}
.loginBox { .loginBox {
background-color: rgb(24,24,24); background-color: rgb(24,24,24);
width: 400px;
display:flex; display:flex;
justify-content: center; justify-content: center;
padding: 40px; border-radius: 5%;
border-radius: 20px;
box-shadow:0 5px 25px #000000; box-shadow:0 5px 25px #000000;
} }
@ -158,9 +185,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%;
} }
@ -168,12 +194,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;
} }
@ -188,8 +214,9 @@
.register{ .register{
color:rgb(239,60,168); color:rgb(239,60,168);
width: 100%; width:70%;
display:flex; margin-bottom:20px;
margin-top:20px;
cursor: pointer; cursor: pointer;
} }
@ -218,6 +245,21 @@ input[type=submit],button,select{
} }
input[type=file]{
display:none;
}
.browser{
display:inline-block;
cursor:pointer;
border-radius:20px;
background-color:rgb(239,60,168);
padding:5%;
font-size:1.35em;
font-family:sans-serif;
background:#FFFFFF;
}
button:active ,.switchpage:active{ button:active ,.switchpage:active{
opacity:0.8; opacity:0.8;

View File

@ -1,100 +1,103 @@
<script setup> <script setup>
import i18n from "@/i18n.js" import i18n from "@/i18n.js"
import {ref} from 'vue' import {reactive , ref} from 'vue'
const curriculum=[ import { getCourses,deleteCourse,alterCourse,createCourse } from "@/rest/courses.js"
{ import {getUser, getSelf, getTeachers } from "@/rest/Users.js"
"id": 12,
"name": "Math pour l'info",
"credits": 11,
"faculty": "science",
"teacher": 42,
"Assistants": []},
{
"id": 42,
"name": "Operating Systems",
"credits": 8,
"faculty": "science",
"teacher": 62,
"Assistants": []},
{
"id": 52,
"name": "Fonctionnement des ordinateurs",
"credits": 11,
"faculty": "science",
"teacher": 59,
"Assistants": []},
]
const profList=[42,45,62,84,59] const self = await getSelf();
const curriculum = ref(await getCourses(self.role));
const profList = await getTeachers();
const createMod = ref(false) const createMod = ref(false)
const deleteMod = ref(false) const deleteMod = ref(false)
const editElementID = ref(""); const editElementID = ref("")
function editItem(id){ function editItem(id){
editElementID = id; editElementID = id;
} }
//Juste pour montrer le Create Mode //Juste pour montrer le Create Mode
const pattern = { const pattern = {
"title":null,
"credits":null,
"owner":null,
}
"id": 0, let toModify = Object.assign({},pattern);
"name": null,
"credits": null,
"faculty": null,
"teacher": null,
"Assistants": []}
let toAdd = Object.assign({}, pattern); let toAdd = Object.assign({}, pattern);
function addToCourse (){ async function addToCourse(){
if (curriculum.length>0){
toAdd.id=(curriculum[curriculum.length-1].id)-1;}
else{
toAdd.id=0;
}
let isnull= false; let isnull= false;
for(const [key, value] of Object.entries(toAdd)){ for(const [key, value] of Object.entries(toAdd)){
console.log(toAdd.owner);
if(value === null){ if(value === null){
isnull=true; isnull=true;
} }
} }
if (!isnull){ if (!isnull){
curriculum.push(toAdd); 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){
for(const el in profList){
if(profList[el].regNo === item.owner.regNo){
toModify.owner= profList[el];
}
}
toModify.credits= item.credits;
toModify.title= item.title;
} }
async function patchCourse(course){
for (let element in toModify){
console.log(toModify,1)
console.log(toModify[element],2)
if (element =="owner" && (toModify[element].regNo != course.owner.regNo)){
await alterCourse(course.courseId,{owner:toModify[element].regNo});
}
else if(element == "title" && (toModify[element] != course.title)){
await alterCourse(course.courseId,{title:toModify[element]});
}
else if(element == "credits" && (parseInt(toModify[element]) != course.credits)){
await alterCourse(course.courseId,{credits:parseInt(toModify[element])});
}
}
toModify= Object.assign({},pattern);
curriculum.value = await getCourses(self.role);
}
//Juste pour montrer le Delete Mode //Juste pour montrer le Delete Mode
let toRemove; let toRemove = null;
function removeCourse() { async function removeCourse(course) {
console.log("ok");
console.log(toRemove); await deleteCourse(course.courseId)
let rem=-1; curriculum.value = await getCourses(self.role);
for(const [key, value] of Object.entries(curriculum)){ toRemove = null;
console.log(key); }
console.log(value)
if(value.name === toRemove){
rem = key;
break;
}
}
console.log(rem)
if (rem > -1){
curriculum.splice(rem, 1);}
console.log(curriculum);
}
</script> </script>
<template> <template>
<div class="body"> <div class="body">
<div v-if="!deleteMod && !createMod" 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" >
@ -102,71 +105,66 @@ const curriculum=[
</button> </button>
</div> </div>
<div v-if="createMod"> <div v-if="createMod">
<form class="listElement"> <form class="listElement" style="width:40%;margin-right:auto;margin-left:auto;">
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
{{i18n("name")}} : {{i18n("name")}} :
<input v-model="toAdd.name"> <input v-model="toAdd.title">
</div> </div>
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
{{i18n("teacher")}} : {{i18n("Teacher")}} :
<select style="max-width:200px;" class="teacher" v-model="toAdd.teacher"> <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;">
{{i18n("credits")}} : {{i18n("Credits")}} :
<input v-model="toAdd.credits"> <input v-model="toAdd.credits">
</div> </div>
<div style="margin-bottom:20px;">
{{i18n("faculty")}} :
<input v-model="toAdd.faculty">
</div>
<button class="create" @click="createMod=!createMod; addToCourse();"> {{i18n("courses.confirm")}} </button> <button class="create" @click="createMod=!createMod; addToCourse();"> {{i18n("courses.confirm")}} </button>
<button style="float:right;" @click="createMod=!createMod">{{i18n("courses.back")}}</button> <button style="float:right;" @click="createMod=!createMod">{{i18n("courses.back")}}</button>
</form> </form>
</div> </div>
<div v-if="deleteMod"> <div v-if="deleteMod">
<form class="listElement"> <form class="listElement" style="width:40%;margin-right:auto;margin-left:auto;">
<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.name}}</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();"> {{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>
<div v-if="!createMod && !deleteMod" v-for="item in curriculum" :key="item.name"> <div v-if="!createMod && !deleteMod" v-for="item in curriculum" :key="item.title" style="width:50%;margin-left:auto; margin-right:auto;">
<div style ="padding:15px 15px 15px 15px;"> <div v-if="editElementID !== item.title" style ="padding:15px 15px 15px 15px;">
<button v-if="editElementID !== item.name" @click="editElementID = item.name"> <button @click="editElementID = item.title; setModify(item); ">
{{i18n("courses.modify")}} {{i18n("courses.modify")}}
</button> </button>
<button v-else @click="editElementID= ''"> {{i18n("courses.confirm")}} </button> </div>
<div v-else>
<button @click="editElementID= '';patchCourse(item)"> {{i18n("courses.confirm")}} </button>
<button @click="editElementID= '';"> {{i18n("courses.back")}} </button>
</div> </div>
<div class="listElement" > <div class="listElement" >
<div class="containerElement" v-if="editElementID !== item.name" >
<div class="name"> {{item.name}} </div> <div class="containerElement" v-if="editElementID !== item.title" >
<div class="teacher">{{item.teacher}}</div>
<div class="credits">{{i18n("credits")}}:{{item.credits}}</div> <div class="name"> {{item.title}} </div>
<div class="teacher">{{item.owner.lastName}}</div>
<div class="credits">{{i18n("Credits")}}:{{item.credits}}</div>
</div> </div>
<div class="containerElement"v-else> <div class="containerElement"v-else>
<input style="max-width:200px;" class="name" v-model="item.name"> <input style="max-width:200px;" class="name" v-model="toModify.title">
<select style="max-width:200px;" class="teacher" v-model="item.teacher"> <select v-if="self.role === 'Secretary'" style="max-width:200px;" class="teacher" v-model="toModify.owner">
<option v-for="item in profList">{{item}}</option> <option v-for="(item,index) in profList" :value='item'>{{item.lastName}}</option>
</select> </select>
<input style="max-width:100px;"class="credits" v-model="item.credits"> <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">
<div v-else class="credits">{{i18n("Credits")}}:{{item.credits}}</div>
</div> </div>
</div> </div>
</div> </div>
@ -176,17 +174,27 @@ const curriculum=[
<style scoped> <style scoped>
.body { .body {
width:100%; width:100%;
margin-bottom:10px; margin-top:3.5%;
} }
.infosContainer {
min-width:350px;
padding-bottom:50px;
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;
}
.containerElement{ .containerElement{
justify-content:center; justify-content:center;
display:grid; display:grid;
grid-template-columns:350px 350px 200px; grid-template-columns:38.8% 38.8% 22.4%;
grid-template-areas: grid-template-areas:
"name teacher credits"; "name teacher credits";
column-gap:10px; column-gap:10px; }
}
.name { .name {
grid-area:name; grid-area:name;
@ -204,6 +212,7 @@ const curriculum=[
} }
.listElement{ .listElement{
min-width:625px;
border:2px solid black; border:2px solid black;
font-size:25px; font-size:25px;
color:white; color:white;
@ -211,6 +220,7 @@ const curriculum=[
background-color:rgb(50,50,50); background-color:rgb(50,50,50);
border-radius:20px; border-radius:20px;
margin-bottom:10px; margin-bottom:10px;
} }
.modify{ .modify{
@ -259,10 +269,11 @@ const curriculum=[
} }
.listTitle{ .listTitle{
min-width:380px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width:400px; width:25%;
margin-left:auto; margin-left:auto;
margin-right:auto; margin-right:auto;
border:2px solid black; border:2px solid black;
@ -270,7 +281,8 @@ const curriculum=[
color:white; color:white;
padding:20px; padding:20px;
background-color:rgb(50,50,50); background-color:rgb(50,50,50);
border-radius:20px;margin-bottom:10px; border-radius:20px;
margin-bottom:10px;
button:hover{ button:hover{
opacity:0.8; opacity:0.8;

View File

@ -1,108 +1,129 @@
<script setup> <script setup>
import {reactive, ref} from 'vue' import {reactive, ref } from 'vue'
import {getUser} 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'
const user = getUser();
*/
const user =reactive({
profilPicture:"../assets/clyde.png",
lastName:"Ghost",
firstName:"Clyde",
role:"student",
address: "Radiator Springs",
email:"ClydeGhost@gmail.com",
curriculum:[
{
"id": 12,
"name": "Math pour l'info",
"credits": 11,
"faculty": "science",
"teacher": 42,
"Assistants": []},
{
"id": 42,
"name": "Fonctionnement des ordinateurs",
"credits": 11,
"faculty": "science",
"teacher": 42,
"Assistants": []},
], const user = ref(await getSelf());
option:"IT", const UserCurriculum = ref("");
degree:"BAC1", const curricula = ref (await getAllCurriculums());
password:"CeciEstUnMotDePasse123", if(user.value.role === "Student"){
}) UserCurriculum.value = await getSelfCurriculum();
}
/* if(user.role === "Teacher"){
Teacher user UserCurriculum.value = await getCourses("Teacher");
const user =reactive({ }
profilPicture:"../assets/clyde.png", const modif = ref(false);
lastName:"Ghost", const curric = ref(false);
firstName:"Clyde", const reg = ref(false);
role:"teacher",
address: "Radiator Springs",
email:"ClydeGhost@gmail.com",
coursesOwned:[
{
"id": 12,
"name": "Math pour l'info",
"faculty": "science",
"teacher": 42,
"Assistants": []},
{
"id": 42,
"name": "Fonctionnement des ordinateurs",
"credits": 11,
"faculty": "science",
"teacher": 42,
"Assistants": []},
], const pattern = {
faculty:"Science", profilPictureUrl:null,
})*/ email:null,
address:null,
password:null,
};
const modif = ref(false); const patternInfos ={
email: null,
password: null,
passwordConfirm:null,
id:null,
}
const toModify = Object.assign({}, user);
let toModify= Object.assign({}, pattern);
let personnalInfos = Object.assign({}, patternInfos);
function resetInputs(inputs,list){
inputs=Object.assign({},list);
}
async function ChangeInfos(){
for (let element in toModify){
if (element =="email" && (toModify[element] !== null)){
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);
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(){
if(user.value.profilePictureUrl === null){
return "/Clyde.png"
}
return user.profilePictureUrl
}
</script> </script>
<template> <template>
<div class="body"> <div class="body">
<div class="container"> <div class="container">
<div class="profilPic"> <div class="profilPic">
<img class="subContainter" src="../assets/Clyde.png"> <img class="subContainter" :src=getPP()>
</div> </div>
<div class="globalInfos"> <div class="globalInfos">
<div v-if="modif==false" class="infosContainer" > <div v-if="modif==false && curric==false && reg==false " class="infosContainer" >
<div> <div>
{{user.firstName}} {{user.lastName.toUpperCase()}} {{user.firstName}} {{user.lastName}}
</div> </div>
<div> <div>
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).toUpperCase()}} {{user.option}} {{i18n(user.role)}}
</div> </div>
<div v-else> <div v-else>
{{i18n("faculty")}}: {{user.faculty}} Role: {{i18n((user.role))}}
Role: {{i18n(user.role).toUpperCase()}}
</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>{{i18n("profile.reRegister")}}</button> <button @click="reg=!reg">{{i18n("profile.reRegister")}}</button>
<button 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 v-if="(user.role==='Student')">
<button @click="curric=!curric">{{i18n("profile.change.curriculum")}}</button>
</div> </div>
</div> </div>
<div v-else class="infosContainer"> <div v-else-if="modif" class="infosContainer">
<div> <div>
{{i18n("profile.picture")}}: {{i18n("profile.picture")}}:
<input type="file"> <input type="file" @change="user.profilPicture = uploadProfilePicture($event.target.files);" accept="image/*">
</div> </div>
<div> <div>
E-mail: E-mail:
@ -110,7 +131,42 @@ const toModify = Object.assign({}, user);
</div> </div>
<div> <div>
{{i18n("profile.address")}}: {{i18n("profile.address")}}:
<input type="text" v-model="toModify.address"> <input type="text" v-model="toModify.id">
</div>
<div>
{{i18n("login.password")}}:
<input type="password" v-model="toModify.password">
</div>
<div>
{{i18n("login.cPassword")}}:
<input type="password" v-model="toModify.passwordConfirm">
</div>
<div>
<button @click=" modif=!modif; ChangeInfos();">{{i18n("courses.confirm")}}</button>
<button @click="modif=!modif; resetInputs(toModify,pattern);" style="float:right;">{{i18n("courses.back")}}</button>
</div>
</div>
<div v-else-if="curric" class="infosContainer">
<div style="height:40px;">
{{i18n("Curriculum")}}:
<select v-model="curriculum" >
<option v-for="item in curricula" style="font-size:20px;" :value="item">{{item.option}}</option>
</select>
</div>
<div>
<button @click=" curric=!curric;">{{i18n("courses.confirm")}}</button>
<button @click="curric=!curric; resetInputs(personnalInfos,patternInfos);" style="float:right;">{{i18n("courses.back")}}</button>
</div>
</div>
<div v-else-if="reg" class="infosContainer">
<div>
E-mail:
<input type="mail" v-model="toModify.email" />
</div>
<div>
ID :
<input type="text" v-model="toModify.id">
</div> </div>
<div> <div>
{{i18n("login.password")}}: {{i18n("login.password")}}:
@ -120,22 +176,25 @@ const toModify = Object.assign({}, user);
{{i18n("login.cPassword")}}: {{i18n("login.cPassword")}}:
<input type="password" id="confirm"> <input type="password" id="confirm">
</div> </div>
<div>
<button @click=" modif=!modif">{{i18n("courses.confirm")}}</button>
</div>
</div>
</div>
<div v-if="modif==false"class="moreInfos">
<div v-if="(user.role==='student')"> <div>
<button @click=" reg=!reg;">{{i18n("courses.confirm")}}</button>
<button @click=" reg=!reg; resetInputs(personnalInfos,patternInfos);" style="float:right;">{{i18n("courses.back")}}</button>
</div>
</div>
</div>
<div v-if="modif==false && curric==false && reg==false "class="moreInfos">
<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>
@ -144,18 +203,6 @@ const toModify = Object.assign({}, user);
<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>
</div> </div>
@ -163,18 +210,19 @@ const toModify = Object.assign({}, user);
<style scoped> <style scoped>
.container{ .container{
min-width:675px;
display:grid; display:grid;
grid-template-columns:200px 900px; grid-template-columns:10vw 50vw;
grid-template-rows:200px auto; grid-template-rows:200px auto;
column-gap:30px; column-gap:2.7%;
row-gap:25px; row-gap:45px;
grid-template-areas: grid-template-areas:
"profilPic globalInfos" "profilPic globalInfos"
"minfos minfos"; "minfos minfos";
} }
.profilPic{ .profilPic{
width:100%;
grid-area:profilPic; grid-area:profilPic;
} }
@ -195,13 +243,17 @@ const toModify = Object.assign({}, user);
grid-area:minfos; grid-area:minfos;
} }
.body { .body {
min-width:960px;
width:100%; width:100%;
margin-bottom:10px; display:flex;
align-items:center;
justify-content:center;
margin-top:5%;
} }
.containerElement{ .containerElement{
justify-content:center; justify-content:center;
display:grid; display:grid;
grid-template-columns:350px 350px 200px; grid-template-columns:38.8% 38.8% 22.4%;
grid-template-areas: grid-template-areas:
"name teacher credits"; "name teacher credits";
column-gap:10px; column-gap:10px;
@ -224,10 +276,11 @@ const toModify = Object.assign({}, user);
} }
.listTitle{ .listTitle{
min-width:197px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width:200px; width:8vw;
margin-left:auto; margin-left:auto;
margin-right:auto; margin-right:auto;
border:2px solid black; border:2px solid black;
@ -239,6 +292,7 @@ const toModify = Object.assign({}, user);
} }
.listElement{ .listElement{
min-width:625px;
border:2px solid black; border:2px solid black;
font-size:25px; font-size:25px;
color:white; color:white;
@ -249,6 +303,7 @@ const toModify = Object.assign({}, user);
} }
.infosContainer { .infosContainer {
min-width:350px;
padding-bottom:50px; padding-bottom:50px;
border:2px solid black; border:2px solid black;
font-size:25px; font-size:25px;

View File

@ -1,109 +0,0 @@
<script setup>
import i18n from "@/i18n.js"
const props = defineProps({
id: Number,
type: String,
lastName: String,
firstName: String,
address: String,
country: String,
birthDate: String,
curriculum:String,
degree:String,});
</script>
<template>
<div class="bodu">
<div class="container">
<div class="id"><a>{{id}}</a></div>
<div class="type"><a>{{type}}</a></div>
<div class="surname"><a>{{lastName}}</a></div>
<div class="firstname"><a>{{firstName}}</a></div>
<div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}} </button></div>
<div class="accept"><button style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</button></div>
<div class="refuse"><button style="background-color:rgb(105,0,0);">{{i18n("request.refuse")}}</button></div>
</div>
</div>
</template>
<style scoped>
.container{
color:white;
height:100px;
font-size:20px;
display:grid;
grid-template-columns:[firstCol-start]100px[firstCol-end secondCol-start]150px[secondCol-end thirdCol-start]200px[thirdCol-end fourthCol-start]150px[fourthCol-end]150px[fifthCol-end]150px[sixthCol-end]150px[endCol];
grid-template-areas:
"id type surname firstname infos accept refuse";
column-gap:10px;
}
.infos {
grid-area:infos;
align-self:center;
}
.accept{
grid-area:accept;
align-self:center;
}
.refuse{
grid-area:refuse;
align-self:center;
}
.titles {
grid-area:titles;
background-color:rgb(215,215,215);
}
.id{
grid-area:id;
margin-left:40px;
align-self:center;
}
.type{
grid-area:type;
align-self:center;
}
.surname{
grid-area:surname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
.firstname{
grid-area:firstname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
button{
font-size:15px;
height:50px;
width:100px;
border:none;
border-radius:20px;
}
.bodu {
width:100%;
margin-bottom:10px;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -0,0 +1,236 @@
<!----------------------------------------------------
File: ResearcherProfile.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: Researcher Profile Page containing his articles and his statistics
----------------------------------------------------->
<script setup>
import { ref, reactive } from "vue";
const input = ref("");
const statsOf = ref("");
const statsBy = ref("");
let chart;
const jsonMockViewsByYears= [
{label: "2004", y:4},
{label: "2005", y:99},
{label: "2007", y:555},
{label: "2009", y:22},
{label: "2011", y:1666},
]
function inputKeyUp() {
let filter, ul, li, a, txtValue;
filter = input.value.toUpperCase();
if (document.getElementById("myUL") != null) {
ul = document.getElementById("myUL");
li = ul.getElementsByTagName("li");
// Loop through all list items, and hide those who don't match the search query
for (let i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
txtValue = a.textContent || a.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
}
const options = reactive({
backgroundColor:null,
theme: "light2",
animationEnabled: true,
title: {
fontColor: "white",
text : "please select options",
},
data: [
{
type: "pie",
indexLabel: "{label} (#percent%)",
yValueFormatString: "#,##0",
indexLabelFontColor: "white",
toolTipContent:
"<span style='\"'color: {color};'\"'>{label}</span> {y}(#percent%)",
}]
});
function update(){
options.title = {
fontColor: "white",
text: statsOf.value + " By "+ statsBy.value,
}
if (statsOf.value === "views" && statsBy.value === "years") {
options.data[0].dataPoints = jsonMockViewsByYears;
}
options.title.text = statsOf.value + " By "+ statsBy.value;
chart.render()
}
</script>
<template>
<div id="main">
<div id="profilePicture">
<img src="/Clyde.png" />
</div>
<div id="researcherInfos">
<div class="surrounded">John Doe</div>
<div class="surrounded">Orcid : 12144-2144-12336-B</div>
<div class="surrounded">Email : John.Doe@umons.ac.be</div>
<div class="surrounded">
site :
<a href="http://localhost:5173" style="color: #007aff">here</a>
</div>
<div class="surrounded">Domain : physics, IT</div>
<div id="coAuthorList" class="surrounded">Co-authors list : D</div>
</div>
<div id="stats">
<div class="surrounded">
Stat type :
<select @change="update()" id="stats-select" v-model="statsOf">
<option value="views">Views</option>
<option value="co-authors">Co-authors</option>
<option value="articles">Articles</option>
<option value="language">Languages</option>
</select>
</div>
<div class="surrounded">
Class by:
<select @change="update()" id="classed-select" v-model="statsBy">
<option selected="selected" value="years">Years</option>
<option value="months">Months</option>
<option value="topics">Topics</option>
</select>
</div>
<div id="statsPie">
<CanvasJSChart :options="options" id=chart @chart-ref="c => chart = c "/>
</div>
</div>
<div id="articles">
<input
type="text"
id="search-input"
@keyup="inputKeyUp()"
placeholder="search articles"
v-model="input"
/>
<ul id="myUL">
<li><a href="#">Adele</a></li>
<li><a href="#">Agnes</a></li>
<li><a href="#">Billy</a></li>
<li><a href="#">Bob</a></li>
<li><a href="#">Calvin</a></li>
<li><a href="#">Christina</a></li>
<li><a href="#">Cindy</a></li>
</ul>
</div>
</div>
</template>
<style scoped>
#main {
display: grid;
grid-template-columns: 22% auto;
grid-template-rows: 26% auto;
height: 100%;
width: 100%;
}
#profilePicture {
display: flex;
justify-content: center;
}
#profilePicture img {
align-self: center;
justify-self: center;
width: 60%;
}
#researcherInfos {
display: grid;
grid-template-columns: auto auto auto;
column-gap: 5px;
grid-template-rows: auto auto;
}
.surrounded {
border: 2px solid black;
color: white;
font-size: x-large;
align-self: center;
text-align: center;
background-color: rgba(255, 255, 255, 0.09);
border-radius: 20px;
margin-bottom: 10px;
}
.surrounded select {
margin-top: 2px;
margin-bottom: 2px;
border: 1px solid black;
color: white;
background-color: rgb(255, 255, 255, 0.1);
font-size: large;
align-self: center;
text-align: center;
}
#statsPie {
}
#articles {
background-color: orange;
}
#search-input {
width: 60%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#myUL {
list-style-type: none;
padding: 0;
margin: 0;
}
#myUL li a {
border: 1px solid #ddd;
/* Add a border to all links */
margin-top: -1px;
/* Prevent double borders */
background-color: #f6f6f6;
/* Grey background color */
padding: 12px;
/* Add some padding */
text-decoration: none;
/* Remove default text underline */
font-size: 18px;
/* Increase the font-size */
color: black;
/* Add a black text color */
display: block;
/* Make it into a block element to fill the whole list */
}
#myUL li a:hover:not(.header) {
background-color: #eee;
}
#Chart{
width: "100%";
height: "100%";
}
</style>

View File

@ -0,0 +1,84 @@
<script setup>
import i18n from "@/i18n.js"
import { reactive } from 'vue'
import { getStudents } from '../rest/Users.js'
const users = await getStudents();
</script>
<template style="margin-top:5%;">
<div style="display:flex; justify-content:center; " v-for="item in users">
<div class="bodu">
<div class="container">
<div class="status"><a style="margin-left:30px">{{item.status}}</a></div>
<div class="option"><a>{{item.role}}</a></div>
<div class="surname"><a>{{item.lastName}}</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>
</div>
</div>
</template>
<style scoped>
.container{
color:white;
height:100px;
font-size:30px;
display:grid;
grid-template-columns:21.7% 21.7% 21.7% 21.7% 13.1%;
grid-template-areas:
"status option surname firstname infos";
}
.infos {
grid-area:infos;
align-self:center;
}
.option{
grid-area:option;
align-self:center;
}
.status{
grid-area:status;
align-self:center;
}
.surname{
grid-area:surname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
.firstname{
grid-area:firstname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
button{
font-size:15px;
height:50px;
width:75%;
border:none;
border-radius:20px;
}
.bodu {
margin-top:2%;
width:66%;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -0,0 +1,81 @@
<script setup>
import i18n from "@/i18n.js"
import { reactive } from 'vue'
import { getAllUsers } from '../rest/Users.js'
const users = await getAllUsers();
</script>
<template style="margin-top:5%;">
<div style="display:flex; justify-content:center; min-width:1140px;" v-for="item in users">
<div class="bodu">
<div class="container">
<div class="role"><a style="margin-left:30px">{{i18n(item.role)}}</a></div>
<div class="surname"><a>{{item.lastName}}</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>
</div>
</div>
</template>
<style scoped>
.container{
color:white;
height:100px;
font-size:30px;
display:grid;
grid-template-columns:27.7% 27.7% 27.7% 16.9%;
grid-template-areas:
"role surname firstname infos";
}
.infos {
grid-area:infos;
align-self:center;
}
.role {
grid-area:role;
align-self:center;
}
.surname{
grid-area:surname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
.firstname{
grid-area:firstname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
button{
font-size:15px;
height:50px;
width:75%;
border:none;
border-radius:20px;
}
.bodu {
margin-top:2%;
width:66%;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -1,4 +1,11 @@
body { body {
background-color: rgb(53, 25, 60); background-color: rgb(53, 25, 60);
margin:0; margin:0;
width: 100vw;
height: 100vh;
}
#app {
width: 100%;
height: 100%;
} }

View File

@ -4,5 +4,8 @@ import 'https://kit.fontawesome.com/fb3bbd0a95.js'
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import CanvasJSChart from '@canvasjs/vue-charts';
createApp(App).mount('#app') const app = createApp(App);
app.use(CanvasJSChart);
app.mount('#app');

View File

@ -33,9 +33,13 @@ export async function getRegisters(id){
return restGet("/request/register") return restGet("/request/register")
} }
export async function getAllRegisters(){
return restGet("/requests/register")
}
/** /**
* 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,9 +1,18 @@
import { restGet, restPost } from './restConsumer.js' import { restGet, restPost, restPatch, restDelete} from './restConsumer.js'
import { getCookie, setCookie } from '@/utils.js'
export async function login(user, pass, exp){ export async function login(user, pass, exp){
return restPost("/login", {identifier: user, password: pass, expirationDate: exp}); return restPost("/login", {identifier: user, password: pass, expirationDate: exp});
} }
export function isLogged(){
return getCookie("session_token") != ""
}
export function disconnect(){
setCookie("session_token", ";expires= Thu, 01 Jan 1970 00:00:01 GMT")
}
/** /**
* Register a user (tokenless) * Register a user (tokenless)
* *
@ -17,16 +26,17 @@ export async function login(user, pass, exp){
* @param curriculum * @param curriculum
* @param imageId id of the image in database returned when uploaded * @param imageId id of the image in database returned when uploaded
*/ */
export async function register(firstname, lastname, birthDate, password, email, address, country, curriculum, 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,
curriculum: curriculum curriculumId: curriculumId,
profilePictureUrl: imageId,
}); });
} }
@ -63,7 +73,7 @@ export async function createUser(firstname, lastname, birthDate, email, address,
* if the user is not authenticated. then an empty array should be returned * if the user is not authenticated. then an empty array should be returned
*/ */
export async function getUser(id){ export async function getUser(id){
const endpoint = "/user" + id != null ? "/" + id : ""; const endpoint = "/user/" + id;
return restGet(endpoint); return restGet(endpoint);
} }
@ -93,7 +103,23 @@ export async function getAllUsers(){
return restGet("/users"); return restGet("/users");
} }
/**
* Return the list of teachers
*
* @return a list of teachers
* each elements is of the form
* - id
* - name
* - role
*/
export async function getTeachers(){
return restGet("/teachers")
}
export async function getStudents(){
return restGet("/students")
}
/** /**
* Get informations about yourself * Get informations about yourself
* - RegNo * - RegNo
@ -114,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)
} }

68
frontend/src/rest/apps.js Normal file
View File

@ -0,0 +1,68 @@
import { restGet } from './restConsumer.js'
import { ref, computed } from 'vue'
import i18n from '@/i18n.js'
// Liste des apps
import LoginPage from '@/Apps/Login.vue'
import Inscription from "@/Apps/Inscription.vue"
import Profil from "@/Apps/Profil.vue"
import Courses from "@/Apps/ManageCourses.vue"
import Users from "@/Apps/UsersList.vue"
import Students from "@/Apps/StudentsList.vue"
import ResearcherProfile from "@/Apps/ScientificPublications/ResearcherProfile.vue";
const apps = {
'/login': LoginPage,
'/inscription': Inscription,
'/profil': Profil,
'/manage-courses' : Courses,
'/users-list' : Users,
'/students-list' : Students,
'/researcher-profile' : ResearcherProfile,
}
const appsList = {
'Msg': { path: '#/msg', icon: 'fa-comment', text: i18n("app.messages") },
'Notification': { path: '#/notifs', icon: 'fa-bell', text: i18n("app.notifications") },
'Forum': { path: '#/forum', icon: 'fa-envelope', text: i18n("app.forum") },
'Schedule': { path: '#/schedule', icon: 'fa-calendar-days', text: i18n("app.schedules") },
'Inscription': { path: '#/inscription', icon: 'fa-users', text: i18n("app.inscription.requests") },
'ManageCourses': { path: '#/manage-courses', icon: 'fa-book', text: i18n("app.manage.courses") },
'StudentsList':{ path: '#/students-list',icon: 'fa-users',text: i18n("app.studentList")},
'UsersList':{ path: '#/users-list',icon: 'fa-users',text: i18n("app.users")},
}
const currentPath = ref(window.location.hash)
export const currentView = computed(() => {
return apps[currentPath.value.slice(1) || '/']
})
/**
* Return the list of app accesible by a logged (or not)
* user.
*/
export async function appList(){
let ret = [];
let userAppList = await restGet("/apps");
for (let userapp in userAppList) {
if(appsList[userAppList[userapp]] != null){
ret.push(appsList[userAppList[userapp]])
}
}
return ret;
}
/**
* Check if the specified page is authorized for the
* user
*/
export async function checkPage(page){
return restGet("/apps/" + page)
}
window.addEventListener('hashchange', () => {
currentPath.value = window.location.hash
})
// vim:set noet sts=0 sw=4 ts=2 tw=2:

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, faculty, teacher, assistants){ export async function createCourse(name, credits, owner){
return restPost("/courses", {name: name, credits: credits, faculty: faculty, teacher: teacher, assistants: assistants} ) console.log(owner);
return restPost("/course", {title: name, credits: credits, owner} )
} }
/** /**
@ -34,6 +36,25 @@ export async function getCourse(id){
return restGet("/course/" + id); return restGet("/course/" + id);
} }
/**
* Get the list of courses to display on secretary's option
*
* @return list of courses of the form
* - id
* - name
* - credits
* - facutly
* - teacher
* - Assistants
*/
export async function getCourses(role){
if(role==="Teacher"){
return restGet("/courses/owned")
}
return restGet("/courses")
}
/** /**
* Change the options of a course * Change the options of a course
* *

View File

@ -2,7 +2,7 @@
* curriculum API * curriculum API
*/ */
import { restGet, restPostn, restDelete, restPatch } from './restConsumer.js' import { restGet, restPost, restDelete, restPatch } from './restConsumer.js'
/** /**
* Create a new curriculum (bundle of courses) * Create a new curriculum (bundle of courses)
@ -19,6 +19,10 @@ export async function deletecurriculum(id){
return restDelete("/curriculum/" + id); return restDelete("/curriculum/" + id);
} }
export async function getAllCurriculums(){
return restGet("/curriculums");
}
/** /**
* Get informations on a particular curriculum * Get informations on a particular curriculum
* *
@ -39,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) {
@ -46,7 +46,6 @@ async function _rest(endPoint, config){
pending: config['pending'] != null ? config['pending'] : 'pending', pending: config['pending'] != null ? config['pending'] : 'pending',
error: config['error'] != null ? config['error'] : 'Network Failure...', error: config['error'] != null ? config['error'] : 'Network Failure...',
success: config['success'] != null ? config['success'] : {render(res){ success: config['success'] != null ? config['success'] : {render(res){
console.log(res);
return res.data.ok ? "Success" : "error"; return res.data.ok ? "Success" : "error";
}}, }},
}) })