Add Oribi Sync plugin for syncing WordPress pages and theme files from a Git repository
- Implement encryption helpers for storing and retrieving the Personal Access Token (PAT). - Create REST API endpoints for triggering sync, checking sync status, and handling webhooks. - Develop the sync engine to fetch pages from the Git repository, create/update WordPress pages, and trash removed pages. - Add functionality for previewing and applying theme files from the repository. - Set up plugin activation and deactivation hooks to manage default options and scheduled tasks. - Implement uninstall routine to clean up plugin options and metadata from posts.
This commit is contained in:
105
includes/rest.php
Normal file
105
includes/rest.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* Oribi Sync — REST API endpoints.
|
||||
*
|
||||
* POST /wp-json/oribi-sync/v1/sync — Trigger a sync
|
||||
* POST /wp-json/oribi-sync/v1/sync — With ?dry_run=1 for preview
|
||||
* GET /wp-json/oribi-sync/v1/status — Get last sync status
|
||||
* POST /wp-json/oribi-sync/v1/webhook — Webhook trigger (secret-based auth)
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
add_action( 'rest_api_init', function () {
|
||||
|
||||
// ── Trigger sync ──────────────────────────────────────────────────────
|
||||
register_rest_route( 'oribi-sync/v1', '/sync', [
|
||||
'methods' => 'POST',
|
||||
'callback' => 'oribi_sync_rest_sync',
|
||||
'permission_callback' => function () {
|
||||
return current_user_can( 'manage_options' );
|
||||
},
|
||||
] );
|
||||
|
||||
// ── Sync status ───────────────────────────────────────────────────────
|
||||
register_rest_route( 'oribi-sync/v1', '/status', [
|
||||
'methods' => 'GET',
|
||||
'callback' => 'oribi_sync_rest_status',
|
||||
'permission_callback' => function () {
|
||||
return current_user_can( 'manage_options' );
|
||||
},
|
||||
] );
|
||||
|
||||
// ── Webhook (secret-based auth, no WP login required) ─────────────────
|
||||
register_rest_route( 'oribi-sync/v1', '/webhook', [
|
||||
'methods' => 'POST',
|
||||
'callback' => 'oribi_sync_rest_webhook',
|
||||
'permission_callback' => '__return_true', // Auth handled in callback
|
||||
] );
|
||||
} );
|
||||
|
||||
/**
|
||||
* REST: Trigger sync.
|
||||
*/
|
||||
function oribi_sync_rest_sync( WP_REST_Request $request ): WP_REST_Response {
|
||||
$dry_run = (bool) $request->get_param( 'dry_run' );
|
||||
$result = oribi_sync_run( $dry_run );
|
||||
|
||||
return new WP_REST_Response( $result, $result['ok'] ? 200 : 500 );
|
||||
}
|
||||
|
||||
/**
|
||||
* REST: Get last sync status.
|
||||
*/
|
||||
function oribi_sync_rest_status(): WP_REST_Response {
|
||||
return new WP_REST_Response( [
|
||||
'last_run' => get_option( 'oribi_sync_last_run', null ),
|
||||
'log' => array_slice( get_option( 'oribi_sync_log', [] ), 0, 5 ),
|
||||
'repo' => get_option( 'oribi_sync_repo', '' ),
|
||||
'branch' => get_option( 'oribi_sync_branch', 'main' ),
|
||||
'provider' => oribi_sync_get_provider(),
|
||||
'has_pat' => ! empty( get_option( 'oribi_sync_pat', '' ) ),
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* REST: Webhook trigger.
|
||||
*
|
||||
* Validates using a shared secret stored in the WP option oribi_sync_webhook_secret
|
||||
* or the constant ORIBI_SYNC_WEBHOOK_SECRET.
|
||||
*
|
||||
* Accepts GitHub-style X-Hub-Signature-256 header, or a simple
|
||||
* Authorization: Bearer <secret> header.
|
||||
*/
|
||||
function oribi_sync_rest_webhook( WP_REST_Request $request ): WP_REST_Response {
|
||||
$secret = defined( 'ORIBI_SYNC_WEBHOOK_SECRET' )
|
||||
? ORIBI_SYNC_WEBHOOK_SECRET
|
||||
: get_option( 'oribi_sync_webhook_secret', '' );
|
||||
|
||||
if ( empty( $secret ) ) {
|
||||
return new WP_REST_Response( [ 'error' => 'Webhook secret not configured.' ], 403 );
|
||||
}
|
||||
|
||||
// Check Authorization: Bearer <secret>
|
||||
$auth = $request->get_header( 'Authorization' );
|
||||
if ( $auth && preg_match( '/^Bearer\s+(.+)$/i', $auth, $m ) ) {
|
||||
if ( ! hash_equals( $secret, $m[1] ) ) {
|
||||
return new WP_REST_Response( [ 'error' => 'Invalid secret.' ], 403 );
|
||||
}
|
||||
}
|
||||
// Check GitHub X-Hub-Signature-256
|
||||
elseif ( $sig = $request->get_header( 'X-Hub-Signature-256' ) ) {
|
||||
$body = $request->get_body();
|
||||
$expected = 'sha256=' . hash_hmac( 'sha256', $body, $secret );
|
||||
if ( ! hash_equals( $expected, $sig ) ) {
|
||||
return new WP_REST_Response( [ 'error' => 'Invalid signature.' ], 403 );
|
||||
}
|
||||
} else {
|
||||
return new WP_REST_Response( [ 'error' => 'Missing authentication.' ], 403 );
|
||||
}
|
||||
|
||||
// Run sync
|
||||
$result = oribi_sync_run();
|
||||
|
||||
return new WP_REST_Response( $result, $result['ok'] ? 200 : 500 );
|
||||
}
|
||||
Reference in New Issue
Block a user