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:
362
examples/auth_examples.php
Normal file
362
examples/auth_examples.php
Normal 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>
|
||||
203
examples/example_enhanced_logging.php
Normal file
203
examples/example_enhanced_logging.php
Normal 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/";
|
||||
?>
|
||||
339
examples/example_fingerprint_integration.php
Normal file
339
examples/example_fingerprint_integration.php
Normal 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>
|
||||
182
examples/example_ip_tracking_usage.php
Normal file
182
examples/example_ip_tracking_usage.php
Normal 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>
|
||||
332
examples/example_queue_integration.php
Normal file
332
examples/example_queue_integration.php
Normal 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.";
|
||||
?>
|
||||
140
examples/example_secure_form.php
Normal file
140
examples/example_secure_form.php
Normal 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
576
examples/rbac_examples.php
Normal 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>
|
||||
Reference in New Issue
Block a user