GatherPress / gatherpress

Powering our community's event management needs.
https://wordpress.org/plugins/gatherpress/
GNU General Public License v2.0
82 stars 28 forks source link

Endless admin-ajax.php requests #605

Closed carstingaxion closed 5 months ago

carstingaxion commented 6 months ago

Describe the bug

For a couple of days now I had returning errors with my local network connection. This was strange enough, but I found out, that my pi-hole banned my device, because it made more than 1000 requests per 60s. Looking into the logs revealed, that it was indeed that local domain I was working on actually. But unfortunately the logs didn't tell me what particular URL was requested.

While day to day I realized no problems at all, except my network connection getting lost 10 times a day.

Today I had the first real contact with what pi-hole was complaining about. While debugging some JS inside the GatherPress blocks I saw multiple, repeating POST requests to admin-ajax.php

Bildschirmfoto vom 2024-03-13 17-17-14

After I did the typical Deactivate everything and search I was unlucky to find out, that it was GatherPress in the current 0.28.0 version that caused the issue.

I still have no clue what is causing the issue, but maybe someone else could reproduce this at first.

Steps to Reproduce

  1. Open an existing event post within the editor
  2. Hit F12 to open the dev-tools of your browser and open the Console tab
  3. Wait aprox. 60s to see the requests flooding your screen.

Screenshots, screen recording, code snippet

I took this recording to show, that even with no interaction at all, the requests start to happen after 60s round about.

You can skip the first 50s, nothing happens here.

https://github.com/GatherPress/gatherpress/assets/198883/75e0e447-6811-49e9-ae2c-36353654b86f

Environment information

WordPress information

`

wp-core

version: 6.5-RC2 site_language: en_GB user_language: en_GB timezone: +00:00 permalink: /%year%/%monthnum%/%postname%/ https_status: true multisite: false user_registration: 0 blog_public: 1 default_comment_status: open environment_type: production user_count: 2 dotorg_communication: true

wp-paths-sizes

wordpress_path: /shared/httpd/wpt/htdocs wordpress_size: loading... uploads_path: /shared/httpd/wpt/htdocs/wp-content/uploads uploads_size: loading... themes_path: /shared/httpd/wpt/htdocs/wp-content/themes themes_size: loading... plugins_path: /shared/httpd/wpt/htdocs/wp-content/plugins plugins_size: loading... database_size: loading... total_size: loading...

wp-dropins (1)

db.php: true

wp-active-theme

name: Twenty Twenty-Four (twentytwentyfour) version: 1.0 author: the WordPress team author_website: https://en-gb.wordpress.org parent_theme: none theme_features: core-block-patterns, post-thumbnails, responsive-embeds, editor-styles, html5, automatic-feed-links, widgets-block-editor, block-templates theme_path: /shared/httpd/wpt/htdocs/wp-content/themes/twentytwentyfour auto_update: Disabled

wp-themes-inactive (13)

Twenty Eleven: version: 4.5, author: the WordPress team, Auto-updates disabled Twenty Fifteen: version: 3.6, author: the WordPress team, Auto-updates disabled Twenty Fourteen: version: 3.8, author: the WordPress team, Auto-updates disabled Twenty Nineteen: version: 2.7, author: WordPress Team, Auto-updates disabled Twenty Seventeen: version: 3.5, author: the WordPress team, Auto-updates disabled Twenty Sixteen: version: 3.1, author: The WordPress Team, Auto-updates disabled Twenty Ten: version: 4.0, author: the WordPress team, Auto-updates disabled Twenty Thirteen: version: 4.0, author: the WordPress team, Auto-updates disabled Twenty Twelve: version: 4.1, author: the WordPress team, Auto-updates disabled Twenty Twenty: version: 2.5, author: the WordPress team, Auto-updates disabled Twenty Twenty-One: version: 2.1, author: the WordPress team, Auto-updates disabled Twenty Twenty-Three: version: 1.3, author: the WordPress team, Auto-updates disabled Twenty Twenty-Two: version: 1.6, author: the WordPress team, Auto-updates disabled

wp-mu-plugins (0)

wp-plugins-active (3)

GatherPress: version: 0.28.0, author: The GatherPress Community, Auto-updates disabled Query Monitor: version: 3.15.0, author: John Blackbourn, Auto-updates disabled WordPress Beta Tester: version: 3.5.5, author: WordPress Upgrade/Install Team, Auto-updates disabled

wp-plugins-inactive (9)

Advanced Query Loop: version: 2.1.0, author: Ryan Welcher, Auto-updates disabled Akismet Anti-spam: Spam Protection: version: 5.3.1, author: Automattic - Anti-spam Team, Auto-updates disabled GatherPress: version: 0.28.0, author: The GatherPress Community, Auto-updates disabled Gatherpress Interactive Block: version: 0.1.0, author: The WordPress Contributors, Auto-updates disabled GatherPress Query Loop: version: 2.1.0, author: Ryan Welcher, Auto-updates disabled Gutenberg: version: 17.9.0-rc.1, author: Gutenberg Team (latest version: 17.9.0), Auto-updates disabled Heartbeat Control by WP Rocket: version: 2.0.1, author: WP Rocket, Auto-updates disabled Theater: version: 0.18.3, author: Jeroen Schmit (latest version: 0.18.4), Auto-updates disabled Theater Production Blocks: version: 0.2.0, author: figuren.theater, Auto-updates disabled

wp-media

image_editor: WP_Image_Editor_Imagick imagick_module_version: 1691 imagemagick_version: ImageMagick 6.9.11-60 Q16 x86_64 2021-01-25 https://imagemagick.org imagick_version: 3.7.0 file_uploads: 1 post_max_size: 72M upload_max_filesize: 64M max_effective_size: 64 MB max_file_uploads: 20 imagick_limits: imagick::RESOURCETYPE_AREA: 122 MB imagick::RESOURCETYPE_DISK: 1073741824 imagick::RESOURCETYPE_FILE: 786432 imagick::RESOURCETYPE_MAP: 512 MB imagick::RESOURCETYPE_MEMORY: 256 MB imagick::RESOURCETYPE_THREAD: 1 imagick::RESOURCETYPE_TIME: 9.2233720368548E+18 imagemagick_file_formats: 3FR, 3G2, 3GP, AAI, AI, APNG, ART, ARW, AVI, AVIF, AVS, BGR, BGRA, BGRO, BIE, BMP, BMP2, BMP3, BRF, CAL, CALS, CANVAS, CAPTION, CIN, CIP, CLIP, CMYK, CMYKA, CR2, CR3, CRW, CUR, CUT, DATA, DCM, DCR, DCX, DDS, DFONT, DNG, DPX, DXT1, DXT5, EPDF, EPI, EPS, EPS2, EPS3, EPSF, EPSI, EPT, EPT2, EPT3, ERF, FAX, FILE, FITS, FRACTAL, FTP, FTS, G3, G4, GIF, GIF87, GRADIENT, GRAY, GRAYA, GROUP4, H, HALD, HDR, HEIC, HISTOGRAM, HRZ, HTM, HTML, HTTP, HTTPS, ICB, ICO, ICON, IIQ, INFO, INLINE, IPL, ISOBRL, ISOBRL6, J2C, J2K, JBG, JBIG, JNG, JNX, JP2, JPC, JPE, JPEG, JPG, JPM, JPS, JPT, JSON, K25, KDC, LABEL, M2V, M4V, MAC, MAGICK, MAP, MASK, MAT, MATTE, MEF, MIFF, MKV, MNG, MONO, MOV, MP4, MPC, MPG, MRW, MSL, MTV, MVG, NEF, NRW, NULL, ORF, OTB, OTF, PAL, PALM, PAM, PATTERN, PBM, PCD, PCDS, PCL, PCT, PCX, PDB, PDF, PDFA, PEF, PES, PFA, PFB, PFM, PGM, PGX, PICON, PICT, PIX, PJPEG, PLASMA, PNG, PNG00, PNG24, PNG32, PNG48, PNG64, PNG8, PNM, POCKETMOD, PPM, PREVIEW, PS, PS2, PS3, PSB, PSD, PTIF, PWP, RADIAL-GRADIENT, RAF, RAS, RAW, RGB, RGBA, RGBO, RGF, RLA, RLE, RMF, RW2, SCR, SCT, SFW, SGI, SHTML, SIX, SIXEL, SPARSE-COLOR, SR2, SRF, STEGANO, SUN, TEXT, TGA, THUMBNAIL, TIFF, TIFF64, TILE, TIM, TTC, TTF, TXT, UBRL, UBRL6, UIL, UYVY, VDA, VICAR, VID, VIDEO, VIFF, VIPS, VST, WBMP, WEBM, WEBP, WMV, WPG, X, X3F, XBM, XC, XCF, XPM, XPS, XV, XWD, YCbCr, YCbCrA, YUV gd_version: bundled (2.1.0 compatible) gd_formats: GIF, JPEG, PNG, WebP, BMP, AVIF, XPM ghostscript_version: 9.53.3

wp-server

server_architecture: Linux 6.5.0-25-generic x86_64 httpd_software: Apache/2.4.54 (Unix) OpenSSL/3.0.7 php_version: 8.2.1 64bit php_sapi: fpm-fcgi max_input_variables: 8000 time_limit: 120 memory_limit: 512M max_input_time: 120 upload_max_filesize: 64M php_post_max_size: 72M curl_version: 7.74.0 OpenSSL/1.1.1n suhosin: false imagick_availability: true pretty_permalinks: true htaccess_extra_rules: false current: 2024-03-13T16:27:37+00:00 utc-time: Wednesday, 13-Mar-24 16:27:37 UTC server-time: 2024-03-13T16:27:36+00:00

wp-database

extension: mysqli server_version: 5.7.41-log client_version: mysqlnd 8.2.1 max_allowed_packet: 4194304 max_connections: 151

wp-constants

WP_HOME: undefined WP_SITEURL: undefined WP_CONTENT_DIR: /shared/httpd/wpt/htdocs/wp-content WP_PLUGIN_DIR: /shared/httpd/wpt/htdocs/wp-content/plugins WP_MEMORY_LIMIT: 40M WP_MAX_MEMORY_LIMIT: 512M WP_DEBUG: false WP_DEBUG_DISPLAY: true WP_DEBUG_LOG: false SCRIPT_DEBUG: false WP_CACHE: false CONCATENATE_SCRIPTS: undefined COMPRESS_SCRIPTS: undefined COMPRESS_CSS: undefined WP_ENVIRONMENT_TYPE: Undefined WP_DEVELOPMENT_MODE: undefined DB_CHARSET: utf8mb4 DB_COLLATE: utf8mb4_unicode_520_ci

wp-filesystem

wordpress: writable wp-content: writable uploads: writable plugins: writable themes: writable mu-plugins: writable

`

Code of Conduct

carstingaxion commented 6 months ago

This is not happening when editing a venue post.

carstingaxion commented 5 months ago

Yeah!!

I was able to isolate the anoying error, at least down to this script.

https://github.com/GatherPress/gatherpress/blob/70cdbf9ea08b2e5b69e7781a69f84b3f55bbfeb3/includes/core/classes/class-assets.php#L158-L167

When I comment out those lines, the error will not occur.

Another, maybe minor, strange finding was the self-closing <div /> tag of the modal. My browser and me are unsure, if this is really supported outside of react.

Bildschirmfoto vom 2024-03-20 22-18-45

carstingaxion commented 5 months ago

This is the culprit:

createRoot(modalWrapper).render(<EventCommuncationModal />);

I went through src/modals/email-communication/index.js almost line by line and disabled parts until I ended up with a completely commented function. With this file running, the described error still occurs.

But because I have absolutely no clue, I would love to get some help at this point. git blame suggested @mauteri as the most promising person to ask :wink:

My file looked like this in the end:

/**
 * WordPress dependencies.
 */
import { __, _x } from '@wordpress/i18n';
import domReady from '@wordpress/dom-ready';
import { createRoot, useState, useEffect } from '@wordpress/element';
// import {
//  Button,
//  CheckboxControl,
//  Flex,
//  FlexItem,
//  Modal,
//  TextareaControl,
// } from '@wordpress/components';
// import apiFetch from '@wordpress/api-fetch';

// /**
//  * Internal dependencies.
//  */
// import { Listener } from '../../helpers/broadcasting';
// import { getFromGlobal } from '../../helpers/globals';

/**
 * A modal component for notifying event members via email.
 *
 * This component provides a modal for event organizers to send email notifications
 * to specific groups of event members, such as attendees, waiting list members, or those
 * who have not indicated attendance.
 *
 * @since 1.0.0
 *
 * @return {JSX.Element} The JSX element for the Event Communication Modal.
 */
const EventCommuncationModal = () => {
/*  const [isOpen, setOpen] = useState(false);
    const [isAllChecked, setAllChecked] = useState(false);
    const [isAttendingChecked, setAttendingChecked] = useState(false);
    const [isWaitingListChecked, setWaitingListChecked] = useState(false);
    const [isNotAttendingChecked, setNotAttendingChecked] = useState(false);
    const [isCheckBoxDisabled, setCheckBoxDisabled] = useState(false);
    const [buttonDisabled, setButtonDisabled] = useState(false);
    const [message, setMessage] = useState('');
    const closeModal = () => setOpen(false);
    const sendMessage = () => {
        if (
            global.confirm(__('Confirm you are ready to send?', 'gatherpress'))
        ) {
            apiFetch({
                path: getFromGlobal('urls.eventRestApi') + '/email',
                method: 'POST',
                data: {
                    post_id: getFromGlobal('eventDetails.postId'),
                    message,
                    send: {
                        all: isAllChecked,
                        attending: isAttendingChecked,
                        waiting_list: isWaitingListChecked,
                        not_attending: isNotAttendingChecked,
                    },
                    _wpnonce: getFromGlobal('misc.nonce'),
                },
            }).then((res) => {
                if (res.success) {
                    closeModal();
                    setMessage('');
                    setAllChecked(false);
                    setAttendingChecked(false);
                    setWaitingListChecked(false);
                    setNotAttendingChecked(false);
                }
            });
        }
    };

    useEffect(() => {
        if (isAllChecked) {
            setCheckBoxDisabled(true);
            setAttendingChecked(false);
            setWaitingListChecked(false);
            setNotAttendingChecked(false);
        } else {
            setCheckBoxDisabled(false);
        }

        if (
            !isAllChecked &&
            !isAttendingChecked &&
            !isWaitingListChecked &&
            !isNotAttendingChecked
        ) {
            setButtonDisabled(true);
        } else {
            setButtonDisabled(false);
        }
    }, [
        isAllChecked,
        isAttendingChecked,
        isWaitingListChecked,
        isNotAttendingChecked,
    ]);
 */
    // Listener({ setOpen });

    return (
        <>
            {/* {isOpen && (
                <Modal
                    title={__('Notify members via email', 'gatherpress')}
                    onRequestClose={closeModal}
                    shouldCloseOnClickOutside={false}
                >
                    <TextareaControl
                        label={__('Optional message', 'gatherpress')}
                        value={message}
                        onChange={(value) => setMessage(value)}
                    />
                    <p className="description">
                        {__(
                            'Select the recipients for your message by checking the relevant boxes.',
                            'gatherpress'
                        )}
                    </p>
                    <Flex gap="8">
                        <FlexItem>
                            <CheckboxControl
                                label={_x(
                                    'All Members',
                                    'List Status',
                                    'gatherpress'
                                )}
                                checked={isAllChecked}
                                onChange={setAllChecked}
                            />
                        </FlexItem>
                        <FlexItem>
                            <CheckboxControl
                                label={_x(
                                    'Attending',
                                    'List Status',
                                    'gatherpress'
                                )}
                                checked={isAttendingChecked}
                                onChange={setAttendingChecked}
                                disabled={isCheckBoxDisabled}
                            />
                        </FlexItem>
                        <FlexItem>
                            <CheckboxControl
                                label={_x(
                                    'Waiting List',
                                    'List Status',
                                    'gatherpress'
                                )}
                                checked={isWaitingListChecked}
                                onChange={setWaitingListChecked}
                                disabled={isCheckBoxDisabled}
                            />
                        </FlexItem>
                        <FlexItem>
                            <CheckboxControl
                                label={_x(
                                    'Not Attending',
                                    'List Status',
                                    'gatherpress'
                                )}
                                checked={isNotAttendingChecked}
                                onChange={setNotAttendingChecked}
                                disabled={isCheckBoxDisabled}
                            />
                        </FlexItem>
                    </Flex>
                    <br />
                    <Button
                        variant="primary"
                        onClick={sendMessage}
                        disabled={buttonDisabled}
                    >
                        {__('Send Email', 'gatherpress')}
                    </Button>
                </Modal>
            )} */}
        </>
    );
};

domReady(() => {
    const modalWrapper = document.getElementById(
        'gp-event-communication-modal'
    );
    if (modalWrapper) {
        createRoot(modalWrapper).render(<EventCommuncationModal />);
    }
});
mauteri commented 5 months ago

Thanks @carstingaxion! I'll have to dig into this a bit and get back to you with more info on this.

mauteri commented 5 months ago

Another, maybe minor, strange finding was the self-closing <div /> tag of the modal. My browser and me are unsure, if this is really supported outside of react.

Bildschirmfoto vom 2024-03-20 22-18-45

I think this may be valid in XHTML as a self closing div, but maybe not as valid in HTML5. Let's try to make this <div id="gp-event-communication-modal"></div> and see if that corrects the issue. I wasn't able to replicate the issue in Chrome (are you?) I can try in FF and see if I can reproduce there.

mauteri commented 5 months ago

@carstingaxion it is that self-closing div tag that is the culprit. I guess this is only "okay" to do in XHTML, but HTML5 it is handled differently (at least in FireFox). Very much a TIL moment, and definitely shows my age as I'm still remembering things that were fine in XHTML (LOL).

PR that fixes the issue: https://github.com/GatherPress/gatherpress/pull/619