Sfoglia il codice sorgente

Remove cached requesting contacts who are blocked.

JC Brand 3 mesi fa
parent
commit
32ab84efc0

+ 53 - 24
src/headless/plugins/blocklist/plugin.js

@@ -3,83 +3,112 @@
  * @license Mozilla Public License (MPLv2)
  * @description Adds support for XEP-0191 Blocking Command
  */
-import _converse from '../../shared/_converse.js';
-import api from '../../shared/api/index.js';
-import converse from '../../shared/api/public.js';
+import _converse from "../../shared/_converse.js";
+import api from "../../shared/api/index.js";
+import converse from "../../shared/api/public.js";
 import log from "@converse/log";
-import Blocklist from './collection.js';
-import BlockedEntity from './model.js';
-import blocklist_api from './api.js';
+import Blocklist from "./collection.js";
+import BlockedEntity from "./model.js";
+import blocklist_api from "./api.js";
+import { rejectPresenceSubscription } from "../roster/utils.js";
 
 const { Strophe, sizzle } = converse.env;
 
-Strophe.addNamespace('BLOCKING', 'urn:xmpp:blocking');
+Strophe.addNamespace("BLOCKING", "urn:xmpp:blocking");
 
-converse.plugins.add('converse-blocklist', {
-    dependencies: ['converse-disco'],
+converse.plugins.add("converse-blocklist", {
+    /**
+     * @typedef {import('../roster/contact').default} RosterContact
+     * @typedef {import('../roster/contacts').default} RosterContacts
+     */
+
+    dependencies: ["converse-disco"],
 
     initialize() {
         const exports = { Blocklist, BlockedEntity };
         Object.assign(_converse.exports, exports);
         Object.assign(api, blocklist_api);
 
-        api.promises.add(['blocklistInitialized']);
+        api.promises.add(["blocklistInitialized"]);
+
+        api.listen.on(
+            "cachedRoster",
+            /** @param {RosterContacts} roster */
+            async (roster) => {
+                const domain = _converse.session.get("domain");
+                const blocking_supported = await api.disco.supports(Strophe.NS.BLOCKING, domain);
+                if (blocking_supported) {
+                    const blocklist = await api.blocklist.get();
+                    const requesting_contacts = roster.filter(
+                        /** @param {RosterContact} m */ (m) => m.get("requesting")
+                    );
+                    requesting_contacts.forEach(
+                        /** @param {RosterContact} m */ async (m) => {
+                            if (blocklist.get(m.get("jid"))) {
+                                rejectPresenceSubscription(m.get("jid"));
+                                m.destroy();
+                            }
+                        }
+                    );
+                }
+            }
+        );
 
         api.listen.on(
-            'getErrorAttributesForMessage',
+            "getErrorAttributesForMessage",
             /**
              * @param {import('shared/types').MessageAttributes} attrs
              * @param {import('shared/types').MessageErrorAttributes} new_attrs
              */
             (attrs, new_attrs) => {
-                if (attrs.errors.find((e) => e.name === 'blocked' && e.xmlns === `${Strophe.NS.BLOCKING}:errors`)) {
+                if (attrs.errors.find((e) => e.name === "blocked" && e.xmlns === `${Strophe.NS.BLOCKING}:errors`)) {
                     const { __ } = _converse;
-                    new_attrs.error = __('You are blocked from sending messages.');
+                    new_attrs.error = __("You are blocked from sending messages.");
                 }
                 return new_attrs;
             }
         );
 
-        api.listen.on('connected', () => {
+        api.listen.on("connected", () => {
             const connection = api.connection.get();
             connection.addHandler(
                 /** @param {Element} stanza */ (stanza) => {
-                    const bare_jid = _converse.session.get('bare_jid');
-                    const from = stanza.getAttribute('from');
+                    const bare_jid = _converse.session.get("bare_jid");
+                    const from = stanza.getAttribute("from");
                     if (Strophe.getBareJidFromJid(from ?? bare_jid) != bare_jid) {
                         log.warn(`Received a blocklist push stanza from a suspicious JID ${from}`);
                         return true;
                     }
 
                     const add_jids = sizzle(`block[xmlns="${Strophe.NS.BLOCKING}"] item`, stanza).map(
-                        /** @param {Element} item */ (item) => item.getAttribute('jid')
+                        /** @param {Element} item */ (item) => item.getAttribute("jid")
                     );
                     if (add_jids.length) api.blocklist.add(add_jids, false);
 
                     const remove_jids = sizzle(`unblock[xmlns="${Strophe.NS.BLOCKING}"] item`, stanza).map(
-                        /** @param {Element} item */ (item) => item.getAttribute('jid')
+                        /** @param {Element} item */ (item) => item.getAttribute("jid")
                     );
                     if (remove_jids.length) api.blocklist.remove(remove_jids, false);
 
                     return true;
                 },
                 Strophe.NS.BLOCKING,
-                'iq',
-                'set'
+                "iq",
+                "set"
             );
         });
 
-        api.listen.on('clearSession', () => {
+        api.listen.on("clearSession", () => {
             const { state } = _converse;
             if (state.blocklist) {
-                state.blocklist.clearStore({ 'silent': true });
+                state.blocklist.clearStore({ "silent": true });
                 window.sessionStorage.removeItem(state.blocklist.fetched_flag);
                 delete state.blocklist;
             }
         });
 
-        api.listen.on('discoInitialized', async () => {
-            const domain = _converse.session.get('domain');
+        api.listen.on("discoInitialized", async () => {
+            const domain = _converse.session.get("domain");
             if (await api.disco.supports(Strophe.NS.BLOCKING, domain)) {
                 _converse.state.blocklist = new _converse.exports.Blocklist();
             }

+ 1 - 1
src/headless/plugins/roster/contacts.js

@@ -324,7 +324,7 @@ class RosterContacts extends Collection {
          * See also the `cachedRoster` event further up, which gets called instead of
          * `roster` if its already in `sessionStorage`.
          * @event _converse#roster
-         * @type { Element }
+         * @type {Element}
          * @example _converse.api.listen.on('roster', iq => { ... });
          * @example _converse.api.waitUntil('roster').then(iq => { ... });
          */

+ 1 - 1
src/headless/plugins/roster/utils.js

@@ -213,7 +213,7 @@ export function onRosterContactsFetched () {
  * Reject or cancel another user's subscription to our presence updates.
  * @function rejectPresenceSubscription
  * @param {String} jid - The Jabber ID of the user whose subscription is being canceled
- * @param {String} message - An optional message to the user
+ * @param {String} [message] - An optional message to the user
  */
 export function rejectPresenceSubscription (jid, message) {
     const pres = $pres({to: jid, type: "unsubscribed"});

+ 2 - 2
src/headless/types/plugins/roster/utils.d.ts

@@ -25,8 +25,8 @@ export function onRosterContactsFetched(): void;
  * Reject or cancel another user's subscription to our presence updates.
  * @function rejectPresenceSubscription
  * @param {String} jid - The Jabber ID of the user whose subscription is being canceled
- * @param {String} message - An optional message to the user
+ * @param {String} [message] - An optional message to the user
  */
-export function rejectPresenceSubscription(jid: string, message: string): void;
+export function rejectPresenceSubscription(jid: string, message?: string): void;
 export type RosterContacts = import("./contacts").default;
 //# sourceMappingURL=utils.d.ts.map