import IdentityManager from './identity-manager.js'
/** Gère l'assocation des identity-manager au resource (layer, control, service...)
* Permet de mutualiser les identity-manager entre plusieurs resources
*/
export default class IdentityManagerPool {
/**
* @ type {Map<String, {identityManager: IdentityManager, resources: Array<{resourceType: String, resourceId: String}>}>}
*/
#identityManager = new Map()
/**
*
* @param {String} resourceType type de resource (layer, control, service...)
* @param {String} resourceId identifiant de la resource
* @param {import("./identity-manager.js").identityOptions | String} identityOptions options de gestion d'identité ou token en clair (historique)
* @returns {IdentityManager}
*/
async addIdentitySource (resourceType, resourceId, identityOptions) {
const identityManagerKey = this.#getIdentityManagerKey(identityOptions)
if (!this.#identityManager.has(identityManagerKey)) {
// si le identity manager n'existe pas, on le crée
const identityManager = new IdentityManager(identityOptions)
this.#identityManager.set(identityManagerKey, {
identityManager,
resources: [{ resourceType, resourceId }],
})
} else {
// on ajoute la resource à la liste des resources utilisant ce identity manager
const identityManagerEntry = this.#identityManager.get(identityManagerKey)
identityManagerEntry.resources.push({ resourceType, resourceId })
}
return this.#identityManager.get(identityManagerKey).identityManager
}
/**
* supprime un identity manager et toutes les resources qui l'utilisent
* @param {import("./identity-manager.js").identityOptions | String} identityOptions options de gestion du token ou token en clair (historique)
* @returns {Boolean}
*/
removeIdentitySource (identityOptions) {
const identityManagerKey = this.#getIdentityManagerKey(identityOptions)
return this.#identityManager.delete(identityManagerKey)
}
/**
* Retire une source de la liste des resources utilisant un identity manager, si plus aucune resource n'utilise ce identity manager, on le supprime
* @param {String} resourceType type de resource (layer, control, service...)
* @param {String} resourceId identifiant de la resource
* @param {Boolean} [removeIdentityManagerIfNoResource=false] indique si l'identity manager doit être supprimé si aucune ressource ne l'utilise
*/
removeResource (resourceType, resourceId, removeIdentityManagerIfNoResource = false) {
for (const [key, entry] of this.#identityManager.entries()) {
const index = entry.resources.findIndex(r => r.resourceType === resourceType && r.resourceId === resourceId)
if (index !== -1) {
entry.resources.splice(index, 1)
// si plus aucune resource n'utilise ce identity manager, on le supprime
if (entry.resources.length === 0 && removeIdentityManagerIfNoResource) {
this.#identityManager.get(key).identityManager.destroy()
this.#identityManager.delete(key)
}
break
}
}
}
/**
* Est-ce que la clé de identity manager existe déjà?
* @param {import("./identity-manager.js").identityOptions | String} identityOptions options de gestion du d'identité ou token en clair (historique)
* @returns {Boolean}
*/
identitySourceExists (identityOptions) {
const identityManagerKey = this.#getIdentityManagerKey(identityOptions)
return this.#identityManager.has(identityManagerKey)
}
getIdentityManager (identityOptions) {
const identityManagerKey = this.#getIdentityManagerKey(identityOptions)
return this.#identityManager.has(identityManagerKey) ? this.#identityManager.get(identityManagerKey).identityManager : null
}
/**
* Stringify stable qui garantit le même résultat indépendamment de l'ordre des propriétés
* @param {*} obj
* @returns {String}
*/
#stableStringify (obj) {
if (obj === null || typeof obj !== 'object') {
return JSON.stringify(obj)
}
if (Array.isArray(obj)) {
return '[' + obj.map(item => this.#stableStringify(item)).join(',') + ']'
}
const keys = Object.keys(obj).sort()
const pairs = keys.map(key => {
return JSON.stringify(key) + ':' + this.#stableStringify(obj[key])
})
return '{' + pairs.join(',') + '}'
}
/**
* @param {import("./identity-manager.js").identityOptions | String} identityOptions options de gestion d'identité ou token en clair (historique)
* @returns {String}
*/
#getIdentityManagerKey (identityOptions) {
// génère une clé de gestionnaire d'identity, si c'est une chaine de caractère, on la prend telle quelle
// Sinon prend la propriété id
// sinon calcule une clé en fonction de la chaine
return typeof identityOptions === 'string'
? identityOptions
: identityOptions?.id
? identityOptions.id
: this.#stableStringify(identityOptions)
}
}