feat: Add comprehensive documentation suite and reorganize project structure

- Created complete documentation in docs/ directory
- Added PROJECT_OVERVIEW.md with feature highlights and getting started guide
- Added ARCHITECTURE.md with system design and technical details
- Added SECURITY.md with comprehensive security implementation guide
- Added DEVELOPMENT.md with development workflows and best practices
- Added DEPLOYMENT.md with production deployment instructions
- Added API.md with complete REST API documentation
- Added CONTRIBUTING.md with contribution guidelines
- Added CHANGELOG.md with version history and migration notes
- Reorganized all documentation files into docs/ directory for better organization
- Updated README.md with proper documentation links and quick navigation
- Enhanced project structure with professional documentation standards
This commit is contained in:
SamiAhmed7777
2025-10-21 00:39:45 -07:00
commit 0b7e2d0a5b
6080 changed files with 1332936 additions and 0 deletions

362
examples/auth_examples.php Normal file
View File

@@ -0,0 +1,362 @@
<?php
/*******************************************************************************************************************
| Software Name : EasyStream
| Software Description : High End YouTube Clone Script with Videos, Shorts, Streams, Images, Audio, Documents, Blogs
| Software Author : (c) Sami Ahmed
|*******************************************************************************************************************
|
|*******************************************************************************************************************
| This source file is subject to the EasyStream Proprietary License Agreement.
|
| By using this software, you acknowledge having read this Agreement and agree to be bound thereby.
|*******************************************************************************************************************
| Copyright (c) 2025 Sami Ahmed. All rights reserved.
|*******************************************************************************************************************/
define('_ISVALID', true);
require_once '../f_core/config.core.php';
$auth = VAuth::getInstance();
$security = VSecurity::getInstance();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EasyStream Authentication Examples</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input, textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
button { background: #007cba; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
button:hover { background: #005a87; }
.success { color: green; padding: 10px; background: #f0f8f0; border: 1px solid #d4edda; border-radius: 4px; }
.error { color: red; padding: 10px; background: #f8f0f0; border: 1px solid #f5c6cb; border-radius: 4px; }
.info { color: blue; padding: 10px; background: #f0f4f8; border: 1px solid #bee5eb; border-radius: 4px; }
.section { margin: 30px 0; padding: 20px; border: 1px solid #eee; border-radius: 8px; }
.user-info { background: #f8f9fa; padding: 15px; border-radius: 4px; margin: 10px 0; }
</style>
</head>
<body>
<h1>🔐 EasyStream Authentication System Examples</h1>
<?php
// Handle form submissions
$message = '';
$messageType = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = VSecurity::postParam('action', 'string');
switch ($action) {
case 'register':
if (VSecurity::validateCSRFFromPost('register')) {
$userData = [
'username' => VSecurity::postParam('username', 'string'),
'email' => VSecurity::postParam('email', 'email'),
'password' => $_POST['password'] ?? ''
];
$result = $auth->register($userData);
$message = $result['message'];
$messageType = $result['success'] ? 'success' : 'error';
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'login':
if (VSecurity::validateCSRFFromPost('login')) {
$identifier = VSecurity::postParam('identifier', 'string');
$password = $_POST['password'] ?? '';
$rememberMe = VSecurity::postParam('remember_me', 'boolean', false);
$result = $auth->login($identifier, $password, $rememberMe);
$message = $result['message'];
$messageType = $result['success'] ? 'success' : 'error';
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'logout':
if (VSecurity::validateCSRFFromPost('logout')) {
$result = $auth->logout();
$message = $result['message'];
$messageType = $result['success'] ? 'success' : 'error';
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'verify_email':
$token = VSecurity::postParam('token', 'string');
$result = $auth->verifyEmail($token);
$message = $result['message'];
$messageType = $result['success'] ? 'success' : 'error';
break;
case 'request_reset':
if (VSecurity::validateCSRFFromPost('password_reset')) {
$email = VSecurity::postParam('email', 'email');
$result = $auth->requestPasswordReset($email);
$message = $result['message'];
$messageType = $result['success'] ? 'success' : 'error';
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'reset_password':
if (VSecurity::validateCSRFFromPost('password_reset')) {
$token = VSecurity::postParam('token', 'string');
$password = $_POST['password'] ?? '';
$result = $auth->resetPassword($token, $password);
$message = $result['message'];
$messageType = $result['success'] ? 'success' : 'error';
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
}
}
// Display message
if ($message) {
echo "<div class='{$messageType}'>{$message}</div>";
}
// Check authentication status
$isAuthenticated = $auth->isAuthenticated();
$currentUser = $auth->getCurrentUser();
?>
<div class="info">
<strong>Authentication Status:</strong>
<?php if ($isAuthenticated): ?>
✅ Authenticated as <strong><?= htmlspecialchars($currentUser['username']) ?></strong>
<?php else: ?>
❌ Not authenticated
<?php endif; ?>
</div>
<?php if ($isAuthenticated): ?>
<div class="user-info">
<h3>Current User Information</h3>
<p><strong>User ID:</strong> <?= htmlspecialchars($currentUser['user_id']) ?></p>
<p><strong>Username:</strong> <?= htmlspecialchars($currentUser['username']) ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($currentUser['email']) ?></p>
<p><strong>Role:</strong> <?= htmlspecialchars($currentUser['role']) ?></p>
</div>
<div class="section">
<h2>🚪 Logout</h2>
<form method="POST">
<input type="hidden" name="action" value="logout">
<?= VSecurity::getCSRFField('logout') ?>
<button type="submit">Logout</button>
</form>
</div>
<?php else: ?>
<div class="section">
<h2>📝 User Registration</h2>
<form method="POST">
<input type="hidden" name="action" value="register">
<?= VSecurity::getCSRFField('register') ?>
<div class="form-group">
<label for="reg_username">Username:</label>
<input type="text" id="reg_username" name="username" required
pattern="[a-zA-Z0-9]{3,50}"
title="3-50 alphanumeric characters only">
</div>
<div class="form-group">
<label for="reg_email">Email:</label>
<input type="email" id="reg_email" name="email" required>
</div>
<div class="form-group">
<label for="reg_password">Password:</label>
<input type="password" id="reg_password" name="password" required
minlength="8"
title="At least 8 characters with uppercase, lowercase, number, and special character">
<small>Must contain: uppercase, lowercase, number, and special character</small>
</div>
<button type="submit">Register</button>
</form>
</div>
<div class="section">
<h2>🔑 User Login</h2>
<form method="POST">
<input type="hidden" name="action" value="login">
<?= VSecurity::getCSRFField('login') ?>
<div class="form-group">
<label for="login_identifier">Username or Email:</label>
<input type="text" id="login_identifier" name="identifier" required>
</div>
<div class="form-group">
<label for="login_password">Password:</label>
<input type="password" id="login_password" name="password" required>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="remember_me" value="1">
Remember me for 30 days
</label>
</div>
<button type="submit">Login</button>
</form>
</div>
<?php endif; ?>
<div class="section">
<h2>📧 Email Verification</h2>
<p>If you registered but haven't verified your email, enter your verification token here:</p>
<form method="POST">
<input type="hidden" name="action" value="verify_email">
<div class="form-group">
<label for="verify_token">Verification Token:</label>
<input type="text" id="verify_token" name="token" required
pattern="[a-f0-9]{64}"
title="64-character hexadecimal token">
</div>
<button type="submit">Verify Email</button>
</form>
</div>
<div class="section">
<h2>🔄 Password Reset</h2>
<h3>Request Password Reset</h3>
<form method="POST">
<input type="hidden" name="action" value="request_reset">
<?= VSecurity::getCSRFField('password_reset') ?>
<div class="form-group">
<label for="reset_email">Email:</label>
<input type="email" id="reset_email" name="email" required>
</div>
<button type="submit">Request Password Reset</button>
</form>
<h3>Reset Password with Token</h3>
<form method="POST">
<input type="hidden" name="action" value="reset_password">
<?= VSecurity::getCSRFField('password_reset') ?>
<div class="form-group">
<label for="reset_token">Reset Token:</label>
<input type="text" id="reset_token" name="token" required
pattern="[a-f0-9]{64}"
title="64-character hexadecimal token">
</div>
<div class="form-group">
<label for="new_password">New Password:</label>
<input type="password" id="new_password" name="password" required
minlength="8"
title="At least 8 characters with uppercase, lowercase, number, and special character">
<small>Must contain: uppercase, lowercase, number, and special character</small>
</div>
<button type="submit">Reset Password</button>
</form>
</div>
<div class="section">
<h2>🔧 API Examples</h2>
<p>The authentication system also provides a REST API at <code>/api/auth.php</code></p>
<h3>Available Endpoints:</h3>
<ul>
<li><strong>POST /api/auth.php?action=register</strong> - Register new user</li>
<li><strong>POST /api/auth.php?action=login</strong> - Login user</li>
<li><strong>POST /api/auth.php?action=logout</strong> - Logout user</li>
<li><strong>GET /api/auth.php?action=me</strong> - Get current user info</li>
<li><strong>GET /api/auth.php?action=status</strong> - Get authentication status</li>
<li><strong>POST /api/auth.php?action=verify_email</strong> - Verify email</li>
<li><strong>POST /api/auth.php?action=request_password_reset</strong> - Request password reset</li>
<li><strong>POST /api/auth.php?action=reset_password</strong> - Reset password</li>
<li><strong>GET /api/auth.php?action=csrf_token</strong> - Get CSRF token</li>
</ul>
<h3>Example JavaScript Usage:</h3>
<pre><code>// Get CSRF token
const tokenResponse = await fetch('/api/auth.php?action=csrf_token&for=login');
const tokenData = await tokenResponse.json();
// Login user
const loginResponse = await fetch('/api/auth.php?action=login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identifier: 'username',
password: 'password',
csrf_token: tokenData.token,
remember_me: true
})
});
const loginResult = await loginResponse.json();
console.log(loginResult);</code></pre>
</div>
<div class="section">
<h2>🛡️ Security Features</h2>
<ul>
<li><strong>CSRF Protection:</strong> All forms include CSRF tokens</li>
<li><strong>Rate Limiting:</strong> Login attempts and password resets are rate limited</li>
<li><strong>Password Strength:</strong> Enforced strong password requirements</li>
<li><strong>Session Security:</strong> Secure session management with Redis support</li>
<li><strong>Input Validation:</strong> All inputs are validated and sanitized</li>
<li><strong>Email Verification:</strong> Optional email verification for new accounts</li>
<li><strong>Remember Me:</strong> Secure remember me functionality</li>
<li><strong>Audit Logging:</strong> All authentication events are logged</li>
<li><strong>IP Tracking:</strong> Login attempts tracked by IP address</li>
<li><strong>Session Regeneration:</strong> Session IDs regenerated on login</li>
</ul>
</div>
<script>
// Add some client-side validation
document.addEventListener('DOMContentLoaded', function() {
const passwordInputs = document.querySelectorAll('input[type="password"]');
passwordInputs.forEach(input => {
input.addEventListener('input', function() {
const password = this.value;
const hasUpper = /[A-Z]/.test(password);
const hasLower = /[a-z]/.test(password);
const hasNumber = /\d/.test(password);
const hasSpecial = /[@$!%*?&]/.test(password);
const isLongEnough = password.length >= 8;
const isStrong = hasUpper && hasLower && hasNumber && hasSpecial && isLongEnough;
this.style.borderColor = isStrong ? 'green' : 'red';
});
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,203 @@
<?php
/*******************************************************************************************************************
| Example: Enhanced Logging Implementation
| This file demonstrates how to use the new logging features
|*******************************************************************************************************************/
define('_ISVALID', true);
include_once 'f_core/config.core.php';
// Example 1: Basic logging
$logger = VLogger::getInstance();
// Different log levels
$logger->info('User logged in successfully', ['user_id' => 123]);
$logger->warning('Failed login attempt', ['username' => 'testuser', 'ip' => '192.168.1.1']);
$logger->error('Database connection failed', ['host' => 'localhost', 'database' => 'easystream']);
// Example 2: Security event logging
log_security_event('Suspicious file upload attempt', [
'filename' => 'malicious.php',
'mime_type' => 'application/x-php',
'user_id' => $_SESSION['USER_ID'] ?? null
]);
// Example 3: Performance monitoring
$startTime = microtime(true);
// Simulate some processing
sleep(1);
$executionTime = microtime(true) - $startTime;
if ($executionTime > 0.5) { // Log if takes more than 500ms
log_performance_issue('Slow database query', $executionTime, [
'query_type' => 'user_search',
'parameters' => ['search_term' => 'example']
]);
}
// Example 4: Validation error logging
function validateUserInput($data) {
$errors = [];
if (empty($data['username'])) {
log_validation_error('username', $data['username'] ?? '', 'required');
$errors[] = 'Username is required';
}
if (!filter_var($data['email'] ?? '', FILTER_VALIDATE_EMAIL)) {
log_validation_error('email', $data['email'] ?? '', 'valid_email');
$errors[] = 'Valid email is required';
}
return $errors;
}
// Example 5: Database operation with error logging
function updateUserProfile($userId, $data) {
global $class_database;
try {
$result = $class_database->doUpdate('db_accountuser', 'usr_id', $data, $userId);
if ($result) {
$logger = VLogger::getInstance();
$logger->info('User profile updated', [
'user_id' => $userId,
'updated_fields' => array_keys($data)
]);
return true;
} else {
log_app_error('Failed to update user profile', [
'user_id' => $userId,
'data' => $data
]);
return false;
}
} catch (Exception $e) {
log_app_error('Exception during profile update: ' . $e->getMessage(), [
'user_id' => $userId,
'exception' => get_class($e),
'trace' => $e->getTraceAsString()
]);
return false;
}
}
// Example 6: Authentication logging
function authenticateUser($username, $password) {
global $class_database;
// Rate limiting check
$clientIP = $_SERVER['REMOTE_ADDR'];
if (!check_rate_limit('login_' . $clientIP, 5, 300)) {
log_auth_error('Rate limit exceeded for login attempts', $username, [
'ip' => $clientIP,
'rate_limit_exceeded' => true
]);
return false;
}
// Validate credentials (simplified example)
$user = $class_database->singleFieldValue('db_accountuser', 'usr_id', 'usr_user', $username);
if (!$user) {
log_auth_error('Login attempt with non-existent username', $username);
return false;
}
// Password verification would go here
$passwordValid = true; // Simplified
if (!$passwordValid) {
log_auth_error('Login attempt with invalid password', $username, [
'user_id' => $user
]);
return false;
}
// Successful login
$logger = VLogger::getInstance();
$logger->info('User logged in successfully', [
'user_id' => $user,
'username' => $username
]);
return $user;
}
// Example 7: File upload logging
function handleFileUpload($file) {
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$maxSize = 5 * 1024 * 1024; // 5MB
$validation = validate_file_upload($file, $allowedTypes, $maxSize);
if (!$validation['valid']) {
log_security_event('Invalid file upload attempt', [
'filename' => $file['name'],
'size' => $file['size'],
'type' => $file['type'],
'error' => $validation['error']
]);
return false;
}
// Process upload
$uploadDir = 'f_data/data_userfiles/uploads/';
$filename = uniqid() . '_' . basename($file['name']);
$uploadPath = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $uploadPath)) {
$logger = VLogger::getInstance();
$logger->info('File uploaded successfully', [
'original_filename' => $file['name'],
'stored_filename' => $filename,
'size' => $file['size'],
'mime_type' => $validation['mime_type']
]);
return $filename;
} else {
log_app_error('Failed to move uploaded file', [
'filename' => $file['name'],
'destination' => $uploadPath
]);
return false;
}
}
// Example 8: API request logging
function logAPIRequest($endpoint, $method, $params, $response, $executionTime) {
$logger = VLogger::getInstance();
$logLevel = VLogger::INFO;
$context = [
'api_endpoint' => $endpoint,
'method' => $method,
'parameters' => $params,
'response_size' => strlen(json_encode($response)),
'execution_time' => $executionTime
];
// Log as warning if slow
if ($executionTime > 2.0) {
$logLevel = VLogger::WARNING;
$context['slow_request'] = true;
}
$logger->log($logLevel, "API request to {$endpoint}", $context);
}
// Example usage
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$startTime = microtime(true);
// Simulate API processing
$response = ['status' => 'success', 'data' => []];
$executionTime = microtime(true) - $startTime;
logAPIRequest('/api/users', 'POST', $_POST, $response, $executionTime);
}
echo "Enhanced logging examples completed. Check the logs in f_data/logs/";
?>

View File

@@ -0,0 +1,339 @@
<?php
/*******************************************************************************************************************
| Example: Browser Fingerprint Integration
| This file demonstrates how to integrate fingerprinting into your existing pages
|*******************************************************************************************************************/
define('_ISVALID', true);
include_once 'f_core/config.core.php';
// Example 1: Check fingerprint on page load
function checkFingerprintAccess() {
// Check if we have a fingerprint in session
if (isset($_SESSION['browser_fingerprint'])) {
$fingerprint = $_SESSION['browser_fingerprint'];
// Check if fingerprint is banned
$ban_info = VFingerprint::isBanned($fingerprint);
if ($ban_info) {
// Log the banned access attempt
VIPTracker::logActivity('banned_fingerprint_page_access', [
'fingerprint' => substr($fingerprint, 0, 16) . '...',
'page' => $_SERVER['REQUEST_URI'],
'ban_reason' => $ban_info['reason']
]);
// Redirect to error page or show ban message
header('Location: /error');
exit;
}
// Track page visit with fingerprint
VFingerprint::trackFingerprint($fingerprint, [
'page_type' => 'content_page',
'page_url' => $_SERVER['REQUEST_URI']
]);
}
}
// Example 2: Enhanced login with fingerprint checking
function handleSecureLogin($username, $password) {
$user_ip = VIPaccess::getUserIP();
// Check IP ban first
if (VIPTracker::isBanned($user_ip)) {
return ['success' => false, 'message' => 'Access denied - IP banned'];
}
// Check fingerprint ban if available
if (isset($_SESSION['browser_fingerprint'])) {
$fingerprint = $_SESSION['browser_fingerprint'];
$ban_info = VFingerprint::isBanned($fingerprint);
if ($ban_info) {
VIPTracker::logActivity('banned_fingerprint_login_attempt', [
'username' => $username,
'fingerprint' => substr($fingerprint, 0, 16) . '...',
'ban_reason' => $ban_info['reason']
]);
return ['success' => false, 'message' => 'Access denied - Device banned'];
}
}
// Rate limiting by IP and fingerprint
$rate_limit_key = 'login_' . $user_ip;
if (isset($_SESSION['browser_fingerprint'])) {
$rate_limit_key .= '_' . substr($_SESSION['browser_fingerprint'], 0, 16);
}
if (!VSecurity::checkRateLimit($rate_limit_key, 5, 300)) {
VIPTracker::logActivity('login_rate_limited', [
'username' => $username,
'fingerprint' => isset($_SESSION['browser_fingerprint']) ? substr($_SESSION['browser_fingerprint'], 0, 16) . '...' : null
]);
return ['success' => false, 'message' => 'Too many login attempts'];
}
// Perform actual login validation
$login_success = validateUserCredentials($username, $password);
if ($login_success) {
// Log successful login with fingerprint
VIPTracker::logActivity('login_success', [
'username' => $username,
'fingerprint' => isset($_SESSION['browser_fingerprint']) ? substr($_SESSION['browser_fingerprint'], 0, 16) . '...' : null
]);
if (isset($_SESSION['browser_fingerprint'])) {
VFingerprint::trackFingerprint($_SESSION['browser_fingerprint'], [
'action' => 'successful_login',
'username' => $username
]);
}
return ['success' => true, 'message' => 'Login successful'];
} else {
// Log failed login
VIPTracker::logActivity('login_failed', [
'username' => $username,
'fingerprint' => isset($_SESSION['browser_fingerprint']) ? substr($_SESSION['browser_fingerprint'], 0, 16) . '...' : null
]);
// Check for auto-ban conditions
if (isset($_SESSION['browser_fingerprint'])) {
$threats = VFingerprint::detectFingerprintThreats($_SESSION['browser_fingerprint']);
if ($threats['threat_level'] >= 4) {
VFingerprint::autoBanFingerprint($_SESSION['browser_fingerprint']);
}
}
return ['success' => false, 'message' => 'Invalid credentials'];
}
}
// Example 3: File upload with fingerprint tracking
function handleSecureFileUpload($file) {
$user_ip = VIPaccess::getUserIP();
// Check bans
if (VIPTracker::isBanned($user_ip)) {
return ['success' => false, 'message' => 'Access denied - IP banned'];
}
if (isset($_SESSION['browser_fingerprint'])) {
$fingerprint = $_SESSION['browser_fingerprint'];
if (VFingerprint::isBanned($fingerprint)) {
return ['success' => false, 'message' => 'Access denied - Device banned'];
}
}
// Rate limiting for uploads
$rate_limit_key = 'upload_' . $user_ip;
if (isset($_SESSION['browser_fingerprint'])) {
$rate_limit_key .= '_' . substr($_SESSION['browser_fingerprint'], 0, 16);
}
if (!VSecurity::checkRateLimit($rate_limit_key, 10, 3600)) {
return ['success' => false, 'message' => 'Upload rate limit exceeded'];
}
// Validate file
$validation = VSecurity::validateFileUpload($file, ['image/jpeg', 'image/png', 'video/mp4'], 50 * 1024 * 1024);
if (!$validation['valid']) {
// Log suspicious upload attempt
if (isset($_SESSION['browser_fingerprint'])) {
VFingerprint::trackFingerprint($_SESSION['browser_fingerprint'], [
'action' => 'suspicious_upload',
'filename' => $file['name'],
'error' => $validation['error']
]);
}
return ['success' => false, 'message' => $validation['error']];
}
// Process upload
$upload_success = processFileUpload($file);
if ($upload_success) {
// Track successful upload
if (isset($_SESSION['browser_fingerprint'])) {
VFingerprint::trackFingerprint($_SESSION['browser_fingerprint'], [
'action' => 'file_upload_success',
'filename' => $file['name'],
'size' => $file['size']
]);
}
return ['success' => true, 'message' => 'File uploaded successfully'];
} else {
return ['success' => false, 'message' => 'Upload failed'];
}
}
// Example 4: Comment posting with fingerprint validation
function handleCommentPost($comment_text, $video_id) {
// Check fingerprint ban
if (isset($_SESSION['browser_fingerprint'])) {
$fingerprint = $_SESSION['browser_fingerprint'];
$ban_info = VFingerprint::isBanned($fingerprint);
if ($ban_info) {
return ['success' => false, 'message' => 'Comments disabled for your device'];
}
// Rate limiting for comments
$rate_limit_key = 'comment_' . substr($fingerprint, 0, 16);
if (!VSecurity::checkRateLimit($rate_limit_key, 20, 3600)) {
return ['success' => false, 'message' => 'Comment rate limit exceeded'];
}
// Track comment activity
VFingerprint::trackFingerprint($fingerprint, [
'action' => 'comment_post',
'video_id' => $video_id,
'comment_length' => strlen($comment_text)
]);
}
// Process comment
$comment_success = saveComment($comment_text, $video_id);
return ['success' => $comment_success, 'message' => $comment_success ? 'Comment posted' : 'Failed to post comment'];
}
// Example 5: Admin function to ban fingerprint from user activity
function adminBanUserFingerprint($user_id, $reason = 'Terms violation') {
global $db;
try {
// Get user's recent fingerprints
$sql = "SELECT DISTINCT fingerprint_hash
FROM db_fingerprints
WHERE last_user_id = ?
AND last_seen >= DATE_SUB(NOW(), INTERVAL 30 DAY)";
$result = $db->Execute($sql, [$user_id]);
$banned_count = 0;
while ($result && !$result->EOF) {
$fingerprint = $result->fields['fingerprint_hash'];
if (VFingerprint::banFingerprint($fingerprint, $reason, 0, $_SESSION['ADMIN_NAME'])) {
$banned_count++;
VIPTracker::logActivity('user_fingerprint_banned', [
'user_id' => $user_id,
'fingerprint' => substr($fingerprint, 0, 16) . '...',
'reason' => $reason
]);
}
$result->MoveNext();
}
return $banned_count;
} catch (Exception $e) {
error_log("Admin fingerprint ban error: " . $e->getMessage());
return 0;
}
}
// Check fingerprint access on every page load
checkFingerprintAccess();
// Dummy functions for examples
function validateUserCredentials($username, $password) {
// Your existing login validation
return true;
}
function processFileUpload($file) {
// Your existing file upload processing
return true;
}
function saveComment($text, $video_id) {
// Your existing comment saving logic
return true;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Fingerprint Integration Example</title>
</head>
<body>
<h1>Browser Fingerprinting Integration</h1>
<div id="fingerprint-status">
<p>Checking device fingerprint...</p>
</div>
<!-- Include the fingerprinting JavaScript -->
<?= VFingerprint::getFingerprintingJS() ?>
<script>
// Override the sendFingerprint function to update status
const originalSendFingerprint = sendFingerprint;
sendFingerprint = function() {
originalSendFingerprint();
// Update status after sending fingerprint
setTimeout(() => {
const statusDiv = document.getElementById('fingerprint-status');
statusDiv.innerHTML = '<p style="color: green;">✓ Device verified</p>';
}, 1000);
};
</script>
<h2>Integration Examples</h2>
<h3>1. Login Form</h3>
<form method="POST" action="login_handler.php">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
<h3>2. File Upload</h3>
<form method="POST" action="upload_handler.php" enctype="multipart/form-data">
<input type="file" name="upload_file" accept="image/*,video/*" required>
<button type="submit">Upload</button>
</form>
<h3>3. Comment Form</h3>
<form method="POST" action="comment_handler.php">
<textarea name="comment" placeholder="Enter your comment..." required></textarea>
<input type="hidden" name="video_id" value="123">
<button type="submit">Post Comment</button>
</form>
<h3>Current Session Info</h3>
<?php if (isset($_SESSION['browser_fingerprint'])): ?>
<p><strong>Fingerprint ID:</strong> <?= substr($_SESSION['browser_fingerprint'], 0, 16) ?>...</p>
<?php
$stats = VFingerprint::getFingerprintStats($_SESSION['browser_fingerprint']);
if ($stats):
?>
<p><strong>Visit Count:</strong> <?= $stats['visit_count'] ?></p>
<p><strong>First Seen:</strong> <?= $stats['first_seen'] ?></p>
<p><strong>Last Seen:</strong> <?= $stats['last_seen'] ?></p>
<?php endif; ?>
<?php
$threats = VFingerprint::detectFingerprintThreats($_SESSION['browser_fingerprint']);
?>
<p><strong>Threat Level:</strong> <span style="color: <?= $threats['risk_assessment'] === 'HIGH' ? 'red' : ($threats['risk_assessment'] === 'MEDIUM' ? 'orange' : 'green') ?>"><?= $threats['risk_assessment'] ?></span></p>
<?php else: ?>
<p><em>Fingerprint not yet captured</em></p>
<?php endif; ?>
</body>
</html>

View File

@@ -0,0 +1,182 @@
<?php
/*******************************************************************************************************************
| Example: IP Tracking Usage
| This file demonstrates how to use the enhanced IP tracking system
|*******************************************************************************************************************/
define('_ISVALID', true);
include_once 'f_core/config.core.php';
// Example 1: Log user activities
VIPTracker::logActivity('page_view', [
'page' => 'home',
'user_type' => 'guest'
]);
VIPTracker::logActivity('video_watch', [
'video_id' => 12345,
'duration' => 120
]);
VIPTracker::logActivity('login_attempt', [
'username' => 'john_doe',
'success' => true
]);
// Example 2: Check if current user's IP is banned
$user_ip = VIPaccess::getUserIP();
$ban_info = VIPTracker::isBanned($user_ip);
if ($ban_info) {
echo "Your IP is banned. Reason: " . $ban_info['reason'];
exit;
}
// Example 3: Get IP statistics
$ip_stats = VIPTracker::getIPStats($user_ip, 24); // Last 24 hours
echo "Total requests in last 24h: " . $ip_stats['total_requests'];
// Example 4: Detect threats and auto-ban if necessary
$threats = VIPTracker::detectThreats($user_ip);
echo "Threat level: " . $threats['risk_assessment'];
if ($threats['threat_level'] >= 5) {
// Auto-ban high-risk IPs
VIPTracker::autoBan($user_ip);
echo "IP has been automatically banned due to suspicious activity.";
}
// Example 5: Manual IP banning (admin function)
if (isset($_SESSION['ADMIN_NAME'])) {
// Ban a specific IP
$result = VIPTracker::banIP('192.168.1.100', 'Spam activity detected', 24, $_SESSION['ADMIN_NAME']);
if ($result) {
echo "IP banned successfully";
}
// Unban an IP
$result = VIPTracker::unbanIP('192.168.1.100');
if ($result) {
echo "IP unbanned successfully";
}
}
// Example 6: Integration with existing login system
function handleLogin($username, $password) {
$user_ip = VIPaccess::getUserIP();
// Check if IP is banned
if (VIPTracker::isBanned($user_ip)) {
VIPTracker::logActivity('login_blocked', ['username' => $username, 'reason' => 'banned_ip']);
return false;
}
// Check rate limiting
if (!VSecurity::checkRateLimit('login_' . $user_ip, 5, 300)) {
VIPTracker::logActivity('login_rate_limited', ['username' => $username]);
return false;
}
// Perform actual login validation
$login_success = validateUserCredentials($username, $password);
if ($login_success) {
VIPTracker::logActivity('login_success', ['username' => $username]);
return true;
} else {
VIPTracker::logActivity('login_failed', ['username' => $username]);
// Check for brute force and auto-ban if necessary
VIPTracker::autoBan($user_ip);
return false;
}
}
// Example 7: Monitor file uploads
function handleFileUpload($file) {
$user_ip = VIPaccess::getUserIP();
VIPTracker::logActivity('file_upload_attempt', [
'filename' => $file['name'],
'size' => $file['size'],
'type' => $file['type']
]);
// Check upload rate limiting
if (!VSecurity::checkRateLimit('upload_' . $user_ip, 10, 3600)) {
VIPTracker::logActivity('upload_rate_limited', ['filename' => $file['name']]);
return false;
}
// Process upload...
$upload_success = processFileUpload($file);
if ($upload_success) {
VIPTracker::logActivity('file_upload_success', ['filename' => $file['name']]);
} else {
VIPTracker::logActivity('file_upload_failed', ['filename' => $file['name']]);
}
return $upload_success;
}
// Dummy functions for example
function validateUserCredentials($username, $password) {
// Your existing login validation logic
return true;
}
function processFileUpload($file) {
// Your existing file upload logic
return true;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>IP Tracking Examples</title>
</head>
<body>
<h1>IP Tracking System Examples</h1>
<h2>Current IP Information</h2>
<p><strong>Your IP:</strong> <?= secure_output($user_ip) ?></p>
<p><strong>Requests (24h):</strong> <?= $ip_stats['total_requests'] ?></p>
<p><strong>Threat Level:</strong> <span class="threat-<?= strtolower($threats['risk_assessment']) ?>"><?= $threats['risk_assessment'] ?></span></p>
<?php if ($ban_info): ?>
<div style="color: red; font-weight: bold;">
<p>⚠️ Your IP is currently banned!</p>
<p>Reason: <?= secure_output($ban_info['reason']) ?></p>
<p>Banned on: <?= secure_output($ban_info['ban_date']) ?></p>
</div>
<?php else: ?>
<div style="color: green;">
<p>✅ Your IP is not banned</p>
</div>
<?php endif; ?>
<h2>Recent Threats Detected</h2>
<?php if (!empty($threats['threats'])): ?>
<ul>
<?php foreach ($threats['threats'] as $threat): ?>
<li><?= secure_output($threat) ?></li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>No threats detected for your IP.</p>
<?php endif; ?>
<style>
.threat-high { color: #dc3545; }
.threat-medium { color: #fd7e14; }
.threat-low { color: #ffc107; }
.threat-none { color: #28a745; }
</style>
</body>
</html>

View File

@@ -0,0 +1,332 @@
<?php
/*******************************************************************************************************************
| Example: Queue System Integration
| This file demonstrates how to integrate the queue system into your EasyStream application
|*******************************************************************************************************************/
define('_ISVALID', true);
include_once 'f_core/config.core.php';
// Example 1: User Registration with Welcome Email
function handleUserRegistration($userData) {
global $class_database;
// Save user to database
$userId = $class_database->doInsert('db_accountuser', $userData);
if ($userId) {
// Enqueue welcome email (runs in background)
enqueue_welcome_email(
$userId,
$userData['usr_email'],
$userData['usr_user']
);
// Enqueue welcome notification
enqueue_notification(
$userId,
'welcome',
'Welcome to EasyStream! Start by uploading your first video.',
'Welcome to EasyStream!'
);
return $userId;
}
return false;
}
// Example 2: Video Upload Processing
function handleVideoUpload($videoData, $uploadedFile) {
global $class_database;
// Save video metadata to database
$videoId = $class_database->doInsert('db_videofiles', $videoData);
if ($videoId) {
// Move uploaded file to processing directory
$processingDir = 'f_data/data_userfiles/processing/';
$inputFile = $processingDir . $videoId . '_original.mp4';
$outputDir = 'f_data/data_userfiles/user_media/' . $videoData['usr_id'] . '/v/';
if (move_uploaded_file($uploadedFile['tmp_name'], $inputFile)) {
// Enqueue video processing job
$jobId = enqueue_video_processing(
$videoId,
$inputFile,
$outputDir,
['1080p', '720p', '480p', '360p']
);
// Notify user that upload is complete and processing started
enqueue_video_upload_notification(
$videoData['usr_id'],
$videoData['file_title'],
'/watch/' . $videoId
);
VLogger::getInstance()->info('Video upload queued for processing', [
'video_id' => $videoId,
'job_id' => $jobId,
'user_id' => $videoData['usr_id']
]);
return $videoId;
}
}
return false;
}
// Example 3: Password Reset Request
function handlePasswordResetRequest($email) {
global $class_database;
// Check if user exists
$user = $class_database->singleFieldValue('db_accountuser', 'usr_id', 'usr_email', $email);
if ($user) {
// Generate reset token
$resetToken = bin2hex(random_bytes(32));
$resetUrl = 'https://yourdomain.com/reset-password?token=' . $resetToken;
// Store reset token in database
$resetData = [
'usr_id' => $user,
'reset_token' => $resetToken,
'expires_at' => date('Y-m-d H:i:s', time() + 86400), // 24 hours
'created_at' => date('Y-m-d H:i:s')
];
$class_database->doInsert('db_password_resets', $resetData);
// Enqueue password reset email
enqueue_password_reset_email($email, $resetToken, $resetUrl);
return true;
}
return false;
}
// Example 4: Bulk Notification to Subscribers
function notifySubscribersOfNewVideo($channelId, $videoId, $videoTitle) {
global $class_database, $db;
// Get all subscribers of the channel
$sql = "SELECT usr_id FROM db_subscriptions WHERE channel_id = ? AND active = 1";
$result = $db->Execute($sql, [$channelId]);
$jobs = [];
$videoUrl = '/watch/' . $videoId;
// Get channel name
$channelName = $class_database->singleFieldValue('db_accountuser', 'usr_user', 'usr_id', $channelId);
while ($result && !$result->EOF) {
$subscriberId = $result->fields['usr_id'];
// Prepare notification job for each subscriber
$jobs[] = [
'class' => 'SendNotificationJob',
'data' => [
'user_id' => $subscriberId,
'type' => 'new_video',
'message' => "{$channelName} has uploaded a new video: '{$videoTitle}'",
'title' => 'New Video from Subscription',
'action_url' => $videoUrl,
'metadata' => [
'channel_id' => $channelId,
'channel_name' => $channelName,
'video_id' => $videoId
]
]
];
$result->MoveNext();
}
// Enqueue all notification jobs as a batch
if (!empty($jobs)) {
$jobIds = enqueue_batch($jobs, 'notifications');
VLogger::getInstance()->info('Subscriber notifications enqueued', [
'channel_id' => $channelId,
'video_id' => $videoId,
'subscriber_count' => count($jobs),
'job_count' => count($jobIds)
]);
return count($jobIds);
}
return 0;
}
// Example 5: Scheduled Content Publishing
function scheduleContentPublishing($contentId, $publishDate) {
$delay = strtotime($publishDate) - time();
if ($delay > 0) {
// Schedule the job to run at the specified time
$jobId = enqueue_job('PublishContentJob', [
'content_id' => $contentId,
'publish_date' => $publishDate
], 'default', $delay);
VLogger::getInstance()->info('Content publishing scheduled', [
'content_id' => $contentId,
'publish_date' => $publishDate,
'delay_seconds' => $delay,
'job_id' => $jobId
]);
return $jobId;
}
return false;
}
// Example 6: Daily Statistics Report
function scheduleDailyReports() {
// Calculate delay until next midnight
$tomorrow = strtotime('tomorrow midnight');
$delay = $tomorrow - time();
// Schedule daily report generation
$jobId = enqueue_job('GenerateDailyReportJob', [
'report_date' => date('Y-m-d'),
'recipients' => ['admin@easystream.com', 'analytics@easystream.com']
], 'default', $delay);
return $jobId;
}
// Example 7: Video Processing Completion Handler
function handleVideoProcessingComplete($videoId, $success, $results) {
global $class_database;
// Get video and user info
$video = $class_database->singleFieldValue('db_videofiles', '*', 'file_key', $videoId);
if ($video) {
// Update video status
$updateData = [
'processing_status' => $success ? 'completed' : 'failed',
'processed_at' => date('Y-m-d H:i:s')
];
$class_database->doUpdate('db_videofiles', 'file_key', $updateData, $videoId);
// Notify user of processing completion
enqueue_video_processing_notification(
$video['usr_id'],
$video['file_title'],
'/watch/' . $videoId,
$success
);
// If successful, notify subscribers
if ($success) {
notifySubscribersOfNewVideo(
$video['usr_id'],
$videoId,
$video['file_title']
);
}
}
}
// Example 8: Cleanup Old Jobs (can be run via cron)
function cleanupOldJobs() {
$redis = VRedis::getInstance();
if (!$redis->isConnected()) {
return false;
}
try {
$redisInstance = $redis->getRedis();
$jobKeys = $redisInstance->keys('job:*');
$cleaned = 0;
$cutoffTime = time() - (7 * 24 * 3600); // 7 days ago
foreach ($jobKeys as $jobKey) {
$job = $redis->get(str_replace('easystream:', '', $jobKey));
if ($job && isset($job['created_at']) && $job['created_at'] < $cutoffTime) {
// Only clean completed or failed jobs
if (in_array($job['status'], ['completed', 'failed'])) {
$redis->delete(str_replace('easystream:', '', $jobKey));
$cleaned++;
}
}
}
VLogger::getInstance()->info('Old jobs cleaned up', [
'cleaned_count' => $cleaned,
'cutoff_time' => date('Y-m-d H:i:s', $cutoffTime)
]);
return $cleaned;
} catch (Exception $e) {
VLogger::getInstance()->error('Job cleanup failed', [
'error' => $e->getMessage()
]);
return false;
}
}
// Example usage in your existing code:
// In your user registration handler:
if ($_POST['action'] === 'register') {
$userData = [
'usr_user' => VSecurity::postParam('username', 'alphanum'),
'usr_email' => VSecurity::postParam('email', 'email'),
'usr_password' => password_hash(VSecurity::postParam('password', 'string'), PASSWORD_DEFAULT),
'usr_datereg' => date('Y-m-d H:i:s')
];
$userId = handleUserRegistration($userData);
if ($userId) {
echo json_encode(['success' => true, 'user_id' => $userId]);
} else {
echo json_encode(['success' => false, 'error' => 'Registration failed']);
}
}
// In your video upload handler:
if ($_POST['action'] === 'upload_video' && isset($_FILES['video'])) {
$videoData = [
'usr_id' => $_SESSION['USER_ID'],
'file_title' => VSecurity::postParam('title', 'string'),
'file_description' => VSecurity::postParam('description', 'html'),
'upload_date' => date('Y-m-d H:i:s'),
'processing_status' => 'pending'
];
$videoId = handleVideoUpload($videoData, $_FILES['video']);
if ($videoId) {
echo json_encode(['success' => true, 'video_id' => $videoId]);
} else {
echo json_encode(['success' => false, 'error' => 'Upload failed']);
}
}
// In your password reset handler:
if ($_POST['action'] === 'reset_password') {
$email = VSecurity::postParam('email', 'email');
if (handlePasswordResetRequest($email)) {
echo json_encode(['success' => true, 'message' => 'Reset email sent']);
} else {
echo json_encode(['success' => false, 'error' => 'Email not found']);
}
}
echo "Queue integration examples completed. Check the queue management interface for job status.";
?>

View File

@@ -0,0 +1,140 @@
<?php
/*******************************************************************************************************************
| Example: Secure Form Implementation
| This file demonstrates how to use the new security features
|*******************************************************************************************************************/
define('_ISVALID', true);
include_once 'f_core/config.core.php';
// Example: Handling a secure form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validate CSRF token
if (!validate_csrf('user_update')) {
die('CSRF token validation failed');
}
// Rate limiting check
$user_ip = $_SERVER['REMOTE_ADDR'];
if (!check_rate_limit('form_submit_' . $user_ip, 5, 300)) {
die('Rate limit exceeded. Please try again later.');
}
// Secure parameter extraction
$username = post_param('username', 'alphanum', '', ['min_length' => 3, 'max_length' => 20]);
$email = post_param('email', 'email');
$age = post_param('age', 'int', 0, ['min' => 13, 'max' => 120]);
$bio = post_param('bio', 'html'); // Will be sanitized by VFilter
// Validate required fields
if (empty($username) || empty($email)) {
$error = 'Username and email are required';
} else {
// Process the form (save to database, etc.)
// The database class now uses prepared statements automatically
$update_data = [
'usr_user' => $username,
'usr_email' => $email,
'usr_age' => $age,
'usr_bio' => $bio
];
$success = $class_database->doUpdate('db_accountuser', 'usr_id', $update_data, $_SESSION['USER_ID']);
if ($success) {
log_security_event('user_profile_updated', ['user_id' => $_SESSION['USER_ID']]);
$message = 'Profile updated successfully';
} else {
$error = 'Failed to update profile';
}
}
}
// Example: Secure file upload
if (isset($_FILES['avatar'])) {
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$maxSize = 2 * 1024 * 1024; // 2MB
$validation = validate_file_upload($_FILES['avatar'], $allowedTypes, $maxSize);
if ($validation['valid']) {
// Process the file upload
$uploadDir = 'f_data/data_userfiles/avatars/';
$filename = uniqid() . '_' . basename($_FILES['avatar']['name']);
$uploadPath = $uploadDir . $filename;
if (move_uploaded_file($_FILES['avatar']['tmp_name'], $uploadPath)) {
log_security_event('avatar_uploaded', ['user_id' => $_SESSION['USER_ID'], 'filename' => $filename]);
$avatar_message = 'Avatar uploaded successfully';
} else {
$avatar_error = 'Failed to upload avatar';
}
} else {
$avatar_error = 'Invalid file: ' . $validation['error'];
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Secure Form Example</title>
</head>
<body>
<h1>Secure User Profile Form</h1>
<?php if (isset($error)): ?>
<div style="color: red;"><?= secure_output($error) ?></div>
<?php endif; ?>
<?php if (isset($message)): ?>
<div style="color: green;"><?= secure_output($message) ?></div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data">
<?= csrf_field('user_update') ?>
<div>
<label>Username:</label>
<input type="text" name="username" value="<?= secure_output(get_param('username', 'alphanum', '')) ?>" required>
</div>
<div>
<label>Email:</label>
<input type="email" name="email" value="<?= secure_output(get_param('email', 'email', '')) ?>" required>
</div>
<div>
<label>Age:</label>
<input type="number" name="age" value="<?= secure_output(get_param('age', 'int', '')) ?>" min="13" max="120">
</div>
<div>
<label>Bio:</label>
<textarea name="bio"><?= secure_output(get_param('bio', 'string', '')) ?></textarea>
</div>
<div>
<label>Avatar:</label>
<input type="file" name="avatar" accept="image/*">
<?php if (isset($avatar_error)): ?>
<div style="color: red;"><?= secure_output($avatar_error) ?></div>
<?php endif; ?>
<?php if (isset($avatar_message)): ?>
<div style="color: green;"><?= secure_output($avatar_message) ?></div>
<?php endif; ?>
</div>
<button type="submit">Update Profile</button>
</form>
<script>
// Example of secure JavaScript output
var userMessage = <?= secure_js($message ?? '') ?>;
if (userMessage) {
console.log('Success: ' + userMessage);
}
</script>
</body>
</html>

576
examples/rbac_examples.php Normal file
View File

@@ -0,0 +1,576 @@
<?php
/*******************************************************************************************************************
| Software Name : EasyStream
| Software Description : High End YouTube Clone Script with Videos, Shorts, Streams, Images, Audio, Documents, Blogs
| Software Author : (c) Sami Ahmed
|*******************************************************************************************************************
|
|*******************************************************************************************************************
| This source file is subject to the EasyStream Proprietary License Agreement.
|
| By using this software, you acknowledge having read this Agreement and agree to be bound thereby.
|*******************************************************************************************************************
| Copyright (c) 2025 Sami Ahmed. All rights reserved.
|*******************************************************************************************************************/
define('_ISVALID', true);
require_once '../f_core/config.core.php';
$auth = VAuth::getInstance();
$rbac = VRBAC::getInstance();
$middleware = VMiddleware::getInstance();
$security = VSecurity::getInstance();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EasyStream RBAC System Examples</title>
<style>
body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input, select, textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
button { background: #007cba; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; margin: 5px; }
button:hover { background: #005a87; }
button.danger { background: #dc3545; }
button.danger:hover { background: #c82333; }
button.success { background: #28a745; }
button.success:hover { background: #218838; }
.success { color: green; padding: 10px; background: #f0f8f0; border: 1px solid #d4edda; border-radius: 4px; }
.error { color: red; padding: 10px; background: #f8f0f0; border: 1px solid #f5c6cb; border-radius: 4px; }
.info { color: blue; padding: 10px; background: #f0f4f8; border: 1px solid #bee5eb; border-radius: 4px; }
.warning { color: orange; padding: 10px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 4px; }
.section { margin: 30px 0; padding: 20px; border: 1px solid #eee; border-radius: 8px; }
.user-info { background: #f8f9fa; padding: 15px; border-radius: 4px; margin: 10px 0; }
.permission-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; margin: 15px 0; }
.permission-item { padding: 10px; border: 1px solid #ddd; border-radius: 4px; text-align: center; }
.permission-granted { background: #d4edda; border-color: #c3e6cb; }
.permission-denied { background: #f8d7da; border-color: #f5c6cb; }
.role-badge { display: inline-block; padding: 4px 8px; border-radius: 12px; font-size: 12px; font-weight: bold; margin: 2px; }
.role-guest { background: #6c757d; color: white; }
.role-member { background: #17a2b8; color: white; }
.role-verified { background: #28a745; color: white; }
.role-premium { background: #ffc107; color: black; }
.role-moderator { background: #fd7e14; color: white; }
.role-admin { background: #dc3545; color: white; }
.role-superadmin { background: #6f42c1; color: white; }
table { width: 100%; border-collapse: collapse; margin: 15px 0; }
th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
th { background: #f8f9fa; }
.status-active { color: green; font-weight: bold; }
.status-suspended { color: orange; font-weight: bold; }
.status-banned { color: red; font-weight: bold; }
</style>
</head>
<body>
<h1>🛡️ EasyStream Role-Based Access Control (RBAC) System</h1>
<?php
// Handle form submissions
$message = '';
$messageType = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = VSecurity::postParam('action', 'string');
switch ($action) {
case 'change_role':
if (VSecurity::validateCSRFFromPost('admin_action')) {
$userId = VSecurity::postParam('user_id', 'int');
$newRole = VSecurity::postParam('new_role', 'string');
$reason = VSecurity::postParam('reason', 'string');
$currentUser = $auth->getCurrentUser();
if ($currentUser && $rbac->hasPermission('user.manage')) {
$result = $rbac->changeUserRole($userId, $newRole, $currentUser['user_id'], $reason);
$message = $result ? 'Role changed successfully' : 'Failed to change role';
$messageType = $result ? 'success' : 'error';
} else {
$message = 'Permission denied';
$messageType = 'error';
}
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'grant_permission':
if (VSecurity::validateCSRFFromPost('admin_action')) {
$userId = VSecurity::postParam('user_id', 'int');
$permission = VSecurity::postParam('permission', 'string');
$expiresAt = VSecurity::postParam('expires_at', 'string');
$currentUser = $auth->getCurrentUser();
if ($currentUser && $rbac->hasPermission('user.manage')) {
$result = $rbac->grantPermission($userId, $permission, $currentUser['user_id'], $expiresAt ?: null);
$message = $result ? 'Permission granted successfully' : 'Failed to grant permission';
$messageType = $result ? 'success' : 'error';
} else {
$message = 'Permission denied';
$messageType = 'error';
}
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'revoke_permission':
if (VSecurity::validateCSRFFromPost('admin_action')) {
$userId = VSecurity::postParam('user_id', 'int');
$permission = VSecurity::postParam('permission', 'string');
$currentUser = $auth->getCurrentUser();
if ($currentUser && $rbac->hasPermission('user.manage')) {
$result = $rbac->revokePermission($userId, $permission, $currentUser['user_id']);
$message = $result ? 'Permission revoked successfully' : 'Failed to revoke permission';
$messageType = $result ? 'success' : 'error';
} else {
$message = 'Permission denied';
$messageType = 'error';
}
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'suspend_user':
if (VSecurity::validateCSRFFromPost('admin_action')) {
$userId = VSecurity::postParam('user_id', 'int');
$reason = VSecurity::postParam('reason', 'string');
$expiresAt = VSecurity::postParam('expires_at', 'string');
$currentUser = $auth->getCurrentUser();
if ($currentUser && $rbac->hasPermission('user.ban')) {
$result = $rbac->suspendUser($userId, $reason, $currentUser['user_id'], $expiresAt ?: null);
$message = $result ? 'User suspended successfully' : 'Failed to suspend user';
$messageType = $result ? 'success' : 'error';
} else {
$message = 'Permission denied';
$messageType = 'error';
}
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'ban_user':
if (VSecurity::validateCSRFFromPost('admin_action')) {
$userId = VSecurity::postParam('user_id', 'int');
$reason = VSecurity::postParam('reason', 'string');
$permanent = VSecurity::postParam('permanent', 'boolean', false);
$currentUser = $auth->getCurrentUser();
if ($currentUser && $rbac->hasPermission('user.ban')) {
$result = $rbac->banUser($userId, $reason, $currentUser['user_id'], $permanent);
$message = $result ? 'User banned successfully' : 'Failed to ban user';
$messageType = $result ? 'success' : 'error';
} else {
$message = 'Permission denied';
$messageType = 'error';
}
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
case 'reinstate_user':
if (VSecurity::validateCSRFFromPost('admin_action')) {
$userId = VSecurity::postParam('user_id', 'int');
$reason = VSecurity::postParam('reason', 'string');
$currentUser = $auth->getCurrentUser();
if ($currentUser && $rbac->hasPermission('user.ban')) {
$result = $rbac->reinstateUser($userId, $reason, $currentUser['user_id']);
$message = $result ? 'User reinstated successfully' : 'Failed to reinstate user';
$messageType = $result ? 'success' : 'error';
} else {
$message = 'Permission denied';
$messageType = 'error';
}
} else {
$message = 'Invalid CSRF token';
$messageType = 'error';
}
break;
}
}
// Display message
if ($message) {
echo "<div class='{$messageType}'>{$message}</div>";
}
// Check authentication status
$isAuthenticated = $auth->isAuthenticated();
$currentUser = $auth->getCurrentUser();
?>
<div class="info">
<strong>Authentication Status:</strong>
<?php if ($isAuthenticated): ?>
✅ Authenticated as <strong><?= htmlspecialchars($currentUser['username']) ?></strong>
<span class="role-badge role-<?= $currentUser['role'] ?>"><?= strtoupper($currentUser['role']) ?></span>
<?php else: ?>
❌ Not authenticated - <a href="auth_examples.php">Login here</a>
<?php endif; ?>
</div>
<?php if ($isAuthenticated): ?>
<div class="section">
<h2>🔐 Your Current Permissions</h2>
<?php
$userPermissions = $rbac->getUserPermissions($currentUser['user_id']);
$allPermissions = VRBAC::PERMISSIONS;
?>
<div class="permission-grid">
<?php foreach ($allPermissions as $permission => $description): ?>
<?php $hasPermission = in_array($permission, $userPermissions); ?>
<div class="permission-item <?= $hasPermission ? 'permission-granted' : 'permission-denied' ?>">
<strong><?= htmlspecialchars($permission) ?></strong><br>
<small><?= htmlspecialchars($description) ?></small><br>
<?= $hasPermission ? '✅ Granted' : '❌ Denied' ?>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="section">
<h2>🧪 Permission Testing</h2>
<p>Test specific permissions with your current role:</p>
<div class="permission-grid">
<?php
$testPermissions = [
'content.view', 'content.create', 'content.moderate',
'admin.dashboard', 'user.ban', 'api.admin',
'upload.large_files', 'feature.beta'
];
foreach ($testPermissions as $permission):
$hasPermission = $rbac->hasPermission($permission);
?>
<div class="permission-item <?= $hasPermission ? 'permission-granted' : 'permission-denied' ?>">
<strong><?= htmlspecialchars($permission) ?></strong><br>
<?= $hasPermission ? '✅ You have this permission' : '❌ You lack this permission' ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php if ($rbac->hasPermission('user.manage')): ?>
<div class="section">
<h2>👥 User Management</h2>
<p>Manage other users (Admin/Moderator only):</p>
<?php
// Get list of users for management
global $class_database;
$db = $class_database->dbConnection();
$sql = "SELECT user_id, username, email, role, status, created_at, last_login FROM db_users ORDER BY created_at DESC LIMIT 10";
$result = $db->Execute($sql);
?>
<table>
<thead>
<tr>
<th>User</th>
<th>Role</th>
<th>Status</th>
<th>Last Login</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php while ($result && !$result->EOF): ?>
<tr>
<td>
<strong><?= htmlspecialchars($result->fields['username']) ?></strong><br>
<small><?= htmlspecialchars($result->fields['email']) ?></small>
</td>
<td>
<span class="role-badge role-<?= $result->fields['role'] ?>">
<?= strtoupper($result->fields['role']) ?>
</span>
</td>
<td>
<span class="status-<?= $result->fields['status'] ?>">
<?= strtoupper($result->fields['status']) ?>
</span>
</td>
<td>
<?= $result->fields['last_login'] ? date('Y-m-d H:i', strtotime($result->fields['last_login'])) : 'Never' ?>
</td>
<td>
<?php if ($result->fields['user_id'] != $currentUser['user_id']): ?>
<button onclick="showUserActions(<?= $result->fields['user_id'] ?>, '<?= htmlspecialchars($result->fields['username']) ?>')">
Manage
</button>
<?php else: ?>
<em>You</em>
<?php endif; ?>
</td>
</tr>
<?php $result->MoveNext(); ?>
<?php endwhile; ?>
</tbody>
</table>
</div>
<!-- User Management Modal -->
<div id="userModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000;">
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 30px; border-radius: 8px; max-width: 600px; width: 90%;">
<h3>Manage User: <span id="modalUsername"></span></h3>
<div class="form-group">
<h4>Change Role</h4>
<form method="POST" style="display: inline-block;">
<input type="hidden" name="action" value="change_role">
<input type="hidden" name="user_id" id="modalUserId">
<?= VSecurity::getCSRFField('admin_action') ?>
<select name="new_role" required>
<option value="">Select Role</option>
<?php foreach (VRBAC::ROLE_HIERARCHY as $role => $level): ?>
<option value="<?= $role ?>"><?= ucfirst($role) ?></option>
<?php endforeach; ?>
</select>
<input type="text" name="reason" placeholder="Reason for role change" required>
<button type="submit">Change Role</button>
</form>
</div>
<div class="form-group">
<h4>Grant Custom Permission</h4>
<form method="POST" style="display: inline-block;">
<input type="hidden" name="action" value="grant_permission">
<input type="hidden" name="user_id" id="modalUserId2">
<?= VSecurity::getCSRFField('admin_action') ?>
<select name="permission" required>
<option value="">Select Permission</option>
<?php foreach (VRBAC::PERMISSIONS as $permission => $description): ?>
<option value="<?= $permission ?>"><?= $permission ?> - <?= $description ?></option>
<?php endforeach; ?>
</select>
<input type="datetime-local" name="expires_at" placeholder="Expiration (optional)">
<button type="submit" class="success">Grant Permission</button>
</form>
</div>
<?php if ($rbac->hasPermission('user.ban')): ?>
<div class="form-group">
<h4>Suspend User</h4>
<form method="POST" style="display: inline-block;">
<input type="hidden" name="action" value="suspend_user">
<input type="hidden" name="user_id" id="modalUserId3">
<?= VSecurity::getCSRFField('admin_action') ?>
<input type="text" name="reason" placeholder="Suspension reason" required>
<input type="datetime-local" name="expires_at" placeholder="Expiration (optional)">
<button type="submit" class="danger">Suspend User</button>
</form>
</div>
<div class="form-group">
<h4>Ban User</h4>
<form method="POST" style="display: inline-block;">
<input type="hidden" name="action" value="ban_user">
<input type="hidden" name="user_id" id="modalUserId4">
<?= VSecurity::getCSRFField('admin_action') ?>
<input type="text" name="reason" placeholder="Ban reason" required>
<label>
<input type="checkbox" name="permanent" value="1">
Permanent ban
</label>
<button type="submit" class="danger">Ban User</button>
</form>
</div>
<div class="form-group">
<h4>Reinstate User</h4>
<form method="POST" style="display: inline-block;">
<input type="hidden" name="action" value="reinstate_user">
<input type="hidden" name="user_id" id="modalUserId5">
<?= VSecurity::getCSRFField('admin_action') ?>
<input type="text" name="reason" placeholder="Reinstatement reason" required>
<button type="submit" class="success">Reinstate User</button>
</form>
</div>
<?php endif; ?>
<button onclick="closeUserModal()" style="background: #6c757d;">Close</button>
</div>
</div>
<?php endif; ?>
<?php else: ?>
<div class="warning">
<p>You need to be logged in to see RBAC features. <a href="auth_examples.php">Login here</a></p>
</div>
<?php endif; ?>
<div class="section">
<h2>📋 Role Hierarchy & Permissions</h2>
<p>EasyStream uses a hierarchical role system where higher roles inherit permissions from lower roles:</p>
<table>
<thead>
<tr>
<th>Role</th>
<th>Level</th>
<th>Key Permissions</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="role-badge role-guest">GUEST</span></td>
<td>0</td>
<td>content.view, comment.view</td>
<td>Unregistered users - can only view content</td>
</tr>
<tr>
<td><span class="role-badge role-member">MEMBER</span></td>
<td>10</td>
<td>content.create, comment.create, upload.basic</td>
<td>Registered users - can create and interact</td>
</tr>
<tr>
<td><span class="role-badge role-verified">VERIFIED</span></td>
<td>20</td>
<td>content.publish, upload.document</td>
<td>Email verified users - can publish content</td>
</tr>
<tr>
<td><span class="role-badge role-premium">PREMIUM</span></td>
<td>30</td>
<td>upload.large_files, feature.beta</td>
<td>Premium subscribers - enhanced features</td>
</tr>
<tr>
<td><span class="role-badge role-moderator">MODERATOR</span></td>
<td>40</td>
<td>content.moderate, comment.moderate</td>
<td>Community moderators - can moderate content</td>
</tr>
<tr>
<td><span class="role-badge role-admin">ADMIN</span></td>
<td>50</td>
<td>admin.dashboard, user.manage, user.ban</td>
<td>Site administrators - full management access</td>
</tr>
<tr>
<td><span class="role-badge role-superadmin">SUPERADMIN</span></td>
<td>60</td>
<td>admin.system, ALL PERMISSIONS</td>
<td>Super administrators - complete system access</td>
</tr>
</tbody>
</table>
</div>
<div class="section">
<h2>🔧 Middleware Examples</h2>
<p>The RBAC system includes middleware for protecting routes and API endpoints:</p>
<h3>PHP Middleware Usage:</h3>
<pre><code>// Require authentication
$middleware->requireAuth();
// Require specific role
$middleware->requireRole('admin');
// Require specific permission
$middleware->requirePermission('content.moderate');
// Require multiple permissions (any)
$middleware->requirePermission(['content.edit', 'content.moderate']);
// Require content ownership
$middleware->requireContentOwnership($videoId, 'video');
// Chain multiple middleware
$middleware->requireAll([
['method' => 'requireAuth'],
['method' => 'requireRole', 'params' => ['verified']],
['method' => 'requirePermission', 'params' => ['content.create']]
]);
// API middleware
$middleware->requireAPI(true); // Require auth for API</code></pre>
<h3>Example Protected Routes:</h3>
<pre><code>// Admin dashboard
if (!$middleware->requireRole('admin')) {
exit; // Redirects to access denied
}
// Content creation
if (!$middleware->requirePermission('content.create')) {
exit; // Handles access denial
}
// User management
if (!$middleware->requirePermission('user.manage')) {
exit;
}</code></pre>
</div>
<div class="section">
<h2>🛡️ Security Features</h2>
<ul>
<li><strong>Hierarchical Roles:</strong> Higher roles inherit lower role permissions</li>
<li><strong>Custom Permissions:</strong> Grant specific permissions to individual users</li>
<li><strong>Permission Expiration:</strong> Set expiration dates for temporary permissions</li>
<li><strong>Context-Based Access:</strong> Content ownership and contextual permissions</li>
<li><strong>Audit Logging:</strong> All role changes and permission grants are logged</li>
<li><strong>Session Integration:</strong> Seamless integration with authentication system</li>
<li><strong>Middleware Protection:</strong> Easy route and API protection</li>
<li><strong>Caching:</strong> Permission caching for performance</li>
<li><strong>User Management:</strong> Suspend, ban, and reinstate users</li>
<li><strong>API Integration:</strong> Full API support with permission checking</li>
</ul>
</div>
<script>
function showUserActions(userId, username) {
document.getElementById('modalUsername').textContent = username;
document.getElementById('modalUserId').value = userId;
document.getElementById('modalUserId2').value = userId;
document.getElementById('modalUserId3').value = userId;
document.getElementById('modalUserId4').value = userId;
document.getElementById('modalUserId5').value = userId;
document.getElementById('userModal').style.display = 'block';
}
function closeUserModal() {
document.getElementById('userModal').style.display = 'none';
}
// Close modal when clicking outside
document.getElementById('userModal').addEventListener('click', function(e) {
if (e.target === this) {
closeUserModal();
}
});
</script>
</body>
</html>