Files
List_ultimate/app/stores/lists.ts

192 lines
6.2 KiB
TypeScript

import { defineStore } from 'pinia'
import type { List, WPListEncrypted } from '~/types/lists'
import {useCryptoStore} from '~/composables/crypto'
import sodium from "libsodium-wrappers"
const crypto = useCryptoStore()
export const useListStore = defineStore('lists', {
state: () => ({
lists: [] as List[],
loading: false as boolean,
masterKey: null as Uint8Array | null,
publicKey: new Uint8Array() as Uint8Array,
privateKey: new Uint8Array() as Uint8Array,
}),
actions: {
saveLists(lists:Array<List>){
this.lists = lists
},
resetLists(){
this.lists = []
},
setMasterKey(key: Uint8Array){
this.masterKey = key
},
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 processRawData(rawData: [WPListEncrypted]){
const { $api } = useNuxtApp();
await crypto.init()
if (rawData && rawData.length > 0) {
const item = rawData[0];
if (item && this.masterKey){
if (this.isWPListEncrypted(item)) {
if (item.content_cipher === "initialize-me"){
/* 1- Création de la paire de clés (TODO : à déporter ailleurs (Key Store ?)) */
const { publicKey, privateKey } = crypto.generateUserKeyPair()
this.publicKey = publicKey;
this.privateKey = privateKey;
// On les envoie au BO //
/* Chiffrage de la private avec la master : */
const privKeyCipher = crypto.encryptPrivateKey(this.privateKey, this.masterKey)
/* empaquetage */
const payload = {
'user_id': item.user_id, // pour vérification au BO
'private_key_cipher': privKeyCipher,
'public_key': publicKey,
}
/* Et on envoie ! */
await $api.lists.uploadKeys(JSON.stringify(payload))
// On crée la liste //
/* D'abord la clé AES de la liste */
const key = crypto.generateListKey();
/* Puis la liste */
const user_id = Number(item.user_id)
const data: List = {
id: Number(item.id),
user_id: user_id,
aesKey: key,
list_title: 'THE VERY première liste',
list_type: 'basic',
content: '{[\'vide\']}',
is_open: true,
created_at: Date.now(),
updated_at: Date.now(),
}
this.lists[0] = data
/* Et on envoie au BO */
this.syncData(data, this.publicKey, this.privateKey)
}
else{
console.log('coucou : ' + rawData);
}
}
}
}
},
async syncData(decryptedData: List, userPublicKey: Uint8Array, userPrivateKey: Uint8Array) {
const { $api } = useNuxtApp();
const aesKey = decryptedData.aesKey;
await crypto.init();
// 1. On prépare les données (en excluant la clé elle-même du contenu)
const { aesKey: _, ...pureData } = decryptedData;
const stringData = JSON.stringify(pureData);
// 2. Chiffrement du contenu par la clé AES (XChaCha20)
const encryptedContent = crypto.encryptList(stringData, aesKey);
// 3. Chiffrement de la clé AES par la clé Publique (Asymétrique)
// On utilise ici ta fonction de l'étape 11
const encryptedKeyPayload = crypto.encryptListKeyForUser(
aesKey,
userPublicKey,
userPrivateKey
);
// 4. On empaquette le tout pour le Back-Office
const dataToBO: WPListEncrypted = {
id: decryptedData.id.toString(),
user_id: decryptedData.user_id.toString(),
// La clé AES verrouillée pour l'utilisateur
key_cipher: sodium.to_base64(encryptedKeyPayload.cipher),
key_nonce: sodium.to_base64(encryptedKeyPayload.nonce),
// Le contenu de la liste
content_cipher: sodium.to_base64(encryptedContent.cipher),
content_nonce: sodium.to_base64(encryptedContent.nonce),
created_at: null,
updated_at: null,
};
await $api.lists.update(dataToBO)
},
// 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);
// }
// }
isWPListEncrypted(obj: any): obj is WPListEncrypted {
console.log(obj !== null)
console.log(typeof obj)
console.log(typeof obj.id)
console.log(typeof obj.key_cipher )
console.log(typeof obj.key_nonce )
console.log(typeof obj.content_cipher)
console.log(typeof obj.content_nonce)
return (
obj !== null &&
typeof obj === 'object' &&
typeof obj.id === 'string' &&
typeof obj.key_cipher === 'string' &&
typeof obj.key_nonce === 'string' &&
typeof obj.content_cipher === 'string' &&
typeof obj.content_nonce === 'string'
);
}
}
})