initial commit
This commit is contained in:
246
app/stores/auth.ts
Normal file
246
app/stores/auth.ts
Normal file
@@ -0,0 +1,246 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import UserRepository from '~/repositories/user.repository'
|
||||
import type { User, LoginResponse, ConfirmResult } from '~/types/auth'
|
||||
|
||||
|
||||
export const useAuthStore = defineStore('auth', {
|
||||
state: () => ({
|
||||
// On lie l'état directement au cookie
|
||||
token: useCookie<string | null>('auth_token', {
|
||||
// secure: false,
|
||||
// sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 7
|
||||
}), // Expire après 7 jours
|
||||
user: useCookie<User | null>('auth_user', {
|
||||
// secure: false,
|
||||
// sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 7
|
||||
}),
|
||||
loading: false,
|
||||
error: null as string | null,
|
||||
}),
|
||||
|
||||
getters: {
|
||||
// Le "!!" transforme la valeur en vrai BOULÉEN (true/false)
|
||||
isLoggedIn: (state) => !!state.token,
|
||||
|
||||
// plus tard on pourras ajouter un getter pour récupérer le prénom
|
||||
//userName: (state) => state.user?.name || 'Invité'
|
||||
},
|
||||
|
||||
actions: {
|
||||
setTokenCookie(newToken: string | null) {
|
||||
const cookie = useCookie('auth_token')
|
||||
cookie.value = newToken // On force l'écriture
|
||||
this.token = newToken // On met à jour le state Pinia
|
||||
},
|
||||
|
||||
setUserCookie(newUser: User | null) {
|
||||
// 1. On récupère le cookie sans typage strict ou typé en 'any' pour l'écriture
|
||||
const userCookie = useCookie<any>('auth_user', {
|
||||
path: '/',
|
||||
maxAge: 60 * 60 * 24 * 7,
|
||||
})
|
||||
|
||||
// 2. On assigne l'objet (Nuxt va faire le JSON.stringify en interne)
|
||||
userCookie.value = newUser
|
||||
|
||||
// 3. On met à jour le state Pinia
|
||||
this.user = newUser
|
||||
},
|
||||
|
||||
async register(email: string, password:string, locale:string ){
|
||||
const { $api } = useNuxtApp();
|
||||
const listsStore = useListStore()
|
||||
const config = useRuntimeConfig()
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const data = await $api.user.register(email, password, locale)
|
||||
|
||||
// En cas de réussite, le nouveau user est connecté.
|
||||
// On assigne les valeurs : useCookie met à jour le state ET le navigateur
|
||||
this.setTokenCookie(data.token)
|
||||
this.setUserCookie(data.user)
|
||||
listsStore.saveLists(data.lists)
|
||||
|
||||
return true
|
||||
} catch (err: any) {
|
||||
// En cas d'erreur, on nettoie les cookies
|
||||
this.token = null
|
||||
this.user = null
|
||||
this.error = err.data?.message || "Erreur de connexion"
|
||||
return false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async confirmUser(token: string) {
|
||||
const { $api } = useNuxtApp();
|
||||
//console.log(token)
|
||||
this.error = null
|
||||
try {
|
||||
const res: ConfirmResult = await $api.user.confirm(token)
|
||||
return res
|
||||
} catch (err: any) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
async login(login: string, password: string) {
|
||||
const listsStore = useListStore()
|
||||
const config = useRuntimeConfig()
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const data = await $fetch<LoginResponse>(`${config.public.apiBase}/auth/login`, {
|
||||
method: 'POST',
|
||||
body: { login, password }
|
||||
})
|
||||
|
||||
// On assigne les valeurs : useCookie met à jour le state ET le navigateur
|
||||
this.setTokenCookie(data.token)
|
||||
this.setUserCookie(data.user)
|
||||
listsStore.saveLists(data.lists)
|
||||
|
||||
return true
|
||||
} catch (err: any) {
|
||||
// En cas d'erreur, on nettoie les cookies
|
||||
this.token = null
|
||||
this.user = null
|
||||
this.error = err.data?.message || "Erreur de connexion"
|
||||
return false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
logout() {
|
||||
this.setTokenCookie(null)
|
||||
this.setUserCookie(null)
|
||||
const listsStore = useListStore()
|
||||
listsStore.resetLists()
|
||||
return navigateTo('/')
|
||||
},
|
||||
|
||||
async pwdResetResquest( email: string, locale: string) {
|
||||
const config = useRuntimeConfig()
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const data = await $fetch<boolean>(`${config.public.apiBase}/user/pwdReset`, {
|
||||
method: 'POST',
|
||||
body: { email, locale }
|
||||
})
|
||||
|
||||
return data
|
||||
} catch (err: any) {
|
||||
|
||||
this.error = err.data?.message || "Erreur de connexion"
|
||||
return false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async pwdReset( password: string, token: any) {
|
||||
const config = useRuntimeConfig()
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const data = await $fetch<boolean>(`${config.public.apiBase}/user/pwdReset`, {
|
||||
method: 'PUT',
|
||||
body: { password, token }
|
||||
})
|
||||
|
||||
return data
|
||||
} catch (err: any) {
|
||||
|
||||
this.error = err.data?.message || "Erreur de connexion"
|
||||
return false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async emailChange( newEmail:string, locale:string){
|
||||
const { $api } = useNuxtApp();
|
||||
|
||||
// const config = useRuntimeConfig()
|
||||
this.error = null;
|
||||
|
||||
if ( !this.user?.email ){
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const data = await $api.user.emailChange(newEmail, locale)
|
||||
return data
|
||||
} catch (err: any) {
|
||||
|
||||
this.error = err.data?.message || "Erreur de connexion"
|
||||
return false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async updateDisplayName(newDisplayName:string){
|
||||
const { $api } = useNuxtApp();
|
||||
|
||||
// const config = useRuntimeConfig()
|
||||
this.error = null;
|
||||
|
||||
if ( !this.user?.email ){
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const data = await $api.user.updateDisplayName(newDisplayName)
|
||||
this.user.display_name = newDisplayName
|
||||
return data
|
||||
} catch (err: any) {
|
||||
this.error = err.data?.message || "Erreur de connexion"
|
||||
return false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async deleteRequest(locale:string){
|
||||
const { $api } = useNuxtApp();
|
||||
this.error = null
|
||||
|
||||
if ( !this.user?.email ){
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await $api.user.deleteRequest(locale)
|
||||
return data
|
||||
} catch (err: any) {
|
||||
this.error = err.data?.message || "Erreur de connexion"
|
||||
return false
|
||||
}
|
||||
},
|
||||
async pwdChallenge(pwd:string){
|
||||
const { $api } = useNuxtApp();
|
||||
|
||||
try {
|
||||
const data = await $api.user.pwdChallenge(pwd)
|
||||
console.log(data)
|
||||
if (this.user){
|
||||
this.user.sudo_token = data.sudo_token
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.response?.status === 403) {
|
||||
console.warn("Mauvais mot de passe, mais on garde la session active.");
|
||||
return false; // On renvoie false pour afficher une erreur dans l'UI
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
21
app/stores/burger.ts
Normal file
21
app/stores/burger.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useBurgerStore = defineStore('burger', {
|
||||
state: () => ({
|
||||
checked: false as boolean,
|
||||
}),
|
||||
|
||||
actions: {
|
||||
toggle() {
|
||||
this.checked = !this.checked
|
||||
},
|
||||
|
||||
open() {
|
||||
this.checked = true
|
||||
},
|
||||
|
||||
close() {
|
||||
this.checked = false
|
||||
},
|
||||
},
|
||||
})
|
||||
62
app/stores/lists.ts
Normal file
62
app/stores/lists.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { List } from '~/types/lists'
|
||||
|
||||
|
||||
export const useListStore = defineStore('lists', {
|
||||
state: () => ({
|
||||
lists: [] as List[],
|
||||
loading: false as boolean,
|
||||
}),
|
||||
|
||||
actions: {
|
||||
saveLists(lists:Array<List>){
|
||||
this.lists = lists
|
||||
},
|
||||
resetLists(){
|
||||
this.lists = []
|
||||
},
|
||||
|
||||
async fetchLists() {
|
||||
// On récupère notre plugin API injecté
|
||||
const { $api } = useNuxtApp();
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
// L'appel est maintenant ultra simple et typé
|
||||
const data = await $api.lists.getAll();
|
||||
this.lists = data;
|
||||
} catch (error) {
|
||||
// La gestion d'erreur est centralisée,
|
||||
// mais tu peux ajouter une logique spécifique ici (ex: notification)
|
||||
console.error("Erreur lors du chargement des listes:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
// async updateList(id, title, content) {
|
||||
// const config = useRuntimeConfig();
|
||||
|
||||
// try {
|
||||
// const data = await $fetch<[]|null>(`${config.public.apiBase}/lists`, {
|
||||
// method: 'GET',
|
||||
// headers: {
|
||||
// // On injecte le token ici
|
||||
// 'Authorization': `Bearer ${this.token}`
|
||||
// },
|
||||
// // Si tu as besoin d'envoyer un corps de message vide ou spécifique
|
||||
// // body: {}
|
||||
// });
|
||||
|
||||
// this.lists = data;
|
||||
// console.log(data);
|
||||
// console.log(this.token);
|
||||
// return data;
|
||||
// } catch (error) {
|
||||
// console.error("Erreur lors de la récupération des listes:", error);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
})
|
||||
64
app/stores/params.ts
Normal file
64
app/stores/params.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useParamsStore = defineStore('params', {
|
||||
|
||||
state: () => ({
|
||||
paramsData: false,
|
||||
}),
|
||||
|
||||
actions:
|
||||
{
|
||||
async findAll(data = null)
|
||||
{
|
||||
if (data){
|
||||
this.paramsData = JSON.parse(data)
|
||||
//console.log(data)
|
||||
}
|
||||
else{
|
||||
this.paramsData = JSON.parse(await paramsService.findAll())
|
||||
//if (this.paramsData)
|
||||
}
|
||||
//console.log(this.paramsData)
|
||||
},
|
||||
|
||||
updateParams(){
|
||||
paramsService.update(JSON.stringify(this.paramsData))
|
||||
},
|
||||
|
||||
changePage(page){
|
||||
this.paramsData.profil_and_params_view = page
|
||||
this.updateParams();
|
||||
},
|
||||
|
||||
deleteColor(){
|
||||
|
||||
if(this.paramsData.colors.length > 1){
|
||||
|
||||
const deletedColor = this.paramsData.colors.pop()
|
||||
if (this.paramsData.unavailable_colors == undefined){
|
||||
this.paramsData = {
|
||||
colors : this.paramsData.colors,
|
||||
unavailable_colors : [],
|
||||
profil_and_params_view : this.paramsData.profil_and_params_view
|
||||
}
|
||||
}
|
||||
this.paramsData.unavailable_colors.push(deletedColor)
|
||||
}
|
||||
this.updateParams();
|
||||
|
||||
},
|
||||
|
||||
addColor(){
|
||||
if(this.paramsData.colors.length < 8){
|
||||
const color = this.paramsData.unavailable_colors.pop()
|
||||
this.paramsData.colors.push(color)
|
||||
this.updateParams();
|
||||
}
|
||||
},
|
||||
|
||||
modifyColor(colorIndex, newColorValue) {
|
||||
this.paramsData.colors[colorIndex] = newColorValue
|
||||
this.updateParams();
|
||||
},
|
||||
}
|
||||
})
|
||||
56
app/stores/passwordToolBox.ts
Normal file
56
app/stores/passwordToolBox.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const usePasswordToolBoxStore = defineStore('passwordToolBox', {
|
||||
state: () => ({
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
|
||||
// --- REGEX ---
|
||||
regNumberOfCaracteres: /^.{8,22}$/,
|
||||
regSpecialCaractere: /[^A-Za-z0-9]/,
|
||||
regCapitalizeCaractere: /[A-Z]/,
|
||||
regMinimizeCaractere: /[a-z]/,
|
||||
regNumber: /\d/,
|
||||
regPassword: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,22}$/,
|
||||
}),
|
||||
actions: {
|
||||
updatePassword(newPassword: string) {
|
||||
this.password = newPassword
|
||||
},
|
||||
updateConfirmPassword(newConfirm: string) {
|
||||
this.confirmPassword = newConfirm
|
||||
},
|
||||
|
||||
// --- CHECK FUNCTIONS ---
|
||||
checkRegex(regex: RegExp) {
|
||||
return regex.test(this.password)
|
||||
},
|
||||
|
||||
isNumberOfCaracteresValid() {
|
||||
return this.checkRegex(this.regNumberOfCaracteres)
|
||||
},
|
||||
isSpecialCaractereValid() {
|
||||
return this.checkRegex(this.regSpecialCaractere)
|
||||
},
|
||||
isCapitalizeCaractereValid() {
|
||||
return this.checkRegex(this.regCapitalizeCaractere)
|
||||
},
|
||||
isMinimizeCaractereValid() {
|
||||
return this.checkRegex(this.regMinimizeCaractere)
|
||||
},
|
||||
isNumberValid() {
|
||||
return this.checkRegex(this.regNumber)
|
||||
},
|
||||
isPasswordValid() {
|
||||
return this.checkRegex(this.regPassword)
|
||||
},
|
||||
isPasswordConfirmationValid() {
|
||||
return this.password === this.confirmPassword && this.isPasswordValid()
|
||||
},
|
||||
|
||||
// --- UI HELPER ---
|
||||
uiClass(valid: boolean) {
|
||||
return valid ? 'has-success' : 'has-error'
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user