Making WordPress.org

Changeset 7737


Ignore:
Timestamp:
10/17/2018 11:01:37 PM (6 years ago)
Author:
iandunn
Message:

WordCamp Payments: Hide other users' payment files from non-admins.

See #3244

Location:
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/includes/privacy.php

    r7291 r7737  
    33namespace WordCamp\Budgets\Privacy;
    44
    5 use WP_Query;
     5use WP_Query, WP_Post;
    66use WordCamp\Budgets\Reimbursement_Requests;
     7use WCP_Payment_Request;
    78
    89defined( 'WPINC' ) || die();
    910
    1011
     12add_filter( 'the_posts',                          __NAMESPACE__ . '\hide_others_payment_files', 10, 2 );
    1113add_filter( 'wp_privacy_personal_data_exporters', __NAMESPACE__ . '\register_personal_data_exporters' );
    1214add_filter( 'wp_privacy_personal_data_erasers', __NAMESPACE__ . '\register_personal_data_erasers' );
     15
     16
     17/**
     18 * Prevent non-admins from viewing payment files uploaded by other users.
     19 *
     20 * The files sometimes have sensitive information, like account numbers etc. `the_posts` was chosen over
     21 * `ajax_query_attachments_args`, `pre_get_posts`, and other techniques, because it is the most comprehensive
     22 * and flexible solution. It will remove things from the Media Library, but also REST API endpoints, XML-RPC,
     23 * RSS, etc. It also allows the chance the to only apply the conditions to certain post types, whereas setting
     24 * query vars is much more limited.
     25 *
     26 * SECURITY WARNING: When querying attachments `get_posts()`, make sure you pass `suppress_filters => false`,
     27 * otherwise this will not run.
     28 *
     29 * @param WP_Post[] $attachments
     30 * @param WP_Query  $wp_query
     31 *
     32 * @return array
     33 */
     34function hide_others_payment_files( $attachments, $wp_query ) {
     35    $user = wp_get_current_user();
     36
     37    if ( 'attachment' !== $wp_query->get( 'post_type' ) || in_array( 'administrator', $user->roles, true ) ) {
     38        return $attachments;
     39    }
     40
     41    $payment_posts_ids = get_payment_file_parent_ids( $attachments );
     42
     43    foreach ( $attachments as $index => $attachment ) {
     44        if ( ! in_array( $attachment->post_parent, $payment_posts_ids, true ) ) {
     45            continue;
     46        }
     47
     48        if ( $attachment->post_author === $user->ID ) {
     49            continue;
     50        }
     51
     52        /*
     53         * The post is already cached from the request in `get_payment_file_parent_ids()`, so this doesn't create
     54         * a new database query, it's just a way to access the individual post directly instead of iterating through
     55         * `$payment_posts_with_attachments`.
     56         */
     57        $parent_author = (int) get_post( $attachment->post_parent )->post_author;
     58
     59        if ( $parent_author === $user->ID ) {
     60            continue;
     61        }
     62
     63        unset( $attachments[ $index ] );
     64    }
     65
     66    // Re-index the array, because WP_Query functions will assume there are no gaps.
     67    return array_values( $attachments );
     68}
     69
     70/**
     71 * Get the Reimbursement/Vendor Payment posts that are attached to the given media items.
     72 *
     73 * @param WP_Post[] $attachments
     74 *
     75 * @return int[]
     76 */
     77function get_payment_file_parent_ids( $attachments ) {
     78    $parent_ids     = array_unique( wp_list_pluck( $attachments, 'post_parent' ) );
     79    $orphaned_index = array_search( 0, $parent_ids, true );
     80
     81    // All payment files should be attached to a post, so unattached files can be removed.
     82    if ( false !== $orphaned_index ) {
     83        unset( $parent_ids[ $orphaned_index ] );
     84    }
     85
     86    $payment_posts_with_attachments = get_posts( array(
     87        'post__in'    => $parent_ids,
     88        'post_status' => 'any',
     89        'numberposts' => 1000,
     90        'post_type'   => array(
     91            Reimbursement_Requests\POST_TYPE,
     92            WCP_Payment_Request::POST_TYPE
     93        ),
     94    ) );
     95
     96    return wp_list_pluck( $payment_posts_with_attachments, 'ID' );
     97}
    1398
    1499/**
  • sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/includes/wordcamp-budgets.php

    r7488 r7737  
    956956            'orderby'        => 'title',
    957957            'order'          => 'ASC',
     958
     959            // Make sure that `WordCamp\Budgets\Privacy\hide_others_payment_files()` runs.
     960            'suppress_filters' => false,
    958961        ) );
    959962
  • sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/views/wordcamp-budgets/field-attached-files.php

    r2373 r7737  
    1717</h4>
    1818
     19<?php if ( ! current_user_can( 'manage_options' ) ) : ?>
     20    <p>
     21        <em><?php _e( 'Note: Files uploaded by other users are hidden to protect privacy.', 'wordcamporg' ); ?></em>
     22    </p>
     23<?php endif; ?>
     24
    1925<ul class="wcb_files_list loading-content">
    2026    <li>
Note: See TracChangeset for help on using the changeset viewer.