From 2bbf606f3053b6b62d980ee415260bc05142bd5b Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Tue, 11 Jun 2024 02:48:37 +0200 Subject: [PATCH] Fix User ... lacks permission to update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correction de l'erreur qui était affichée chez les joueurs lors de hooks utilisés pour effectuer des modifications sur des documents: - ChatMessage, ajout de flags pour l'heure - Item au sein d'un Actor pour mettre à jour certains éléments --- module/achat-vente/chat-vente.js | 35 ++++++++++++++------------------ module/actor.js | 4 ++-- module/actor/base-actor.js | 14 +++++-------- module/chat-utility.js | 11 +++++----- module/misc.js | 34 ++++++++++++++++++++++++++----- 5 files changed, 57 insertions(+), 41 deletions(-) diff --git a/module/achat-vente/chat-vente.js b/module/achat-vente/chat-vente.js index 76d69d9f..604500f0 100644 --- a/module/achat-vente/chat-vente.js +++ b/module/achat-vente/chat-vente.js @@ -38,10 +38,22 @@ export class ChatVente { return foundry.utils.mergeObject(detail, { acheteur }) } + static async diminuerQuantiteAchatVente(chatMessageId, quantite) { + const chatMessage = game.messages.get(chatMessageId) + const vente = ChatVente.getDetailVente(chatMessageId) + vente.nbLots = Math.max(0, vente.nbLots - quantite) + await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) - static async setDetailAchatVente(chatMessage, vente) { - await chatMessage?.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) - await chatMessage?.setFlag(SYSTEM_RDD, DETAIL_VENTE, { + const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente); + chatMessage.update({ content: html }); + chatMessage.render(true); + } + + static async displayAchatVente(vente) { + const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente); + const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html)) + await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) + await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, { item: vente.item, properties: vente.item.getProprietes(), vendeurId: vente.vendeurId, @@ -50,21 +62,4 @@ export class ChatVente { prixLot: vente.prixLot }) } - - static async diminuerQuantite(chatMessageId, quantite) { - const chatMessage = game.messages.get(chatMessageId) - const vente = ChatVente.getDetailVente(chatMessageId) - vente.nbLots = Math.max(0, vente.nbLots - quantite) - await chatMessage?.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) - - const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente); - chatMessage.update({ content: html }); - chatMessage.render(true); - } - - static async displayAchatVente(venteData) { - const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', venteData); - const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html)) - await ChatVente.setDetailAchatVente(chatMessage, venteData) - } } \ No newline at end of file diff --git a/module/actor.js b/module/actor.js index c6146106..5fa1e100 100644 --- a/module/actor.js +++ b/module/actor.js @@ -2626,13 +2626,13 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async resetItemUse() { - await this.unsetFlag(SYSTEM_RDD, 'itemUse'); await this.setFlag(SYSTEM_RDD, 'itemUse', {}); } /* -------------------------------------------- */ async incDecItemUse(itemId, inc = 1) { - let itemUse = foundry.utils.duplicate(this.getFlag(SYSTEM_RDD, 'itemUse') ?? {}); + const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse'); + let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {}; itemUse[itemId] = (itemUse[itemId] ?? 0) + inc; await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse); console.log("ITEM USE INC", inc, itemUse); diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index 224b253a..65d93043 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -32,10 +32,10 @@ export class RdDBaseActor extends Actor { } static init() { - Hooks.on("preUpdateItem", (item, change, options, id) => RdDBaseActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id)); - Hooks.on("createItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onCreateItem(item, options, id)); - Hooks.on("deleteItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onDeleteItem(item, options, id)); - Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId)); + Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id)) + Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id)) + Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id)) + Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId)) } static onSocketMessage(sockmsg) { @@ -82,10 +82,6 @@ export class RdDBaseActor extends Actor { static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; }; - static getParentActor(document) { - return document?.parent instanceof Actor ? document.parent : undefined - } - /** * Cette methode surcharge Actor.create() pour ajouter si besoin des Items par défaut: * compétences et monnaies. @@ -381,7 +377,7 @@ export class RdDBaseActor extends Actor { ChatUtility.removeChatMessageId(achat.chatMessageIdVente); } else if (achat.chatMessageIdVente) { - await ChatVente.diminuerQuantite(achat.chatMessageIdVente, achat.choix.nombreLots) + await ChatVente.diminuerQuantiteAchatVente(achat.chatMessageIdVente, achat.choix.nombreLots) } } } diff --git a/module/chat-utility.js b/module/chat-utility.js index a4f1f96d..6e0386ff 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -149,14 +149,13 @@ export class ChatUtility { } static async setMessageData(chatMessage, key, flag) { - if (flag) { - await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(flag)); + if (flag && chatMessage.isAuthor) { + await chatMessage.setFlag(SYSTEM_RDD, key, flag) } } static getMessageData(chatMessage, key) { - const json = chatMessage.getFlag(SYSTEM_RDD, key); - return json ? JSON.parse(json) : undefined; + return chatMessage.getFlag(SYSTEM_RDD, key); } static getChatMessage(event) { @@ -175,6 +174,8 @@ export class ChatUtility { } static async onCreateChatMessage(chatMessage, options, id) { - await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); + if (chatMessage.isAuthor) { + await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); + } } } diff --git a/module/misc.js b/module/misc.js index c3e6c232..2f1cbf64 100644 --- a/module/misc.js +++ b/module/misc.js @@ -166,15 +166,39 @@ export class Misc { } static firstConnectedGM() { - return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active); + return game.users.sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active); + } + static connectedGMs() { + return game.users.filter(u => u.isGM && u.active); } - static isOwnerPlayer(actor, user = undefined) { - return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER) + /** + * This helper method allows to get the docuument, for a single user (either first connected GM, or the owner + * if there is no connected GMs), or else return undefined. + * + * This allows for example update hooks that should apply modifications to actors to be called only for one + * user (preventing the "User ... lacks permission to update Item" that was occuring on hooks when Item updates + * were triggering other changes) + * + * @param {*} document the Document with is potentially an Actor + * @returns the actor if either the game.user is the first connected GM, or if the game.user is the owner + * and there is no connected GM + */ + static documentIfResponsible(document) { + if (document instanceof Document) { + if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) { + return document + } + } + return undefined } - static isOwnerPlayerOrUniqueConnectedGM(actor, user = undefined) { - return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM(); + static isOwnerPlayer(actor) { + return actor.testUserPermission(game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER) + } + + static isOwnerPlayerOrUniqueConnectedGM(actor) { + return Misc.isOwnerPlayer(actor) ?? Misc.isUniqueConnectedGM(); } /**