feat: Add complete Docker deployment with web-based setup wizard
Major additions: - Web-based setup wizard (setup.php, setup_wizard.php, setup-wizard.js) - Production Docker configuration (docker-compose.prod.yml, .env.production) - Database initialization SQL files (deploy/init_settings.sql) - Template builder system with drag-and-drop UI - Advanced features (OAuth, CDN, enhanced analytics, monetization) - Comprehensive documentation (deployment guides, quick start, feature docs) - Design system with accessibility and responsive layout - Deployment automation scripts (deploy.ps1, generate-secrets.ps1) Setup wizard allows customization of: - Platform name and branding - Domain configuration - Membership tiers and pricing - Admin credentials - Feature toggles Database includes 270+ tables for complete video streaming platform with advanced features for analytics, moderation, template building, and monetization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
206
f_core/f_classes/class.oauth.php
Normal file
206
f_core/f_classes/class.oauth.php
Normal file
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
/**
|
||||
* EasyStream OAuth 2.0 Server
|
||||
* OAuth 2.0 authentication for API
|
||||
* Version: 1.0
|
||||
*/
|
||||
|
||||
defined('_ISVALID') or header('Location: /error');
|
||||
|
||||
class VOAuth {
|
||||
private static $db;
|
||||
|
||||
public static function init() {
|
||||
self::$db = VDatabase::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate authorization code
|
||||
* @param int $usr_id User ID
|
||||
* @param string $client_id Client ID
|
||||
* @param array $scopes Requested scopes
|
||||
* @param string $redirect_uri Redirect URI
|
||||
* @return string Authorization code
|
||||
*/
|
||||
public static function generateAuthCode($usr_id, $client_id, $scopes, $redirect_uri) {
|
||||
self::init();
|
||||
|
||||
$code = bin2hex(random_bytes(32));
|
||||
$usr_id = (int)$usr_id;
|
||||
$client_id_safe = VDatabase::escape($client_id);
|
||||
$scopes_json = VDatabase::escape(json_encode($scopes));
|
||||
$redirect_safe = VDatabase::escape($redirect_uri);
|
||||
|
||||
$sql = "INSERT INTO db_oauth_codes
|
||||
(usr_id, client_id, code, scopes, redirect_uri, expires_at, created_at)
|
||||
VALUES ($usr_id, '$client_id_safe', '$code', '$scopes_json', '$redirect_safe', DATE_ADD(NOW(), INTERVAL 10 MINUTE), NOW())";
|
||||
|
||||
if (self::$db->execute($sql)) {
|
||||
return $code;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange authorization code for access token
|
||||
* @param string $code Authorization code
|
||||
* @param string $client_id Client ID
|
||||
* @param string $client_secret Client secret
|
||||
* @return array|false Token data or false
|
||||
*/
|
||||
public static function exchangeCode($code, $client_id, $client_secret) {
|
||||
self::init();
|
||||
|
||||
$code_safe = VDatabase::escape($code);
|
||||
$client_id_safe = VDatabase::escape($client_id);
|
||||
|
||||
// Validate code
|
||||
$sql = "SELECT * FROM db_oauth_codes
|
||||
WHERE code = '$code_safe'
|
||||
AND client_id = '$client_id_safe'
|
||||
AND expires_at > NOW()
|
||||
AND is_used = 0";
|
||||
|
||||
$result = self::$db->execute($sql);
|
||||
|
||||
if (!$result || $result->RecordCount() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code_data = $result->FetchRow();
|
||||
|
||||
// Mark code as used
|
||||
$code_id = (int)$code_data['code_id'];
|
||||
self::$db->execute("UPDATE db_oauth_codes SET is_used = 1 WHERE code_id = $code_id");
|
||||
|
||||
// Generate tokens
|
||||
$access_token = bin2hex(random_bytes(32));
|
||||
$refresh_token = bin2hex(random_bytes(32));
|
||||
|
||||
$usr_id = (int)$code_data['usr_id'];
|
||||
$scopes = $code_data['scopes'];
|
||||
|
||||
$sql = "INSERT INTO db_oauth_tokens
|
||||
(usr_id, client_id, access_token, refresh_token, token_type, scopes, expires_at, refresh_expires_at, created_at)
|
||||
VALUES ($usr_id, '$client_id_safe', '$access_token', '$refresh_token', 'Bearer', '$scopes',
|
||||
DATE_ADD(NOW(), INTERVAL 1 HOUR),
|
||||
DATE_ADD(NOW(), INTERVAL 30 DAY),
|
||||
NOW())";
|
||||
|
||||
if (self::$db->execute($sql)) {
|
||||
return [
|
||||
'access_token' => $access_token,
|
||||
'refresh_token' => $refresh_token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600,
|
||||
'scope' => implode(' ', json_decode($scopes, true))
|
||||
];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh access token
|
||||
* @param string $refresh_token Refresh token
|
||||
* @param string $client_id Client ID
|
||||
* @return array|false New token data or false
|
||||
*/
|
||||
public static function refreshToken($refresh_token, $client_id) {
|
||||
self::init();
|
||||
|
||||
$refresh_safe = VDatabase::escape($refresh_token);
|
||||
$client_id_safe = VDatabase::escape($client_id);
|
||||
|
||||
// Validate refresh token
|
||||
$sql = "SELECT * FROM db_oauth_tokens
|
||||
WHERE refresh_token = '$refresh_safe'
|
||||
AND client_id = '$client_id_safe'
|
||||
AND refresh_expires_at > NOW()
|
||||
AND is_revoked = 0";
|
||||
|
||||
$result = self::$db->execute($sql);
|
||||
|
||||
if (!$result || $result->RecordCount() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$token_data = $result->FetchRow();
|
||||
|
||||
// Revoke old token
|
||||
$token_id = (int)$token_data['token_id'];
|
||||
self::$db->execute("UPDATE db_oauth_tokens SET is_revoked = 1 WHERE token_id = $token_id");
|
||||
|
||||
// Generate new tokens
|
||||
$new_access_token = bin2hex(random_bytes(32));
|
||||
$new_refresh_token = bin2hex(random_bytes(32));
|
||||
|
||||
$usr_id = (int)$token_data['usr_id'];
|
||||
$scopes = $token_data['scopes'];
|
||||
|
||||
$sql = "INSERT INTO db_oauth_tokens
|
||||
(usr_id, client_id, access_token, refresh_token, token_type, scopes, expires_at, refresh_expires_at, created_at)
|
||||
VALUES ($usr_id, '$client_id_safe', '$new_access_token', '$new_refresh_token', 'Bearer', '$scopes',
|
||||
DATE_ADD(NOW(), INTERVAL 1 HOUR),
|
||||
DATE_ADD(NOW(), INTERVAL 30 DAY),
|
||||
NOW())";
|
||||
|
||||
if (self::$db->execute($sql)) {
|
||||
return [
|
||||
'access_token' => $new_access_token,
|
||||
'refresh_token' => $new_refresh_token,
|
||||
'token_type' => 'Bearer',
|
||||
'expires_in' => 3600
|
||||
];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate access token
|
||||
* @param string $access_token Access token
|
||||
* @return array|false User and scope data or false
|
||||
*/
|
||||
public static function validateToken($access_token) {
|
||||
self::init();
|
||||
|
||||
$token_safe = VDatabase::escape($access_token);
|
||||
|
||||
$sql = "SELECT t.*, u.usr_user, u.usr_email
|
||||
FROM db_oauth_tokens t
|
||||
JOIN db_accountuser u ON t.usr_id = u.usr_id
|
||||
WHERE t.access_token = '$token_safe'
|
||||
AND t.expires_at > NOW()
|
||||
AND t.is_revoked = 0";
|
||||
|
||||
$result = self::$db->execute($sql);
|
||||
|
||||
if ($result && $result->RecordCount() > 0) {
|
||||
$data = $result->FetchRow();
|
||||
return [
|
||||
'usr_id' => $data['usr_id'],
|
||||
'username' => $data['usr_user'],
|
||||
'email' => $data['usr_email'],
|
||||
'scopes' => json_decode($data['scopes'], true)
|
||||
];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke token
|
||||
* @param string $access_token Access token
|
||||
* @return bool Success
|
||||
*/
|
||||
public static function revokeToken($access_token) {
|
||||
self::init();
|
||||
|
||||
$token_safe = VDatabase::escape($access_token);
|
||||
|
||||
$sql = "UPDATE db_oauth_tokens SET is_revoked = 1 WHERE access_token = '$token_safe'";
|
||||
return self::$db->execute($sql);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user