210 lines
6.8 KiB
PHP
210 lines
6.8 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/web.php';
|
|
require_once __DIR__ . '/auth/Auth.php';
|
|
require_once __DIR__ . '/auth/AuthMiddleware.php';
|
|
require_once __DIR__ . '/auth/providers/JsonUserProvider.php';
|
|
require_once __DIR__ . '/auth/providers/SqliteUserProvider.php';
|
|
require_once __DIR__ . '/auth/providers/MysqlUserProvider.php';
|
|
|
|
// Choose your storage provider
|
|
// Option 1: JSON file storage
|
|
$userProvider = new JsonUserProvider(__DIR__ . '/storage/users.json');
|
|
|
|
// Option 2: SQLite database
|
|
// $userProvider = new SqliteUserProvider(__DIR__ . '/storage/database.sqlite');
|
|
|
|
// Option 3: MySQL database
|
|
// $userProvider = new MysqlUserProvider([
|
|
// 'host' => 'localhost',
|
|
// 'database' => 'myapp',
|
|
// 'username' => 'root',
|
|
// 'password' => 'password'
|
|
// ]);
|
|
|
|
// Create web application
|
|
$app = new Web(debug: true);
|
|
|
|
// Initialize auth system
|
|
$auth = new Auth($userProvider, new Session());
|
|
$authMiddleware = new AuthMiddleware($auth);
|
|
|
|
// Make auth available in all routes
|
|
$app->use(function($context, $next) use ($auth) {
|
|
$context->set('auth', $auth);
|
|
$next();
|
|
});
|
|
|
|
// Public routes
|
|
$app->get('/', function($context) {
|
|
$user = $context->get('auth')->user();
|
|
$context->html("<h1>Welcome " . ($user ? $user->username : 'Guest') . "</h1>");
|
|
});
|
|
|
|
// Registration page
|
|
$app->get('/register', function($context) {
|
|
$csrfToken = $context->session->token();
|
|
$context->html(<<<HTML
|
|
<form method="POST" action="/register">
|
|
<input type="hidden" name="_token" value="{$csrfToken}">
|
|
<input type="text" name="username" placeholder="Username" required><br>
|
|
<input type="email" name="email" placeholder="Email" required><br>
|
|
<input type="password" name="password" placeholder="Password" required><br>
|
|
<input type="password" name="password_confirmation" placeholder="Confirm Password" required><br>
|
|
<button type="submit">Register</button>
|
|
</form>
|
|
HTML);
|
|
});
|
|
|
|
// Registration handler
|
|
$app->post('/register', function($context) use ($auth) {
|
|
// Validate input
|
|
$validator = $context->validate($context->request->all(), [
|
|
'username' => 'required|alphaNum|min:3|max:20',
|
|
'email' => 'required|email',
|
|
'password' => 'required|min:6|confirmed'
|
|
]);
|
|
|
|
// Check if username/email already exists
|
|
if ($auth->provider->findByUsername($context->request->input('username'))) {
|
|
$context->error(400, 'Username already taken');
|
|
return;
|
|
}
|
|
|
|
if ($auth->provider->findByEmail($context->request->input('email'))) {
|
|
$context->error(400, 'Email already registered');
|
|
return;
|
|
}
|
|
|
|
// Register user
|
|
$user = $auth->register([
|
|
'username' => $context->request->input('username'),
|
|
'email' => $context->request->input('email'),
|
|
'password' => $context->request->input('password')
|
|
]);
|
|
|
|
$context->redirect('/dashboard');
|
|
})->use($authMiddleware->verifyCsrf());
|
|
|
|
// Login page
|
|
$app->get('/login', function($context) {
|
|
$csrfToken = $context->session->token();
|
|
$context->html(<<<HTML
|
|
<form method="POST" action="/login">
|
|
<input type="hidden" name="_token" value="{$csrfToken}">
|
|
<input type="text" name="username" placeholder="Username or Email" required><br>
|
|
<input type="password" name="password" placeholder="Password" required><br>
|
|
<label>
|
|
<input type="checkbox" name="remember"> Remember me
|
|
</label><br>
|
|
<button type="submit">Login</button>
|
|
</form>
|
|
HTML);
|
|
})->use($authMiddleware->requireGuest());
|
|
|
|
// Login handler
|
|
$app->post('/login', function($context) use ($auth) {
|
|
$credentials = [
|
|
'username' => $context->request->input('username'),
|
|
'password' => $context->request->input('password')
|
|
];
|
|
|
|
$remember = $context->request->input('remember') === 'on';
|
|
|
|
if ($auth->attempt($credentials, $remember)) {
|
|
$context->redirect('/dashboard');
|
|
} else {
|
|
$context->error(401, 'Invalid credentials');
|
|
}
|
|
})->use($authMiddleware->verifyCsrf())
|
|
->use($authMiddleware->requireGuest());
|
|
|
|
// Logout
|
|
$app->post('/logout', function($context) use ($auth) {
|
|
$auth->logout();
|
|
$context->redirect('/');
|
|
})->use($authMiddleware->verifyCsrf());
|
|
|
|
// Protected routes
|
|
$app->group('/dashboard', function($app) use ($authMiddleware) {
|
|
// Apply auth middleware to all routes in this group
|
|
$app->use($authMiddleware->requireAuth());
|
|
|
|
$app->get('', function($context) {
|
|
$user = $context->get('user');
|
|
$csrfToken = $context->session->token();
|
|
$context->html(<<<HTML
|
|
<h1>Dashboard</h1>
|
|
<p>Welcome, {$user->username}!</p>
|
|
<p>Email: {$user->email}</p>
|
|
<form method="POST" action="/logout" style="display:inline">
|
|
<input type="hidden" name="_token" value="{$csrfToken}">
|
|
<button type="submit">Logout</button>
|
|
</form>
|
|
HTML);
|
|
});
|
|
|
|
$app->get('/profile', function($context) {
|
|
$user = $context->get('user');
|
|
$context->json($user->toSafeArray());
|
|
});
|
|
|
|
$app->post('/update-profile', function($context) use ($auth) {
|
|
$user = $context->get('user');
|
|
|
|
$validator = $context->validate($context->request->all(), [
|
|
'email' => 'email',
|
|
'username' => 'alphaNum|min:3|max:20'
|
|
]);
|
|
|
|
$data = $context->request->only(['email', 'username']);
|
|
|
|
if (!empty($data)) {
|
|
$auth->provider->update($user, $data);
|
|
$auth->refresh();
|
|
}
|
|
|
|
$context->json(['success' => true, 'user' => $auth->user()->toSafeArray()]);
|
|
})->use($authMiddleware->verifyCsrf());
|
|
});
|
|
|
|
// Admin only routes
|
|
$app->group('/admin', function($app) use ($authMiddleware) {
|
|
// Require admin role
|
|
$app->use($authMiddleware->requireRole('admin'));
|
|
|
|
$app->get('', function($context) {
|
|
$context->html('<h1>Admin Panel</h1>');
|
|
});
|
|
});
|
|
|
|
// API routes with rate limiting
|
|
$app->group('/api', function($app) use ($authMiddleware, $auth) {
|
|
// Optional auth for API
|
|
$app->use($authMiddleware->optional());
|
|
|
|
// Rate limiting: 60 requests per minute
|
|
$app->use($authMiddleware->rateLimit(60, 1));
|
|
|
|
$app->post('/login', function($context) use ($auth) {
|
|
$credentials = $context->request->only(['username', 'password']);
|
|
|
|
if ($auth->validate($credentials)) {
|
|
$auth->attempt($credentials);
|
|
return ['success' => true, 'user' => $auth->user()->toSafeArray()];
|
|
}
|
|
|
|
return $context->json(['error' => 'Invalid credentials'], 401);
|
|
});
|
|
|
|
$app->get('/me', function($context) use ($auth) {
|
|
if ($auth->guest()) {
|
|
return $context->json(['error' => 'Unauthenticated'], 401);
|
|
}
|
|
|
|
return $auth->user()->toSafeArray();
|
|
});
|
|
});
|
|
|
|
// Run the application
|
|
$app->run(); |