Jelajahi Sumber

add the profileHash header to persist requests

Olivier Massot 1 tahun lalu
induk
melakukan
39f0c6ccb3

+ 5 - 8
composables/data/useAp2iRequestService.ts

@@ -5,7 +5,6 @@ import ApiRequestService from '~/services/data/apiRequestService'
 import { usePageStore } from '~/stores/page'
 import UnauthorizedError from '~/services/error/UnauthorizedError'
 import { useAccessProfileStore } from '~/stores/accessProfile'
-import type { AssociativeArray } from '~/types/data'
 
 /**
  * Retourne une instance de ApiRequestService configurée pour interroger l'api Ap2i
@@ -34,16 +33,14 @@ export const useAp2iRequestService = () => {
 
     const accessProfileStore = useAccessProfileStore()
 
-    const headers: AssociativeArray = {
-      'x-accessid': String(accessProfileStore.id),
-      Authorization: 'BEARER ' + accessProfileStore.bearer,
-    }
+    const headers = new Headers(options.headers)
 
+    headers.set('x-accessid', String(accessProfileStore.id))
+    headers.set('Authorization', 'BEARER ' + accessProfileStore.bearer)
     if (accessProfileStore.switchId) {
-      headers['x-switch-user'] = String(accessProfileStore.switchId)
+      headers.set('x-switch-user', String(accessProfileStore.switchId))
     }
-
-    options.headers = { ...options.headers, ...headers }
+    options.headers = headers
 
     pending.value = true
     console.log('Request : ' + request + ' (SSR: ' + process.server + ')')

+ 14 - 1
composables/data/useEntityManager.ts

@@ -1,6 +1,7 @@
 import { useRepo } from 'pinia-orm'
 import EntityManager from '~/services/data/entityManager'
 import { useAp2iRequestService } from '~/composables/data/useAp2iRequestService'
+import { useAccessProfileStore } from '~/stores/accessProfile'
 
 let entityManager: EntityManager | null = null
 
@@ -9,7 +10,19 @@ export const useEntityManager = () => {
     const { apiRequestService } = useAp2iRequestService()
     const getRepo = useRepo
 
-    entityManager = new EntityManager(apiRequestService, getRepo)
+    const profileStore = useAccessProfileStore()
+    const getProfileMask = () => {
+      return {
+        activityYear: profileStore.activityYear,
+        historical: profileStore.historical,
+      }
+    }
+
+    entityManager = new EntityManager(
+      apiRequestService,
+      getRepo,
+      getProfileMask,
+    )
   }
   return { em: entityManager }
 }

+ 14 - 2
services/data/entityManager.ts

@@ -8,6 +8,7 @@ import ApiResource from '~/models/ApiResource'
 import type { AnyJson, AssociativeArray, Collection } from '~/types/data.d'
 import models from '~/models/models'
 import HydraNormalizer from '~/services/data/normalizer/hydraNormalizer'
+import ObjectUtils from '~/services/utils/objectUtils'
 
 /**
  * Entity manager: make operations on the models defined with the Pinia-Orm library
@@ -30,12 +31,16 @@ class EntityManager {
    */
   protected _getRepo: (model: typeof ApiResource) => Repository<ApiResource>
 
+  protected _getProfileMask: () => object
+
   public constructor(
     apiRequestService: ApiRequestService,
     getRepo: (model: typeof ApiResource) => Repository<ApiResource>,
+    getProfileMask: () => object,
   ) {
     this.apiRequestService = apiRequestService
     this._getRepo = getRepo
+    this._getProfileMask = getProfileMask
   }
 
   /**
@@ -241,12 +246,14 @@ class EntityManager {
 
     const data: AnyJson = HydraNormalizer.normalizeEntity(instance)
 
+    const headers = { profileHash: await this.makeProfileHash() }
+
     if (!instance.isNew()) {
       url = UrlUtils.join(url, String(instance.id))
-      response = await this.apiRequestService.put(url, data)
+      response = await this.apiRequestService.put(url, data, null, headers)
     } else {
       delete data.id
-      response = await this.apiRequestService.post(url, data)
+      response = await this.apiRequestService.post(url, data, null, headers)
     }
 
     const hydraResponse = HydraNormalizer.denormalize(response, model)
@@ -426,6 +433,11 @@ class EntityManager {
     repository.destroy(tempInstanceId)
     repository.destroy(this.CLONE_PREFIX + tempInstanceId)
   }
+
+  protected async makeProfileHash(): Promise<string> {
+    const mask = this._getProfileMask()
+    return await ObjectUtils.hash(mask)
+  }
 }
 
 export default EntityManager

+ 13 - 1
services/utils/objectUtils.ts

@@ -3,8 +3,9 @@
  * @class ObjectUtils
  * Classe aidant à manipuler des Objets
  */
+import _ from 'lodash'
 import type { AnyJson } from '~/types/data'
-
+import StringUtils from '~/services/utils/stringUtils'
 export default class ObjectUtils {
   /**
    * Flatten un objet nested en un objet avec un seul niveau avec des noms de propriétés transformées comme cela 'foo.bar'
@@ -138,4 +139,15 @@ export default class ObjectUtils {
         return obj
       }, {})
   }
+
+  /**
+   * Créé un hash à partir d'un objet
+   * (après l'avoir trié selon ses clés, et converti en json sans espace)
+   *
+   * @param obj
+   */
+  static async hash(obj: object): Promise<string> {
+    const sortedObject = this.sortObjectsByKey(_.cloneDeep(obj))
+    return await StringUtils.hash(JSON.stringify(sortedObject), 'SHA-1')
+  }
 }

+ 19 - 0
services/utils/stringUtils.ts

@@ -1,3 +1,4 @@
+
 export default class StringUtils {
   /**
    * Normalise une chaine de caractères en retirant la casse et les caractères spéciaux, à des fins de recherche
@@ -25,4 +26,22 @@ export default class StringUtils {
   public static parseInt(s: string | number) {
     return typeof s === 'number' ? s : parseInt(s)
   }
+
+  /**
+   * Hash une chaine de caractères avec l'algorithme demandé
+   *
+   * @param input
+   * @param algorithm
+   */
+  public static async hash(input: string, algorithm: string = 'SHA-256') {
+    const textAsBuffer = new TextEncoder().encode(input)
+
+    const hashBuffer = await window.crypto.subtle.digest(
+      algorithm,
+      textAsBuffer,
+    )
+
+    const hashArray = Array.from(new Uint8Array(hashBuffer))
+    return hashArray.map((item) => item.toString(16).padStart(2, '0')).join('')
+  }
 }

File diff ditekan karena terlalu besar
+ 393 - 184
yarn.lock


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini