brettkrueger / multisite-rest-api

Adds several REST API endpoints for multisite management.
https://wordpress.org/plugins/multisite-rest-api/
GNU General Public License v3.0
32 stars 12 forks source link

CREATE POST METHOD never triggered #3

Closed crapthings closed 4 years ago

crapthings commented 4 years ago

i think we can just check if its a GET or POST

$_SERVER['REQUEST_METHOD'] === 'GET'
if($_SERVER['REQUEST_METHOD'] === 'GET' && preg_match("/sites\/?/", $route, $matches)) {
        if(($params["blog_id"]) || (preg_match("/sites\/\d\/?/", $route, $matches))) {
          if(! is_user_member_of_blog($user, $site_id)) {
            return rest_ensure_response('Invalid user permissions.');
          } else {
            return rest_ensure_response( get_site( $site_id ));
          }
        }
        #elseif(preg_match("/sites\/?$/", $route, $matches)) {
          #if(! current_user_can('create_sites')) {
            #$user_sites = get_blogs_of_user( $user );
            #return rest_ensure_response( get_sites( $user_sites ));
          #} else {
            #return rest_ensure_response( get_sites());
          #}
        #}
      }

https://github.com/brettkrueger/multisite-rest-api/blob/master/multisite-rest-api.php#L78

brettkrueger commented 4 years ago

Nice! This is looking good. Thank you. Do you know if there is a way to get this to work with all sites as well? I'll work on that on this end as well, but if you have any ideas already, let me know!

As it is now, the reason there's the if and elseif clause for sites is just to ensure that if no digit is provided, it will display all sites that a user has access to (and if they are a superadmin, all sites), but I am certain that there is a better way to go about it than I am doing. The setup for the endpoints also limits which methods the endpoint will actually accept, so I'm not totally sure if we need the extra redundancy during the endpoint if/else. Let me know your thoughts!

I noticed you had opened a question about the create site POST request not working earlier (sorry about the delay) but I can't seem to find that now. Were you able to get that working, or is that related to the title of this issue? If not, feel free to open that again and I'll take a look!

crapthings commented 4 years ago

hey @brettkrueger thanks for this plugin and sorry about my english, i try to explain

As it is now, the reason there's the if and elseif clause for sites is just to ensure that if no digit is provided, it will display all sites that a user has access to (and if they are a superadmin, all sites), but I am certain that there is a better way to go about it than I am doing. The setup for the endpoints also limits which methods the endpoint will actually accept, so I'm not totally sure if we need the extra redundancy during the endpoint if/else. Let me know your thoughts!

yes, i think its okay, the issue is

GET sites/$site_id POST sites/create

are similar pattern, but the Request Method is different

I noticed you had opened a question about the create site POST request not working earlier (sorry about the delay) but I can't seem to find that now. Were you able to get that working, or is that related to the title of this issue? If not, feel free to open that again and I'll take a look!

i think that issue is relate this one somehow, i've tried serval auth plugin and found they doesn't play well with currently, the POST sites/create will always match GET /sites/$site_id, and then it checks current user has permission or not, but when it failed. it has no response at all.

https://github.com/brettkrueger/multisite-rest-api/blob/master/multisite-rest-api.php#L78

if(preg_match("/sites\/?/", $route, $matches)) {
        if(($params["blog_id"]) || (preg_match("/sites\/\d\/?/", $route, $matches))) {
          if(! is_user_member_of_blog($user, $site_id)) {
            return rest_ensure_response('Invalid user permissions.');
          } else {
            return rest_ensure_response( get_site( $site_id ));
          }
        }
        elseif(preg_match("/sites\/?$/", $route, $matches)) {
          if(! current_user_can('create_sites')) {
            $user_sites = get_blogs_of_user( $user );
            return rest_ensure_response( get_sites( $user_sites ));
          } else {
            return rest_ensure_response( get_sites());
          }
        } else {
            return rest_ensure_response('something wrong with auth');
        }
      }

some plugin i've tried was JWT one that you mention on README

WordPress REST API Authentication (free version) Application Passwords

they all failed same way (empty response)

for now i modify your code and make it work temporary.

<?php
/**
 * Plugin Name: Multisite Rest API
 * Plugin URI: https://krux.us/multisite-rest-api/
 * Description: Adds multisite functionality to Rest API
 * Version: 1.0
 * Author: Brett Krueger
 * Author URI: https://krux.us
 */

/* Setup routes for site management */

add_action( 'rest_api_init', function () {
  register_rest_route('wp/v2', '/sites/?(?P<blog_id>\d+)?', [
    'methods'  => "GET",
    'callback' => 'wmra_sites_callback',
    'args' => [
      'blog_id',
    ],
  ]);
});

add_action( 'rest_api_init', function () {
  $now = current_time( 'mysql', true );
  register_rest_route('wp/v2', '/sites/create', [
    'methods'  => "POST",
    'callback' => 'wmra_sites_callback',
    'args' => [
      'domain',
      'path',
      'network_id'   => get_current_network_id(),
      'registered'   => $now,
      'last_updated' => $now,
      'public'       => 1,
      'archived'     => 0,
      'mature'       => 0,
      'spam'         => 0,
      'deleted'      => 0,
      'lang_id'      => 0,
    ],
  ]);
});

add_action( 'rest_api_init', function () {
  register_rest_route('wp/v2', '/sites/update', [
    'methods'  => "PUT",
    'callback' => 'wmra_sites_callback',
    'args' => [
      'blog_id',
      'option',
      'value',
    ],
  ]);
});

add_action( 'rest_api_init', function () {
  register_rest_route('wp/v2', '/sites/delete/?(?P<blog_id>\d+)?', [
    'methods'  => "DELETE",
    'callback' => 'wmra_sites_callback',
    'args' => [
      'blog_id',
    ],
  ]);
});
/* End Site Route setup */

/* Begin Sites Callback */
function wmra_sites_callback( $request ) {
    if ( is_multisite() ) {
      $params = $request->get_params();
      $route = $request->get_route();
      $user = get_current_user_id();
      if(! $params["blog_id"]) {
        $site_id = explode('/', $matches[0])[1];
      } else {
        $site_id = $params["blog_id"];
      }
      if($_SERVER['REQUEST_METHOD'] === 'GET' && preg_match("/sites\/?/", $route, $matches)) {
        if(($params["blog_id"]) || (preg_match("/sites\/\d\/?/", $route, $matches))) {
          if(! is_user_member_of_blog($user, $site_id)) {
            return rest_ensure_response('Invalid user permissions.');
          } else {
            return rest_ensure_response( get_site( $site_id ));
          }
        }
        elseif(preg_match("/sites\/?$/", $route, $matches)) {
          if(! current_user_can('create_sites')) {
            $user_sites = get_blogs_of_user( $user );
            return rest_ensure_response( get_sites( $user_sites ));
          } else {
            return rest_ensure_response( get_sites());
          }
        }
      }
      elseif (preg_match("/sites\/create/", $route, $matches)) {
      $apikey = "apikey";
      $params["domain"] = $params["domain"] ?? "mydomain.com";
        if($params["apikey"] != $apikey){
          return rest_ensure_response('Invalid user permissions.');
          die();
        } else {
          if(! $params["domain"]) {
            return rest_ensure_response('You must provide a domain.');
            die();
          } else {
            $domain = $params["domain"];
          }
          if(! $params["path"]) {
            $path = '/';
          } else {
            $path = $params["path"];
          }
          if (! $params["title"]) {
            $title = $domain;
          } else {
            $title = $params["title"];
          }
          if (! $params["user_id"]) {
            $user_id = $user;
          } else {
            $user_id = $params["user_id"];
          }
          $options = [
            "admin_email" => $params["admin_email"],
          ];
          return rest_ensure_response(wpmu_create_blog($domain, $path, $title, $user_id, $options));
        }
      }
      elseif (preg_match("/sites\/update/", $route, $matches)) {
        if(! current_user_can('update_sites')){
          return rest_ensure_response('Invalid user permissions.');
          die();
        } else {
          $option = $params["option"];
          $value = $params["value"];
          return rest_ensure_response(update_blog_option($site_id, $option, $value));
        }
        return $route;
      }
      elseif (preg_match("/sites\/delete/", $route, $matches)) {
        if(! current_user_can('delete_sites')){
          return rest_ensure_response('Invalid user permissions.');
          die();
        } else {
          return rest_ensure_response(wp_delete_site($site_id));
        }
        return $route;
      }
      else {
        return rest_ensure_response('Invalid REST Route.');
        die();
      }
    } else {
      return rest_ensure_response('This is not a Multisite install. Please enable Multisite to make use of this endpoint.');
      die();
    }
}
/* End Sites Callback */

?>

and it did create site for me

brettkrueger commented 4 years ago

Awesome, thank you so much for this! I'll go ahead and review it and work to implement a fix (likely your fix, if you wanted to make a PR and get the contributor credit aside from my thanks!)

brettkrueger commented 4 years ago

Both this and #4 are resolved in PR https://github.com/brettkrueger/multisite-rest-api/commit/0cf85f5e43e6ae34b34cf596e4f049ccb91ef495 now. Let me know if anything else comes up. Your input on this is very appreciated!

I'll be working on converting the if/else statements to a switch case to help with future potential issues. Cheers!