diff --git a/config/deploy.rb b/config/deploy.rb index 57022f6..f288b17 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -48,7 +48,6 @@ on roles(:app) do execute "ln -sf #{shared_path}/.env-api #{release_path}/api/.env" execute "ln -sf #{shared_path}/.env-frontend #{release_path}/frontend/.env" - execute "ln -sf #{shared_path}/.env-frontend #{release_path}/frontend/.env.production" end end @@ -86,6 +85,7 @@ on roles(:app) do within release_path.join('frontend') do execute :npm, 'install' # Installer les dépendances npm + execute :sudo, 'rm -rf dist' # Supprimer ancien build de l'application execute :npm, 'run build' # Construire l'application Vue.js end end diff --git a/frontend/src/components/NavBar.vue b/frontend/src/components/NavBar.vue index 9817aec..d1ce8f4 100644 --- a/frontend/src/components/NavBar.vue +++ b/frontend/src/components/NavBar.vue @@ -1,6 +1,9 @@ diff --git a/frontend/src/domain/AuthService.js b/frontend/src/domain/AuthService.js index ab71034..23743d9 100644 --- a/frontend/src/domain/AuthService.js +++ b/frontend/src/domain/AuthService.js @@ -3,7 +3,6 @@ import { ref } from 'vue'; import { setCookie, getCookie, deleteAllCookies } from "./Cookies"; import { User } from './User'; - /** Utility class to manage authentication and make requests to the API.*/ export class AuthService { @@ -17,10 +16,13 @@ export class AuthService { * @return {boolean} Wether the operation was successful. */ static async register(username, password, passwordConfirmation) { + const hash = await this.hashString(password); + const hashConf = await this.hashString(passwordConfirmation); + let data = { "username": username, - "password1": password, - "password2": passwordConfirmation, + "password1": hash, + "password2": hashConf, }; let response = null; @@ -46,11 +48,15 @@ export class AuthService { * @return {string} The authentication token that was saved. */ static async login(username, password) { + const hash = await this.hashString(password); + let data = { "username": username, - "password": password, + "password": hash, }; + + const response = await axios.post( `${import.meta.env.VITE_API_URL}/user/login/`, data @@ -113,6 +119,27 @@ export class AuthService { return null; } } + + + /** + * Hashes a string using the SHA-256 algorithm. + * @param {string} str - The string to be hashed. + * @returns {Promise} A Promise that resolves with the hexadecimal hash string. + */ + static async hashString(str) { + // Convert the string to an array buffer + const encoder = new TextEncoder(); + const data = encoder.encode(str); + + // Hash the data using SHA-256 algorithm + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + + // Convert the hash buffer to a hex string + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join(''); + + return hashHex; + } } diff --git a/frontend/src/views/EditTournamentView.vue b/frontend/src/views/EditTournamentView.vue index d365879..de28ffc 100644 --- a/frontend/src/views/EditTournamentView.vue +++ b/frontend/src/views/EditTournamentView.vue @@ -81,13 +81,15 @@ const sendMatchResult = (match) => { + :value="match.scores === '' ? null : match.scores.split('-')[0]" + min="0" max="100"> + :value="match.scores === '' ? null : match.scores.split('-')[1]" + min="0" max="100"> diff --git a/frontend/src/views/LoginView.vue b/frontend/src/views/LoginView.vue index 241f646..fecab06 100644 --- a/frontend/src/views/LoginView.vue +++ b/frontend/src/views/LoginView.vue @@ -8,6 +8,7 @@ const form = ref(null) const username = ref(null) const password = ref(null) +const errorMessage = ref(null) const login = () => { if (!form.value.reportValidity()) return; @@ -16,7 +17,9 @@ const login = () => { password.value, ).then((token) => { router.push({ name: "home" }) - }) + }).catch(error => { + errorMessage.value = "Nom d'utilisateur ou mot de passe incorrect"; // Définition du message d'erreur + }); }; @@ -29,7 +32,7 @@ const login = () => {
-
@@ -39,12 +42,16 @@ const login = () => {
+
{{ errorMessage }}

Pas de compte ? S'inscrire

\ No newline at end of file diff --git a/frontend/src/views/ManageTournamentsView.vue b/frontend/src/views/ManageTournamentsView.vue index f085da5..9a4d9ac 100644 --- a/frontend/src/views/ManageTournamentsView.vue +++ b/frontend/src/views/ManageTournamentsView.vue @@ -6,18 +6,20 @@ import { TournamentStatus } from '../domain/TournamentStatus'; const router = useRouter(); const tournaments = ref([]); +const loading = ref(false); -function deleteTournament(id,name) { + +function deleteTournament(id, name) { let text = prompt("Êtes-vous sûr de vouloir supprimer le tournoi ?\nSi oui, tapez \"" + name + "\" pour confirmer"); - if(text ==name){ - + if (text == name) { + TournamentService.deleteTournament(id).then((successful) => { if (!successful) return; tournaments.value = tournaments.value.filter((tournament) => tournament.id != id); - }); + }); } - + } function editTournament(id) { @@ -30,9 +32,13 @@ function addTournament() { function nextTournamentStatus(tournament) { if (tournament.status.id == TournamentStatus.Completed.id) return; + loading.value = true; TournamentService.nextTournamentStatus(tournament).then((newStatus) => { const index = tournaments.value.indexOf(tournament); tournaments.value[index].status = newStatus; + loading.value = false; + }).catch(() => { + loading.value = false; }); } @@ -46,7 +52,7 @@ onMounted(async () => {

Gérer les tournois - + add

@@ -65,10 +71,13 @@ onMounted(async () => { {{ (tournament.status) }}
- - next_plan + + next_plan + + cancel @@ -78,6 +87,8 @@ onMounted(async () => { title="Cliquez pour modifier le tournoi"> edit +
+

@@ -97,6 +108,20 @@ h1 { span { cursor: pointer; margin-left: 16px; + border-width: 1px; + border-color: white; + background: white; + border-style: solid; + padding: 4px; + border-radius: 4px; + color: black; + transition: all 0.25s; + + + &:hover { + transform: translateY(-2px); + box-shadow: 0px 0px 20px rgba($color: $primary, $alpha: 0.5); + } } } @@ -154,12 +179,19 @@ h1 { user-select: none; /* Standard syntax */ - span:hover { - cursor: pointer; - } + span { + &:hover { + cursor: pointer; + } - span.disabled:hover { - cursor: not-allowed; + &.disabled { + opacity: 0.5; + + &:hover { + + cursor: not-allowed; + } + } } } @@ -214,4 +246,23 @@ h1 { width: calc(100% - (3 * 8px / 4)); } } + +.loading-spinner { + border: 4px solid rgba(0, 0, 0, 0.1); + border-left-color: #09f; + border-radius: 50%; + width: 20%; + height: 100%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/frontend/src/views/RegisterView.vue b/frontend/src/views/RegisterView.vue index dd68aa0..a9d1420 100644 --- a/frontend/src/views/RegisterView.vue +++ b/frontend/src/views/RegisterView.vue @@ -35,7 +35,7 @@ const register = async () => {
-
diff --git a/frontend/src/views/TournamentDetailsView.vue b/frontend/src/views/TournamentDetailsView.vue index 2a5b111..8d48428 100644 --- a/frontend/src/views/TournamentDetailsView.vue +++ b/frontend/src/views/TournamentDetailsView.vue @@ -28,6 +28,8 @@ const register = async () => { } await TournamentService.registerForTournament(tournamentId); } + + location.reload(); }; const unregister = async () => { @@ -36,6 +38,7 @@ const unregister = async () => { isRegistered.value = false; } await TournamentService.unregisterFromTournament(tournamentId); + location.reload(); }; @@ -57,7 +60,7 @@ const unregister = async () => {
-
+
@@ -65,6 +68,9 @@ const unregister = async () => { \ No newline at end of file