init commit
This commit is contained in:
166
routes/api.php
Normal file
166
routes/api.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* API Routes
|
||||
* Professional Resume Builder - Laravel Application
|
||||
*
|
||||
* @author David Valera Melendez <david@valera-melendez.de>
|
||||
* @created 2025-08-08
|
||||
* @location Made in Germany 🇩🇪
|
||||
*/
|
||||
|
||||
use App\Http\Controllers\Api\AuthController;
|
||||
use App\Http\Controllers\Api\ResumeController;
|
||||
use App\Http\Controllers\Api\TemplateController;
|
||||
use App\Http\Controllers\Api\UserController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register API routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider and all of them will
|
||||
| be assigned to the "api" middleware group. Make something great!
|
||||
|
|
||||
*/
|
||||
|
||||
// Public API Routes
|
||||
Route::prefix('v1')->group(function () {
|
||||
// Authentication
|
||||
Route::prefix('auth')->group(function () {
|
||||
Route::post('login', [AuthController::class, 'login']);
|
||||
Route::post('register', [AuthController::class, 'register']);
|
||||
Route::post('forgot-password', [AuthController::class, 'forgotPassword']);
|
||||
Route::post('reset-password', [AuthController::class, 'resetPassword']);
|
||||
Route::post('refresh', [AuthController::class, 'refresh']);
|
||||
});
|
||||
|
||||
// Public Templates
|
||||
Route::get('templates', [TemplateController::class, 'index']);
|
||||
Route::get('templates/{template}', [TemplateController::class, 'show']);
|
||||
|
||||
// Public Resume Views
|
||||
Route::get('resumes/public/{publicUrl}', [ResumeController::class, 'showPublic']);
|
||||
});
|
||||
|
||||
// Protected API Routes
|
||||
Route::middleware(['auth:sanctum', 'throttle:60,1'])->prefix('v1')->group(function () {
|
||||
// Authentication
|
||||
Route::prefix('auth')->group(function () {
|
||||
Route::post('logout', [AuthController::class, 'logout']);
|
||||
Route::get('me', [AuthController::class, 'me']);
|
||||
Route::put('profile', [AuthController::class, 'updateProfile']);
|
||||
Route::put('password', [AuthController::class, 'updatePassword']);
|
||||
});
|
||||
|
||||
// User Management
|
||||
Route::prefix('user')->group(function () {
|
||||
Route::get('profile', [UserController::class, 'profile']);
|
||||
Route::put('profile', [UserController::class, 'updateProfile']);
|
||||
Route::post('avatar', [UserController::class, 'uploadAvatar']);
|
||||
Route::delete('avatar', [UserController::class, 'deleteAvatar']);
|
||||
Route::get('stats', [UserController::class, 'stats']);
|
||||
Route::delete('account', [UserController::class, 'deleteAccount']);
|
||||
});
|
||||
|
||||
// Resume Management
|
||||
Route::apiResource('resumes', ResumeController::class);
|
||||
Route::prefix('resumes')->group(function () {
|
||||
Route::post('{resume}/duplicate', [ResumeController::class, 'duplicate']);
|
||||
Route::post('{resume}/make-public', [ResumeController::class, 'makePublic']);
|
||||
Route::post('{resume}/make-private', [ResumeController::class, 'makePrivate']);
|
||||
Route::post('{resume}/autosave', [ResumeController::class, 'autosave']);
|
||||
Route::get('{resume}/download-pdf', [ResumeController::class, 'downloadPdf']);
|
||||
Route::get('{resume}/analytics', [ResumeController::class, 'analytics']);
|
||||
Route::post('{resume}/sections/{section}', [ResumeController::class, 'updateSection']);
|
||||
});
|
||||
|
||||
// Templates
|
||||
Route::get('templates', [TemplateController::class, 'index']);
|
||||
Route::get('templates/{template}', [TemplateController::class, 'show']);
|
||||
Route::get('templates/{template}/preview', [TemplateController::class, 'preview']);
|
||||
});
|
||||
|
||||
// Admin API Routes
|
||||
Route::middleware(['auth:sanctum', 'admin', 'throttle:100,1'])->prefix('v1/admin')->group(function () {
|
||||
// User Management
|
||||
Route::apiResource('users', AdminUserController::class);
|
||||
Route::post('users/{user}/activate', [AdminUserController::class, 'activate']);
|
||||
Route::post('users/{user}/deactivate', [AdminUserController::class, 'deactivate']);
|
||||
|
||||
// Template Management
|
||||
Route::apiResource('templates', AdminTemplateController::class);
|
||||
|
||||
// Analytics
|
||||
Route::get('analytics/dashboard', [AdminAnalyticsController::class, 'dashboard']);
|
||||
Route::get('analytics/users', [AdminAnalyticsController::class, 'users']);
|
||||
Route::get('analytics/resumes', [AdminAnalyticsController::class, 'resumes']);
|
||||
|
||||
// System
|
||||
Route::get('system/health', [AdminSystemController::class, 'health']);
|
||||
Route::get('system/logs', [AdminSystemController::class, 'logs']);
|
||||
});
|
||||
|
||||
// Health Check
|
||||
Route::get('health', function () {
|
||||
return response()->json([
|
||||
'status' => 'ok',
|
||||
'service' => 'Professional Resume Builder API',
|
||||
'version' => 'v1',
|
||||
'timestamp' => now()->toISOString(),
|
||||
'author' => 'David Valera Melendez',
|
||||
'location' => 'Made in Germany 🇩🇪'
|
||||
]);
|
||||
});
|
||||
|
||||
// API Documentation
|
||||
Route::get('docs', function () {
|
||||
return response()->json([
|
||||
'name' => 'Professional Resume Builder API',
|
||||
'version' => 'v1',
|
||||
'description' => 'Enterprise-grade API for resume building and management',
|
||||
'author' => 'David Valera Melendez',
|
||||
'email' => 'david@valera-melendez.de',
|
||||
'location' => 'Made in Germany 🇩🇪',
|
||||
'endpoints' => [
|
||||
'authentication' => '/api/v1/auth',
|
||||
'users' => '/api/v1/user',
|
||||
'resumes' => '/api/v1/resumes',
|
||||
'templates' => '/api/v1/templates',
|
||||
'admin' => '/api/v1/admin'
|
||||
],
|
||||
'documentation' => 'https://docs.valera-melendez.de/resume-builder-api'
|
||||
]);
|
||||
});
|
||||
|
||||
// Rate Limited Public Endpoints
|
||||
Route::middleware(['throttle:30,1'])->prefix('v1/public')->group(function () {
|
||||
// Contact form
|
||||
Route::post('contact', [PublicController::class, 'contact']);
|
||||
|
||||
// Newsletter subscription
|
||||
Route::post('newsletter', [PublicController::class, 'newsletter']);
|
||||
|
||||
// Template preview requests
|
||||
Route::post('template-preview', [PublicController::class, 'templatePreview']);
|
||||
});
|
||||
|
||||
// Webhook Endpoints
|
||||
Route::prefix('webhooks')->group(function () {
|
||||
Route::post('stripe', [WebhookController::class, 'stripe'])->name('webhooks.stripe');
|
||||
Route::post('mailgun', [WebhookController::class, 'mailgun'])->name('webhooks.mailgun');
|
||||
Route::post('analytics', [WebhookController::class, 'analytics'])->name('webhooks.analytics');
|
||||
});
|
||||
|
||||
// Fallback for undefined API routes
|
||||
Route::fallback(function () {
|
||||
return response()->json([
|
||||
'error' => 'Endpoint not found',
|
||||
'message' => 'The requested API endpoint does not exist.',
|
||||
'available_versions' => ['v1'],
|
||||
'documentation' => 'https://docs.valera-melendez.de/resume-builder-api'
|
||||
], 404);
|
||||
});
|
||||
18
routes/channels.php
Normal file
18
routes/channels.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Broadcast;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Broadcast Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may register all of the event broadcasting channels that your
|
||||
| application supports. The given channel authorization callbacks are
|
||||
| used to check if an authenticated user can listen to the channel.
|
||||
|
|
||||
*/
|
||||
|
||||
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
|
||||
return (int) $user->id === (int) $id;
|
||||
});
|
||||
19
routes/console.php
Normal file
19
routes/console.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Console Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is where you may define all of your Closure based console
|
||||
| commands. Each Closure is bound to a command instance allowing a
|
||||
| simple approach to interacting with each command's IO methods.
|
||||
|
|
||||
*/
|
||||
|
||||
Artisan::command('inspire', function () {
|
||||
$this->comment(Inspiring::quote());
|
||||
})->purpose('Display an inspiring quote');
|
||||
170
routes/web.php
Normal file
170
routes/web.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Web Routes
|
||||
* Professional Resume Builder - Laravel Application
|
||||
*
|
||||
* @author David Valera Melendez <david@valera-melendez.de>
|
||||
* @created 2025-08-08
|
||||
* @location Made in Germany 🇩🇪
|
||||
*/
|
||||
|
||||
use App\Http\Controllers\Auth\AuthController;
|
||||
use App\Http\Controllers\DashboardController;
|
||||
use App\Http\Controllers\ResumeBuilderController;
|
||||
use App\Http\Controllers\HomeController;
|
||||
use App\Http\Controllers\TemplateController;
|
||||
use App\Http\Controllers\ProfileController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register web routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider and all of them will
|
||||
| be assigned to the "web" middleware group. Make something great!
|
||||
|
|
||||
*/
|
||||
|
||||
// Public Routes
|
||||
Route::get('/', [HomeController::class, 'index'])->name('home');
|
||||
Route::get('/features', [HomeController::class, 'features'])->name('features');
|
||||
Route::get('/pricing', [HomeController::class, 'pricing'])->name('pricing');
|
||||
Route::get('/help', [HomeController::class, 'help'])->name('help');
|
||||
Route::get('/contact', [HomeController::class, 'contact'])->name('contact');
|
||||
Route::get('/privacy', [HomeController::class, 'privacy'])->name('privacy');
|
||||
Route::get('/terms', [HomeController::class, 'terms'])->name('terms');
|
||||
Route::get('/support', [HomeController::class, 'support'])->name('support');
|
||||
|
||||
// Public Resume Views
|
||||
Route::get('/resume/{publicUrl}', [ResumeBuilderController::class, 'showPublic'])->name('public.resume');
|
||||
|
||||
// Authentication Routes
|
||||
Route::middleware('guest')->group(function () {
|
||||
// Login
|
||||
Route::get('/login', [AuthController::class, 'showLoginForm'])->name('login');
|
||||
Route::post('/login', [AuthController::class, 'login']);
|
||||
|
||||
// Registration
|
||||
Route::get('/register', [AuthController::class, 'showRegistrationForm'])->name('register');
|
||||
Route::post('/register', [AuthController::class, 'register']);
|
||||
|
||||
// Password Reset
|
||||
Route::get('/forgot-password', [AuthController::class, 'showForgotPasswordForm'])->name('password.request');
|
||||
Route::post('/forgot-password', [AuthController::class, 'sendResetLinkEmail'])->name('password.email');
|
||||
Route::get('/reset-password/{token}', [AuthController::class, 'showResetPasswordForm'])->name('password.reset');
|
||||
Route::post('/reset-password', [AuthController::class, 'resetPassword'])->name('password.update');
|
||||
});
|
||||
|
||||
// Authenticated Routes
|
||||
Route::middleware('auth')->group(function () {
|
||||
// Logout
|
||||
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
|
||||
|
||||
// Dashboard
|
||||
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
|
||||
|
||||
// Profile Management
|
||||
Route::prefix('profile')->name('profile.')->group(function () {
|
||||
Route::get('/', [ProfileController::class, 'show'])->name('show');
|
||||
Route::get('/edit', [ProfileController::class, 'edit'])->name('edit');
|
||||
Route::put('/', [ProfileController::class, 'update'])->name('update');
|
||||
Route::delete('/', [ProfileController::class, 'destroy'])->name('destroy');
|
||||
});
|
||||
|
||||
// Account Settings
|
||||
Route::prefix('account')->name('account.')->group(function () {
|
||||
Route::get('/settings', [ProfileController::class, 'settings'])->name('settings');
|
||||
Route::put('/password', [ProfileController::class, 'updatePassword'])->name('password.update');
|
||||
Route::put('/preferences', [ProfileController::class, 'updatePreferences'])->name('preferences.update');
|
||||
});
|
||||
|
||||
// Resume Builder
|
||||
Route::prefix('resume-builder')->name('resume-builder.')->group(function () {
|
||||
Route::get('/', [ResumeBuilderController::class, 'index'])->name('index');
|
||||
Route::get('/create', [ResumeBuilderController::class, 'create'])->name('create');
|
||||
Route::post('/', [ResumeBuilderController::class, 'store'])->name('store');
|
||||
Route::get('/{resume}/edit', [ResumeBuilderController::class, 'edit'])->name('edit');
|
||||
Route::put('/{resume}', [ResumeBuilderController::class, 'update'])->name('update');
|
||||
Route::get('/{resume}/preview', [ResumeBuilderController::class, 'preview'])->name('preview');
|
||||
Route::get('/{resume}/download-pdf', [ResumeBuilderController::class, 'downloadPdf'])->name('download-pdf');
|
||||
Route::delete('/{resume}', [ResumeBuilderController::class, 'destroy'])->name('destroy');
|
||||
|
||||
// Resume Actions
|
||||
Route::post('/{resume}/duplicate', [ResumeBuilderController::class, 'duplicate'])->name('duplicate');
|
||||
Route::post('/{resume}/make-public', [ResumeBuilderController::class, 'makePublic'])->name('make-public');
|
||||
Route::post('/{resume}/make-private', [ResumeBuilderController::class, 'makePrivate'])->name('make-private');
|
||||
});
|
||||
|
||||
// Templates
|
||||
Route::prefix('templates')->name('templates.')->group(function () {
|
||||
Route::get('/', [TemplateController::class, 'index'])->name('index');
|
||||
Route::get('/{template}', [TemplateController::class, 'show'])->name('show');
|
||||
Route::get('/{template}/preview', [TemplateController::class, 'preview'])->name('preview');
|
||||
});
|
||||
});
|
||||
|
||||
// API Routes for AJAX requests
|
||||
Route::middleware(['auth', 'throttle:60,1'])->prefix('api')->name('api.')->group(function () {
|
||||
// Resume API
|
||||
Route::prefix('resumes')->name('resumes.')->group(function () {
|
||||
Route::get('/', [ResumeBuilderController::class, 'apiIndex'])->name('index');
|
||||
Route::post('/{resume}/autosave', [ResumeBuilderController::class, 'autosave'])->name('autosave');
|
||||
Route::get('/{resume}/analytics', [ResumeBuilderController::class, 'analytics'])->name('analytics');
|
||||
});
|
||||
|
||||
// Profile API
|
||||
Route::prefix('profile')->name('profile.')->group(function () {
|
||||
Route::put('/avatar', [ProfileController::class, 'updateAvatar'])->name('avatar.update');
|
||||
Route::get('/completion', [ProfileController::class, 'completion'])->name('completion');
|
||||
});
|
||||
});
|
||||
|
||||
// Admin Routes (Future Enhancement)
|
||||
// Route::middleware(['auth', 'admin'])->prefix('admin')->name('admin.')->group(function () {
|
||||
// Route::get('/dashboard', [AdminController::class, 'dashboard'])->name('dashboard');
|
||||
// Route::resource('users', AdminUserController::class);
|
||||
// Route::resource('templates', AdminTemplateController::class);
|
||||
// });
|
||||
|
||||
// Webhook Routes (Future Enhancement)
|
||||
// Route::prefix('webhooks')->name('webhooks.')->group(function () {
|
||||
// Route::post('/payment/stripe', [WebhookController::class, 'stripe'])->name('stripe');
|
||||
// Route::post('/analytics', [WebhookController::class, 'analytics'])->name('analytics');
|
||||
// });
|
||||
|
||||
// Health Check
|
||||
Route::get('/health', function () {
|
||||
return response()->json([
|
||||
'status' => 'ok',
|
||||
'timestamp' => now()->toISOString(),
|
||||
'version' => config('app.version', '1.0.0'),
|
||||
'environment' => app()->environment(),
|
||||
'author' => 'David Valera Melendez',
|
||||
'location' => 'Made in Germany 🇩🇪'
|
||||
]);
|
||||
})->name('health');
|
||||
|
||||
// Sitemap (SEO)
|
||||
Route::get('/sitemap.xml', [SeoController::class, 'sitemap'])->name('sitemap');
|
||||
|
||||
// Robots.txt (SEO)
|
||||
Route::get('/robots.txt', function () {
|
||||
$content = "User-agent: *\n";
|
||||
$content .= "Allow: /\n";
|
||||
$content .= "Disallow: /admin/\n";
|
||||
$content .= "Disallow: /api/\n";
|
||||
$content .= "Sitemap: " . route('sitemap') . "\n";
|
||||
|
||||
return response($content, 200, ['Content-Type' => 'text/plain']);
|
||||
})->name('robots');
|
||||
|
||||
// Fallback for SPA-like behavior (if needed)
|
||||
Route::fallback(function () {
|
||||
return response()->view('errors.404', [
|
||||
'title' => 'Page Not Found',
|
||||
'message' => 'The page you are looking for could not be found.'
|
||||
], 404);
|
||||
});
|
||||
Reference in New Issue
Block a user