/
home
/
altere25
/
.trash
/
wp-to-sanity-migration.9
/
/home/altere25/.trash/wp-to-sanity-migration.9
mkdir
upload
Name
Size
Mode
Actions
wp-companion/
-
0755
rm
acf-json\.gitkeep
0
0644
edit
dl
rm
assets\css\admin.css
12113
0644
edit
dl
rm
assets\js\admin.js
52894
0644
edit
dl
rm
includes\class-ad-admin.php
10358
0644
edit
dl
rm
includes\class-ad-ai-client.php
10724
0644
edit
dl
rm
includes\class-ad-auth.php
9189
0644
edit
dl
rm
includes\class-ad-cli.php
8671
0644
edit
dl
rm
includes\class-ad-extractor.php
17237
0644
edit
dl
rm
includes\class-ad-mcp.php
6429
0644
edit
dl
rm
includes\class-ad-plugin-core.php
10252
0644
edit
dl
rm
includes\class-ad-progress.php
8022
0644
edit
dl
rm
includes\class-ad-rest.php
43443
0644
edit
dl
rm
includes\class-ad-uninstall.php
1966
0644
edit
dl
rm
includes\class-ad-webhook.php
24172
0644
edit
dl
rm
languages\.gitkeep
0
0644
edit
dl
rm
templates\admin\wizard.php
29414
0644
edit
dl
rm
wp-to-sanity-migration\acf-json\.gitkeep
0
0644
edit
dl
rm
wp-to-sanity-migration\assets\
0
0644
edit
dl
rm
wp-to-sanity-migration\assets\css\admin.css
12113
0644
edit
dl
rm
wp-to-sanity-migration\assets\js\admin.js
52894
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-admin.php
10358
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-ai-client.php
10724
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-auth.php
9189
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-cli.php
8671
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-extractor.php
17237
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-mcp.php
6429
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-plugin-core.php
10252
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-progress.php
8022
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-rest.php
43443
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-uninstall.php
1966
0644
edit
dl
rm
wp-to-sanity-migration\includes\class-ad-webhook.php
24172
0644
edit
dl
rm
wp-to-sanity-migration\languages\.gitkeep
0
0644
edit
dl
rm
wp-to-sanity-migration\package.json
220
0644
edit
dl
rm
wp-to-sanity-migration\readme.txt
8174
0644
edit
dl
rm
wp-to-sanity-migration\templates\
0
0644
edit
dl
rm
wp-to-sanity-migration\templates\admin\wizard.php
29414
0644
edit
dl
rm
wp-to-sanity-migration\uninstall.php
365
0644
edit
dl
rm
wp-to-sanity-migration\wp-to-sanity-migration.php
4418
0644
edit
dl
rm
Edit:
/home/altere25/.trash/wp-to-sanity-migration.9/includes\class-ad-auth.php
(9189B)
<?php /** * Altered Digital Migration — Auth (Supabase JWT) * * Authenticates the WordPress site owner against the Altered Digital * Supabase project so the plugin can call AI service endpoints on the * customer's behalf. The JWT is stored in the `ad_account_session` option, * encrypted with `wp_salt('auth')`. * * Phase B: stubbed — login/verify/refresh methods return `not_configured`. * Phase C wires these to the live Supabase auth endpoints. * * @package AlteredDigitalMigration */ if (!defined('ABSPATH')) { exit; } class AD_Auth { /** @var AD_Plugin_Core */ private $core; /** Supabase URL (set once during plugin settings). */ private function supabase_url(): string { return $this->core->setting('supabase_url', ''); } /** Supabase anon/public key for client-side auth calls. */ private function supabase_anon_key(): string { return $this->core->setting('supabase_anon_key', ''); } public function __construct(AD_Plugin_Core $core) { $this->core = $core; } /** * Log a user in with email + password. * * @param string $email * @param string $password * @return array{success:bool,data:array<string,mixed>} */ public function login(string $email, string $password): array { $url = $this->supabase_url(); $key = $this->supabase_anon_key(); if (empty($url) || empty($key)) { return ['success' => false, 'data' => ['error' => 'not_configured']]; } $endpoint = rtrim($url, '/') . '/auth/v1/token?grant_type=password'; $response = wp_remote_post($endpoint, [ 'timeout' => 20, 'headers' => [ 'Content-Type' => 'application/json', 'apikey' => $key, ], 'body' => wp_json_encode([ 'email' => $email, 'password' => $password, ]), ]); if (is_wp_error($response)) { return ['success' => false, 'data' => ['error' => $response->get_error_message()]]; } $code = wp_remote_retrieve_response_code($response); $body = wp_remote_retrieve_body($response); $decoded = json_decode($body, true); if ($code !== 200 || !is_array($decoded) || empty($decoded['access_token'])) { return [ 'success' => false, 'data' => [ 'error' => is_array($decoded) && !empty($decoded['error']) ? $decoded['error'] : 'auth_failed', 'status' => intval($code), ], ]; } $this->store_session($decoded); return ['success' => true, 'data' => $decoded]; } /** * Sign up a new account. * * @param string $email * @param string $password * @return array{success:bool,data:array<string,mixed>} */ public function signup(string $email, string $password): array { $url = $this->supabase_url(); $key = $this->supabase_anon_key(); if (empty($url) || empty($key)) { return ['success' => false, 'data' => ['error' => 'not_configured']]; } $endpoint = rtrim($url, '/') . '/auth/v1/signup'; $response = wp_remote_post($endpoint, [ 'timeout' => 20, 'headers' => [ 'Content-Type' => 'application/json', 'apikey' => $key, ], 'body' => wp_json_encode([ 'email' => $email, 'password' => $password, ]), ]); if (is_wp_error($response)) { return ['success' => false, 'data' => ['error' => $response->get_error_message()]]; } $code = wp_remote_retrieve_response_code($response); $decoded = json_decode(wp_remote_retrieve_body($response), true); if ($code >= 400 || !is_array($decoded)) { return [ 'success' => false, 'data' => ['error' => is_array($decoded) && !empty($decoded['error']) ? $decoded['error'] : 'signup_failed', 'status' => intval($code)], ]; } if (!empty($decoded['access_token'])) { $this->store_session($decoded); } return ['success' => true, 'data' => $decoded]; } /** * Refresh the stored JWT using the refresh_token. * * @return array{success:bool,data:array<string,mixed>} */ public function refresh(): array { $session = $this->load_session(); if (empty($session['refresh_token'])) { return ['success' => false, 'data' => ['error' => 'no_session']]; } $url = $this->supabase_url(); $key = $this->supabase_anon_key(); if (empty($url) || empty($key)) { return ['success' => false, 'data' => ['error' => 'not_configured']]; } $endpoint = rtrim($url, '/') . '/auth/v1/token?grant_type=refresh_token'; $response = wp_remote_post($endpoint, [ 'timeout' => 20, 'headers' => [ 'Content-Type' => 'application/json', 'apikey' => $key, ], 'body' => wp_json_encode(['refresh_token' => $session['refresh_token']]), ]); if (is_wp_error($response)) { return ['success' => false, 'data' => ['error' => $response->get_error_message()]]; } $code = wp_remote_retrieve_response_code($response); $decoded = json_decode(wp_remote_retrieve_body($response), true); if ($code !== 200 || !is_array($decoded) || empty($decoded['access_token'])) { return ['success' => false, 'data' => ['error' => 'refresh_failed', 'status' => intval($code)]]; } $this->store_session($decoded); return ['success' => true, 'data' => $decoded]; } /** * Get the current access token (or null if not logged in). */ public function access_token(): ?string { $session = $this->load_session(); return $session['access_token'] ?? null; } /** * Lightweight JWT exp check (no signature verification — the AI service * verifies via JWKS). Returns true if expired or about to expire. */ public function is_expired(): bool { $session = $this->load_session(); if (empty($session['access_token'])) { return true; } $parts = explode('.', $session['access_token']); if (count($parts) !== 3) { return true; } $payload = json_decode(base64_decode(strtr($parts[1], '-_', '+/')), true); $exp = $payload['exp'] ?? 0; return time() > ((int) $exp - 60); } /** * Clear the stored session (logout). */ public function logout(): void { delete_option('ad_account_session'); } // ----------------------------------------------------------------- // Encrypted storage // ----------------------------------------------------------------- private function store_session(array $token_response): void { $encrypted = $this->encrypt(wp_json_encode($token_response)); update_option('ad_account_session', $encrypted); } private function load_session(): array { $raw = get_option('ad_account_session', ''); if (empty($raw) || !is_string($raw)) { return []; } $json = $this->decrypt($raw); $decoded = $json ? json_decode($json, true) : null; return is_array($decoded) ? $decoded : []; } /** * AES-256-GCM encrypt with WP auth salt. IV (12 bytes) + auth tag * (16 bytes) are prepended to the ciphertext and base64'd. * Falls back to AES-256-CBC for decryption of legacy values. */ private function encrypt(string $plain): string { $key = hash('sha256', wp_salt('auth'), true); $iv = random_bytes(12); $tag = ''; $cipher = openssl_encrypt($plain, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag, '', 16); if ($cipher === false) { return ''; } return base64_encode($iv . $tag . $cipher); } private function decrypt(string $encoded): string { $raw = base64_decode($encoded, true); if ($raw === false || strlen($raw) < 29) { return ''; } $key = hash('sha256', wp_salt('auth'), true); // GCM: IV (12) + tag (16) + ciphertext $iv = substr($raw, 0, 12); $tag = substr($raw, 12, 16); $cipher = substr($raw, 28); $plain = openssl_decrypt($cipher, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag); if ($plain !== false) { return $plain; } // Legacy CBC fallback: IV (16) + ciphertext if (strlen($raw) >= 17) { $iv_cbc = substr($raw, 0, 16); $cipher_cbc = substr($raw, 16); $plain_cbc = openssl_decrypt($cipher_cbc, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv_cbc); if ($plain_cbc !== false) { return $plain_cbc; } } return ''; } }
Save
cmd:
run