diff --git a/Documents/JournalDeBord/authentification.md b/Documents/JournalDeBord/authentification.md new file mode 100644 index 0000000..bd8debe --- /dev/null +++ b/Documents/JournalDeBord/authentification.md @@ -0,0 +1,36 @@ +# Authentification + +## Contexte + +Le projet demande de pouvoir authentifier les utilisateurs présents. Le but étant de leurs associer un "contexte" +(cours, informations personnelles, ...). Pour que ceux-ci puissent accomplir différentes actions nécéssitantes une +identification (permission, info personelles, ...). + +## Méthode + +Lorsque qu'un utilisateur se connecte au serveur, nous lui envoyons un token qui sera stocké dans le +navigateur. Ce token est unique à l'utilisateur et pourra être ré-envoyé dans les futures requêtes +pour identifier l'utilisateur. + +Ce token est donc une chaine de 64 caractères suivant la norme ISO_8859_1(8bits par cararctère) aléatoires,ce qui est d'après nos recherches suffisant. + +De plus une limite de 5 token par utilisateur sera ajoutée de sorte à +1) S'assurer qu'une personne ne noie la base de donnée de tokens. +2) Ajouter une protection supplémentaire pour assurer qu'un token est bien unique à un utilisateur. + +## Autres méthodes envisagée + +### Oauth2 + +C'est un protocol d'identification vastement utilisé permettant, en plus d'identifier les requettes, +de gérer leurs permissions. Un utilisateur créen un token peut lui attribuer des permissions +spécifique qui restrainderaients les permissions d'utilisation de ce token. C'est très utile pour +déployer des api de site pouvant notament être accédé par des ordinateurs / bots. Ca n'est en +revanche pas l'objectif du projet et l'option n'a donc pas été retenue + +### Spring Sessions / Tomcat sessions + +Il aurait été possible de laisser une librairie automatiser les sessions. Malheuresement, celà +implique de devoir se plier au format de la dite librairie. L'implémentation d'un système de gestion +de token maison semblai à la fois, non-imposible et interessant à notre apprentisage. C'est pourquoi +nous n'avons pas utilisé cette option. diff --git a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java index d47885f..8a0722d 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java +++ b/backend/src/main/java/ovh/herisson/Clyde/EndPoints/LoginController.java @@ -1,4 +1,5 @@ package ovh.herisson.Clyde.EndPoints; +import com.fasterxml.jackson.annotation.JsonFormat; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -11,13 +12,26 @@ import java.util.Date; @CrossOrigin(origins = "http://localhost:5173") public class LoginController { private final AuthenticatorService authServ; - public LoginController(AuthenticatorService authServ){ - this.authServ = authServ; - } - @PostMapping("/login") - public ResponseEntity login(@RequestParam String identifier, String password, Date expirationDate){ - String sessionToken = authServ.login(identifier,password,expirationDate); + static public class RequestLogin{ + private final String identifier; + private final String password; + @JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss") + private final Date expirationDate; + public RequestLogin(String identifier, String password, Date expirationDate){ + this.identifier = identifier; + this.password = password; + this.expirationDate = expirationDate; + } + } + + public LoginController(AuthenticatorService authServ){ + this.authServ = authServ; + } + @PostMapping(value = "/login") + public ResponseEntity login(@RequestBody RequestLogin requestLogin){ + + String sessionToken = authServ.login(requestLogin.identifier,requestLogin.password,requestLogin.expirationDate); if (sessionToken == null){ return new UnauthorizedResponse<>("Identifier or Password incorrect"); } diff --git a/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java b/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java index 6dd0cfb..7134508 100644 --- a/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java +++ b/backend/src/main/java/ovh/herisson/Clyde/Services/TokenService.java @@ -6,7 +6,7 @@ import ovh.herisson.Clyde.Repositories.TokenRepository; import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.User; -import java.nio.charset.StandardCharsets; +import java.io.UnsupportedEncodingException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Calendar; @@ -25,9 +25,15 @@ public class TokenService { public String generateNewToken(){ byte[] bytes = new byte[64]; new SecureRandom().nextBytes(bytes); - String token = new String(bytes, StandardCharsets.US_ASCII); - System.out.println(token); - return token; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) (((bytes[i]+256)%256 %95+ 32)); + } + // will never end up in the catch because of the way that SecureRandom.nextBytes is implemented + try { + return new String(bytes,"ISO_8859_1"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } } public User getUserFromToken(String token){ @@ -57,4 +63,4 @@ public class TokenService { } } }; -} \ No newline at end of file +} diff --git a/frontend/README.md b/frontend/README.md index 39ae23c..251ed06 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -19,9 +19,3 @@ npm run dev ```sh npm run build ``` - -### Run Unit Tests with [Vitest](https://vitest.dev/) - -```sh -npm run test:unit -``` diff --git a/frontend/login/index.html b/frontend/login/index.html deleted file mode 100644 index 05192e0..0000000 --- a/frontend/login/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Clyde - Login - - -
- - - diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3165c6e..809af17 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,7 @@ "name": "clyde", "version": "0.0.0", "dependencies": { + "vite-plugin-top-level-await": "^1.4.1", "vue": "^3.4.15", "vue3-toastify": "^0.2.1" }, @@ -35,7 +36,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "aix" @@ -51,7 +51,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -67,7 +66,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -83,7 +81,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "android" @@ -99,7 +96,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -115,7 +111,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -131,7 +126,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -147,7 +141,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -163,7 +156,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -179,7 +171,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -195,7 +186,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "linux" @@ -211,7 +201,6 @@ "cpu": [ "loong64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -227,7 +216,6 @@ "cpu": [ "mips64el" ], - "dev": true, "optional": true, "os": [ "linux" @@ -243,7 +231,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -259,7 +246,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -275,7 +261,6 @@ "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -291,7 +276,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -307,7 +291,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "netbsd" @@ -323,7 +306,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "openbsd" @@ -339,7 +321,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "sunos" @@ -355,7 +336,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -371,7 +351,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -387,7 +366,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -401,6 +379,22 @@ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, + "node_modules/@rollup/plugin-virtual": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", + "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", @@ -408,7 +402,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -421,7 +414,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -434,7 +426,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -447,7 +438,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -460,7 +450,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -473,7 +462,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -486,7 +474,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -499,7 +486,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -512,7 +498,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -525,7 +510,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -538,7 +522,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -551,7 +534,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -564,17 +546,212 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" ] }, + "node_modules/@swc/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.5.tgz", + "integrity": "sha512-4/JGkG4b1Z/QwCGgx+Ub46MlzrsZvBk5JSkxm9PcZ4bSX81c+4Y94Xm3iLp5Ka8NxzS5rD4mJSpcYuN3Tw0ceg==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.2", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.4.5", + "@swc/core-darwin-x64": "1.4.5", + "@swc/core-linux-arm-gnueabihf": "1.4.5", + "@swc/core-linux-arm64-gnu": "1.4.5", + "@swc/core-linux-arm64-musl": "1.4.5", + "@swc/core-linux-x64-gnu": "1.4.5", + "@swc/core-linux-x64-musl": "1.4.5", + "@swc/core-win32-arm64-msvc": "1.4.5", + "@swc/core-win32-ia32-msvc": "1.4.5", + "@swc/core-win32-x64-msvc": "1.4.5" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.5.tgz", + "integrity": "sha512-toMSkbByHNfGXESyY1aiq5L3KutgijrNWB/THgdHIA1aIbwtrgMdFQfxpSE+INuuvWYi/Fxarv86EnU7ewbI0Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.5.tgz", + "integrity": "sha512-LN8cbnmb4Gav8UcbBc+L/DEthmzCWZz22rQr6fIEHMN+f0d71fuKnV0ca0hoKbpZn33dlzUmXQE53HRjlRUQbw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.5.tgz", + "integrity": "sha512-suRFkhBWmOQxlM4frpos1uqjmHfaEI8FuJ0LL5+yRE7IunNDeQJBKujGZt6taeuxo1KqC0N0Ajr8IluN2wrKpA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.5.tgz", + "integrity": "sha512-mLKxasQArDGmR6k9c0tkPVUdoo8VfUecocMG1Mx9NYvpidJNaZ3xq9nYM77v7uq1fQqrs/59DM1fJTNRWvv/UQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.5.tgz", + "integrity": "sha512-pgKuyRP7S29U/HMDTx+x8dFcklWxwB9cHFNCNWSE6bS4vHR93jc4quwPX9OEQX5CVHxm+c8+xof043I4OGkAXw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.5.tgz", + "integrity": "sha512-srR+YN86Oerzoghd0DPCzTbTp08feeJPSr9kkNdmtQWENOa4l/9cJV3+XY6vviw0sEjezPmYnc3SwRxJRaxvEw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.5.tgz", + "integrity": "sha512-aSf41LZtDeG5VXI4RCnzcu0UInPyNm3ip8Kw+sCK+sSqW9o7DgBkyqqbip3RZq84fNUHBQQQQdKXetltsyRRqw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.5.tgz", + "integrity": "sha512-vU3k8JwRUlTkJMfJQY9E4VvLrsIFOpfhnvbuXB84Amo1cJsz+bYQcC6RSvY7qpaDzDKFdUGbJco4uZTRoRf7Mg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.5.tgz", + "integrity": "sha512-856YRh3frRK2XbrSjDOFBgoAqWJLNRkaEtfGzXfeEoyJlOz0BFsSJHxKlHAFkxRfHe2li9DJRUQFTEhXn4OUWw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.5.tgz", + "integrity": "sha512-j1+kV7jmWY1+NbXAvxAEW165781yLXVZKLcoXIZKmw18EatqMF6w8acg1gDG8C+Iw5aWLkRZVS4pijSh7+DtCQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==" + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@vitejs/plugin-vue": { "version": "5.0.4", @@ -796,7 +973,6 @@ "version": "0.19.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", - "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -848,7 +1024,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -1090,7 +1265,6 @@ "version": "4.12.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", - "dev": true, "dependencies": { "@types/estree": "1.0.5" }, @@ -1202,11 +1376,22 @@ "requires-port": "^1.0.0" } }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vite": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.3.tgz", "integrity": "sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==", - "dev": true, "dependencies": { "esbuild": "^0.19.3", "postcss": "^8.4.35", @@ -1257,6 +1442,19 @@ } } }, + "node_modules/vite-plugin-top-level-await": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/vite-plugin-top-level-await/-/vite-plugin-top-level-await-1.4.1.tgz", + "integrity": "sha512-hogbZ6yT7+AqBaV6lK9JRNvJDn4/IJvHLu6ET06arNfo0t2IsyCaon7el9Xa8OumH+ESuq//SDf8xscZFE0rWw==", + "dependencies": { + "@rollup/plugin-virtual": "^3.0.2", + "@swc/core": "^1.3.100", + "uuid": "^9.0.1" + }, + "peerDependencies": { + "vite": ">=2.8" + } + }, "node_modules/vue": { "version": "3.4.19", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz", diff --git a/frontend/package.json b/frontend/package.json index d92904b..c02c826 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "vite-plugin-top-level-await": "^1.4.1", "vue": "^3.4.15", "vue3-toastify": "^0.2.1" }, diff --git a/frontend/public/i18n/EN.txt b/frontend/public/i18n/EN.txt index 8ffb03d..bc4eb40 100644 --- a/frontend/public/i18n/EN.txt +++ b/frontend/public/i18n/EN.txt @@ -1,8 +1,30 @@ # English translations (some examples to remove) -login.guest.login=log in -login.guest.register=register -login.guest.welcome=Please Register here -login.success=You are now registered as $name - +login.guest.signin=Sign in +login.guest.register=Register +login.guest.alregister=Already Registered +login.guest.welcome=WELCOME TO THE UNIVERSITY +login.guest.email=E-MAIL +login.guest.firstname= FIRSTNAME +login.guest.surname=SURNAME +login.guest.country=COUNTRY +login.guest.address=ADDRESS +login.guest.password=PASSWORD +login.guest.nextpage=Next Page +login.guest.lastpage=Last Page +login.guest.submit=Submit +login.guest.birthday=BIRTHDAY +login.guest.confirm=CONFIRM +app.home=Home +app.login=Login +app.notifications=Notifications +app.settings=Settings +app.messages=Messages +app.forum=Forum +app.schedules=Schedules +app.inscription.requests=Inscription Requests +request.moreInfos=More Infos +request.accept=Accept +request.refuse=Refuse #===================================================== + diff --git a/frontend/public/i18n/FR.txt b/frontend/public/i18n/FR.txt index caf4165..42ab8bf 100644 --- a/frontend/public/i18n/FR.txt +++ b/frontend/public/i18n/FR.txt @@ -1,8 +1,29 @@ # Traductions françaises (Quelques examples a enlever) -login.guest.login=s'identifier -login.guest.register=s'enregistrer -login.guest.welcome=Veuillez vous enregistrer ici -login.success=Vous êtes maintenant identifié comme $name - +login.guest.signin=SE CONNECTER +login.guest.register=S'enregistrer +login.guest.alregister=Déjà Enregistré +login.guest.welcome=BIENVENUE A L'UNIVERSITE +login.guest.email=E-MAIL +login.guest.firstname= PRENOM +login.guest.surname= NOM +login.guest.country= PAYS +login.guest.address=ADRESSE +login.guest.password= MOT DE PASSE +login.guest.nextpage=Prochaine Page +login.guest.lastpage=Derniere Page +login.guest.submit=Envoyer +login.guest.birthday=DATE DE NAISSANCE +login.guest.confirm=CONFIRMER +app.home=Home +app.login=Se connecter +app.notifications=Notifications +app.settings=Options +app.messages=Messages +app.forum=Forum +app.schedules=Horaires +app.inscription.requests=Demandes d'Inscription +request.moreInfos=Plus d'Infos +request.accept=Accepter +request.refuse=Refuser #===================================================== diff --git a/frontend/src/App.vue b/frontend/src/App.vue index a9d7a8a..51f8882 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,15 +1,34 @@ @@ -193,4 +221,51 @@ transition-duration: .3s; padding-left: 5px; } + .theme-checkbox { + --toggle-size: 16px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 80px; + height: 40px; + background: -webkit-gradient(linear, left top, right top, color-stop(50%, #efefef), color-stop(50%, #2a2a2a)) no-repeat; + background: -o-linear-gradient(left, #efefef 50%, rgb(239, 60, 168) 50%) no-repeat; + background: linear-gradient(to right, #efefef 50%, rgb(239, 60, 168) 50%) no-repeat; + background-size: 205%; + background-position: 0; + -webkit-transition: 0.4s; + -o-transition: 0.4s; + transition: 0.4s; + border-radius: 99em; + position: relative; + cursor: pointer; + font-size: var(--toggle-size); + } + + .theme-checkbox::before { + content: ""; + width: 35px; + height: 35px; + position: absolute; + top: 2px; + left: 3px; + background: -webkit-gradient(linear, left top, right top, color-stop(50%, #efefef), color-stop(50%, #2rgb(239, 60, 168))) no-repeat; + background: -o-linear-gradient(left, #efefef 50%, rgb(239, 60, 168) 50%) no-repeat; + background: linear-gradient(to right, #efefef 50%, rgb(239, 60, 168) 50%) no-repeat; + background-size: 205%; + background-position: 100%; + border-radius: 50%; + -webkit-transition: 0.4s; + -o-transition: 0.4s; + transition: 0.4s; + } + + .theme-checkbox:checked::before { + left: calc(100% - 35px - 3px); + background-position: 0; + } + + .theme-checkbox:checked { + background-position: 100%; + } diff --git a/frontend/src/Apps/Inscription.vue b/frontend/src/Apps/Inscription.vue new file mode 100644 index 0000000..0ba7fce --- /dev/null +++ b/frontend/src/Apps/Inscription.vue @@ -0,0 +1,32 @@ + + + diff --git a/frontend/src/Apps/Login.vue b/frontend/src/Apps/Login.vue new file mode 100644 index 0000000..5f053ab --- /dev/null +++ b/frontend/src/Apps/Login.vue @@ -0,0 +1,237 @@ + + + + + + diff --git a/frontend/src/Apps/Request.vue b/frontend/src/Apps/Request.vue new file mode 100644 index 0000000..4d63464 --- /dev/null +++ b/frontend/src/Apps/Request.vue @@ -0,0 +1,109 @@ + + + + + + + diff --git a/frontend/src/Login.vue b/frontend/src/Login.vue deleted file mode 100644 index 52e7e19..0000000 --- a/frontend/src/Login.vue +++ /dev/null @@ -1,105 +0,0 @@ - - - diff --git a/frontend/src/assets/base.css b/frontend/src/assets/base.css deleted file mode 100644 index 8816868..0000000 --- a/frontend/src/assets/base.css +++ /dev/null @@ -1,86 +0,0 @@ -/* color palette from */ -:root { - --vt-c-white: #ffffff; - --vt-c-white-soft: #f8f8f8; - --vt-c-white-mute: #f2f2f2; - - --vt-c-black: #181818; - --vt-c-black-soft: #222222; - --vt-c-black-mute: #282828; - - --vt-c-indigo: #2c3e50; - - --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); - --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); - --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); - --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); - - --vt-c-text-light-1: var(--vt-c-indigo); - --vt-c-text-light-2: rgba(60, 60, 60, 0.66); - --vt-c-text-dark-1: var(--vt-c-white); - --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); -} - -/* semantic color variables for this project */ -:root { - --color-background: var(--vt-c-white); - --color-background-soft: var(--vt-c-white-soft); - --color-background-mute: var(--vt-c-white-mute); - - --color-border: var(--vt-c-divider-light-2); - --color-border-hover: var(--vt-c-divider-light-1); - - --color-heading: var(--vt-c-text-light-1); - --color-text: var(--vt-c-text-light-1); - - --section-gap: 160px; -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--vt-c-black); - --color-background-soft: var(--vt-c-black-soft); - --color-background-mute: var(--vt-c-black-mute); - - --color-border: var(--vt-c-divider-dark-2); - --color-border-hover: var(--vt-c-divider-dark-1); - - --color-heading: var(--vt-c-text-dark-1); - --color-text: var(--vt-c-text-dark-2); - } -} - -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - font-weight: normal; -} - -body { - min-height: 100vh; - color: var(--color-text); - background: var(--color-background); - transition: - color 0.5s, - background-color 0.5s; - line-height: 1.6; - font-family: - Inter, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Oxygen, - Ubuntu, - Cantarell, - 'Fira Sans', - 'Droid Sans', - 'Helvetica Neue', - sans-serif; - font-size: 15px; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} diff --git a/frontend/src/i18n.js b/frontend/src/i18n.js index eaf2dac..d8909f1 100644 --- a/frontend/src/i18n.js +++ b/frontend/src/i18n.js @@ -9,7 +9,7 @@ * */ -import { getCookie } from './utils.js'; +import { getCookie, setCookie } from './utils.js'; const default_lang = "EN"; let langs; @@ -34,10 +34,6 @@ export default function i18n(key, options) { return ret; } -// -// Those functions are utility functions use by previous exported functions. -// - /** * Function that load the file with translation from the specified lang and return a dictionnary * @param select the language to load. could be null to fetch the cookies for an answer @@ -61,3 +57,8 @@ export async function loadLangs(lang){ langs = filteredLines; } await loadLangs(); + +export async function setLang(lang){ + setCookie("lang", lang); + await loadLangs(); +} diff --git a/frontend/src/login.js b/frontend/src/login.js deleted file mode 100644 index 5e4180d..0000000 --- a/frontend/src/login.js +++ /dev/null @@ -1,7 +0,0 @@ -import './assets/main.css' -import 'vue3-toastify/dist/index.css'; - -import { createApp } from 'vue' -import App from './Login.vue' - -createApp(App).mount('#app') diff --git a/frontend/src/main.js b/frontend/src/main.js index 59b267a..a46ba7e 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -1,5 +1,6 @@ import './assets/main.css' import 'vue3-toastify/dist/index.css'; +import 'https://kit.fontawesome.com/fb3bbd0a95.js' import { createApp } from 'vue' import App from './App.vue' diff --git a/frontend/src/rest/ServiceInscription.js b/frontend/src/rest/ServiceInscription.js new file mode 100644 index 0000000..ee75c3b --- /dev/null +++ b/frontend/src/rest/ServiceInscription.js @@ -0,0 +1,35 @@ +/** + * functions to handle register requests. + * + * TODO: On time of writing, the backend doesn't support these endpoints so it could be modified in the future. + */ +import { restGet } from './restConsumer.js' + +/** + * create a new register requests that can be recovered by the registering service + * TODO: add info in the Object (I don't know what will be needed) + */ +export async function createRegister(){ + return restPost("/requests/register"}); +} + +/** + * list all register request in a list of Objects + */ +export async function getRegisters(){ + return restGet("/requests/register") +} + +/** + * Get info on a particular registering request + */ +export async function getRegisters(id){ + return restGet("/requests/register/" + id); +} + +/** + * Change the state of a requests. + */ +export async function validateRegister(id, state){ + return restPost("/requests/register/" + id, {state: state}); +} diff --git a/frontend/src/rest/Users.js b/frontend/src/rest/Users.js new file mode 100644 index 0000000..e34d611 --- /dev/null +++ b/frontend/src/rest/Users.js @@ -0,0 +1,27 @@ +import { restGet, restPost } from './restConsumer.js' + +export async function login(user, pass, exp){ + return restPost("/login", {login: user, password: pass, expiration: exp}); +} + +export async function register(user, pass, mail){ + return restPost("/user", {name: user, password: pass, mail: mail}); +} + +/** + * get informations on a specific user. + * Leaving the id empty will return the user's value based on his token + * if the user is not authenticated. then an empty array should be returned + */ +export async function getUser(id){ + const endpoint = "/user" + id != null ? "/" + id : ""; + return restGet(endpoint); +} + +/** + * Reserved for secretary roles. Allow to list all user on the plateform + */ +export async function getAllUsers(){ + return restGet("/users"); +} + diff --git a/frontend/src/rest/courses.js b/frontend/src/rest/courses.js new file mode 100644 index 0000000..0b98284 --- /dev/null +++ b/frontend/src/rest/courses.js @@ -0,0 +1,52 @@ +/** + * Courses API + */ + +import { restGet, restPost, restDelete, restPatch } from './restConsumer.js' + +/** + * Create a new course + */ +export async function createCourse(name, credits, faculty, teacher, assistants){ + return restPost("/courses", {name: name, credits: credits, faculty: faculty, teacher: teacher, assistants: assistants} ) +} + +/** + * Delete the specified course + */ +export async function deleteCourse(id){ + return restDelete("/course/" + id); +} + +/** + * Get informations on a particular course + * + * @param id identification of the course + * + * @return all atribute of the specified course + * - name + * - credits + * - faculty + * - teacher + * - assistants : list + */ +export async function getCourse(id){ + return restGet("/course/" + id); +} + +/** + * Change the options of a course + * + * @param id the id of the course + * @param changes Object with value to changes + * + * The changes object can contain: + * - name + * - credits + * - faculty + * - teacher + * - assistants: should be a list and will replace all assistants + */ +export async function alterCourse(id, changes){ + return restPatch("/course/" + id, changes); +} diff --git a/frontend/src/rest/cursus.js b/frontend/src/rest/cursus.js new file mode 100644 index 0000000..5aad5be --- /dev/null +++ b/frontend/src/rest/cursus.js @@ -0,0 +1,41 @@ +/** + * cursus API + */ + +import { restGet, restPostn, restDelete, restPatch } from './restConsumer.js' + +/** + * Create a new cursus (bundle of courses) + * @param courses list of courses + */ +export async function createCursus(courses){ + return restPost("/cursus", {courses: courses} ); +} + +/** + * Delete the specified cursus + */ +export async function deleteCursus(id){ + return restDelete("/cursus/" + id); +} + +/** + * Get informations on a particular cursus + * + * @param id identification of the cursus + * + * @return list of courses + */ +export async function getCursus(id){ + return restGet("/cursus/" + id); +} + +/** + * Modify the courses of a cursus + * + * @param id the id of the cursus + * @param courses list of new courses + */ +export async function alterCursus(id, courses){ + return restPatch("/cursus/" + id, courses); +} diff --git a/frontend/src/utils.js b/frontend/src/utils.js index e79eec4..d00e306 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -2,7 +2,7 @@ * Return the content of a cookie with specified key * @param key cookie name */ -function getCookie(key){ +export function getCookie(key){ key = key + "=" let cookies = decodeURIComponent(document.cookie).split(";"); for (let el of cookies) { @@ -14,4 +14,12 @@ function getCookie(key){ return ""; } -export {getCookie}; +/** + * Return the content of a cookie with specified key + * @param key cookie name + */ +export function setCookie(key, value){ + let cookie = key + "=" + value + "; SameSite=Lax"; + document.cookie = cookie; + // Here we can apreciate the stupidity of Javascript :/ +} diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 7ff998b..79b748d 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -2,21 +2,14 @@ import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' +import topLevelAwait from 'vite-plugin-top-level-await' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), + topLevelAwait(), ], - build: { - rollupOptions:{ - input:{ - main: './index.html', - login: './login/index.html' - } - - } - }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url))