feat(monitoring): integrate sentry with tenant context and gitea actions
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 48s
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 48s
This commit is contained in:
402
GEMINI.md
402
GEMINI.md
@@ -4,11 +4,11 @@
|
||||
|
||||
**Growup Pro** is a whitelabel implementation of [Krayin Laravel CRM](https://github.com/krayin/laravel-crm) with multi-tenancy support. The platform allows multiple companies/organizations to use the same CRM instance with complete data isolation through subdomain-based tenancy.
|
||||
|
||||
**CURRENT STATUS: DEBUGGING PHASE**
|
||||
- **Multi-tenancy implementation**: Installed but encountering issues.
|
||||
- **Issue 1**: `localhost` not recognized as central domain (TenantCouldNotBeIdentifiedOnDomainException).
|
||||
- **Issue 2**: Tenant instances (`tenant1.localhost`) load but missing CSS (Asset 404).
|
||||
- **Goal**: Fix central domain detection and static asset serving for tenants.
|
||||
**CURRENT STATUS: FEATURE IMPLEMENTATION PHASE**
|
||||
- **Multi-tenancy implementation**: Stable.
|
||||
- **Authentication**: Stable (Infinite redirect loop resolved).
|
||||
- **Core Systems**: Localhost and central domain detection working.
|
||||
- **Goal**: Implement advanced admin features, Sentry integration, and finalize branding.
|
||||
|
||||
### Key Differentiators from Krayin
|
||||
- **Rebranding**: Complete visual overhaul with Growup Pro branding
|
||||
@@ -326,350 +326,15 @@ Route::post('/register-tenant', [TenantController::class, 'register']);
|
||||
- `resources/lang/pt_BR/` - Portuguese translations
|
||||
- `resources/views/layouts/app.blade.php` - Main layout (branded)
|
||||
|
||||
## CRITICAL: Krayin Authentication Issues (MUST RESOLVE BEFORE MULTI-TENANCY)
|
||||
## Resolved Issues (History)
|
||||
|
||||
**IMPORTANT:** Multi-tenancy implementation is ON HOLD until we stabilize Krayin's base authentication system. We have experienced critical login issues that must be resolved first.
|
||||
### Authentication Stabilization
|
||||
Previous critical issues with infinite redirect loops, CSRF token mismatches (419), and session persistence have been resolved. The authentication system is now stable across local, staging, and production environments.
|
||||
|
||||
### Known Authentication Problems
|
||||
|
||||
#### Problem 1: Error 419 - CSRF Token Mismatch
|
||||
**Symptoms:**
|
||||
- User enters credentials
|
||||
- Form submission returns 419 error
|
||||
- Login fails even with correct credentials
|
||||
|
||||
**Possible Causes:**
|
||||
- Session driver misconfiguration (`file` vs `redis` vs `database`)
|
||||
- Session cookie not being set properly
|
||||
- Domain/subdomain mismatch in session configuration
|
||||
- `APP_URL` mismatch with actual access URL
|
||||
- CSRF token expiration (session timeout too short)
|
||||
- Reverse proxy stripping session cookies
|
||||
|
||||
**Debug Steps:**
|
||||
```bash
|
||||
# Check current session driver
|
||||
grep SESSION_DRIVER .env
|
||||
|
||||
# Clear all caches
|
||||
php artisan cache:clear
|
||||
php artisan config:clear
|
||||
php artisan route:clear
|
||||
php artisan view:clear
|
||||
|
||||
# Check session files (if using file driver)
|
||||
ls -la storage/framework/sessions/
|
||||
|
||||
# Test session configuration
|
||||
php artisan tinker
|
||||
>>> session()->put('test', 'value');
|
||||
>>> session()->get('test'); # Should return 'value'
|
||||
```
|
||||
|
||||
**Potential Fixes:**
|
||||
1. **Ensure APP_URL matches access URL exactly:**
|
||||
```env
|
||||
# If accessing via localhost:8000
|
||||
APP_URL=http://localhost:8000
|
||||
|
||||
# If accessing via IP
|
||||
APP_URL=http://192.168.1.100:8000
|
||||
```
|
||||
|
||||
2. **Check session configuration** (`config/session.php`):
|
||||
```php
|
||||
'domain' => env('SESSION_DOMAIN', null), // Should match your domain
|
||||
'secure' => env('SESSION_SECURE_COOKIE', false), // false for HTTP, true for HTTPS
|
||||
'same_site' => 'lax', // Not 'strict' - can cause issues
|
||||
```
|
||||
|
||||
3. **Verify CSRF middleware** is present in `app/Http/Kernel.php`:
|
||||
```php
|
||||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class, // THIS IS CRITICAL
|
||||
// ...
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
4. **Check CSRF exceptions** (if login route needs to be excluded):
|
||||
```php
|
||||
// app/Http/Middleware/VerifyCsrfToken.php
|
||||
protected $except = [
|
||||
// Add routes here ONLY as last resort
|
||||
];
|
||||
```
|
||||
|
||||
#### Problem 2: Tenant Database Connection Issues
|
||||
**Symptoms:**
|
||||
- Login attempt fails silently
|
||||
- Database connection errors in logs
|
||||
- Can't authenticate against tenant-specific users table
|
||||
|
||||
**Possible Causes:**
|
||||
- Tenant database doesn't exist yet
|
||||
- Database migrations not run on tenant database
|
||||
- Wrong database being queried (central vs tenant)
|
||||
- Tenant context not initialized before authentication attempt
|
||||
|
||||
**Debug Steps:**
|
||||
```bash
|
||||
# List all databases
|
||||
php artisan tinker
|
||||
>>> DB::select('SHOW DATABASES');
|
||||
|
||||
# Check which database Laravel is connected to
|
||||
>>> DB::connection()->getDatabaseName();
|
||||
|
||||
# Verify users table exists in tenant DB
|
||||
>>> Schema::connection('tenant')->hasTable('users');
|
||||
```
|
||||
|
||||
**Critical Notes for Multi-tenancy:**
|
||||
- Authentication MUST work in single-tenant (non-multi-tenant) mode FIRST
|
||||
- Only after stable authentication should we add tenant context switching
|
||||
- Tenant middleware should NOT interfere with session/CSRF handling
|
||||
|
||||
#### Problem 3: Infinite Login Redirect Loop (CRITICAL - UNRESOLVED)
|
||||
**Symptoms:**
|
||||
- User enters valid credentials
|
||||
- Form submits successfully (no 419 error)
|
||||
- Page redirects back to login page
|
||||
- User is never authenticated
|
||||
- Dashboard never loads
|
||||
- No error messages displayed
|
||||
|
||||
**This is the MOST CRITICAL issue and must be debugged thoroughly.**
|
||||
|
||||
**Possible Causes:**
|
||||
1. **Session not persisting after authentication:**
|
||||
- Session written but immediately destroyed
|
||||
- Session driver issue (file permissions, Redis connection)
|
||||
- Session ID regeneration failing
|
||||
|
||||
2. **Authentication middleware misconfigured:**
|
||||
- `Auth` middleware blocking authenticated users
|
||||
- Wrong guard being checked
|
||||
- Middleware order issues in Kernel.php
|
||||
|
||||
3. **Redirect logic broken:**
|
||||
- `redirectTo` property in LoginController pointing to login route
|
||||
- Intended destination not being preserved
|
||||
- Route name/path mismatch
|
||||
|
||||
4. **Auth guard misconfigured:**
|
||||
- Wrong guard specified in `config/auth.php`
|
||||
- Provider not finding users correctly
|
||||
- User model relationship issues
|
||||
|
||||
5. **Cookie domain/path mismatch:**
|
||||
- Session cookie being set but not read back
|
||||
- Domain attribute too restrictive
|
||||
- Path attribute incorrect
|
||||
|
||||
**Detailed Debug Steps:**
|
||||
|
||||
```bash
|
||||
# 1. Enable query logging to see what's happening
|
||||
# Add to AppServiceProvider boot():
|
||||
DB::listen(function ($query) {
|
||||
Log::info('Query: ' . $query->sql . ' - Bindings: ' . json_encode($query->bindings));
|
||||
});
|
||||
|
||||
# 2. Add extensive logging to login process
|
||||
# In LoginController or wherever authentication happens:
|
||||
Log::info('Login attempt for: ' . request()->email);
|
||||
Log::info('Session ID before auth: ' . session()->getId());
|
||||
|
||||
# After Auth::attempt():
|
||||
Log::info('Auth attempt result: ' . (Auth::check() ? 'success' : 'failed'));
|
||||
Log::info('Session ID after auth: ' . session()->getId());
|
||||
Log::info('Authenticated user: ' . (Auth::user() ? Auth::user()->id : 'none'));
|
||||
|
||||
# 3. Check session files directly
|
||||
# If using file driver:
|
||||
tail -f storage/logs/laravel.log &
|
||||
# Make login attempt
|
||||
# Check if session file is created and contains auth data:
|
||||
cat storage/framework/sessions/*
|
||||
|
||||
# 4. Test authentication in Tinker
|
||||
php artisan tinker
|
||||
>>> $user = User::first();
|
||||
>>> Auth::login($user);
|
||||
>>> Auth::check(); # Should return true
|
||||
>>> session()->all(); # Check session data
|
||||
>>> session()->save(); # Manually save session
|
||||
```
|
||||
|
||||
**Configuration Files to Check:**
|
||||
|
||||
1. **config/auth.php**
|
||||
```php
|
||||
'defaults' => [
|
||||
'guard' => 'web', // Verify this matches your usage
|
||||
'passwords' => 'users',
|
||||
],
|
||||
|
||||
'guards' => [
|
||||
'web' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
],
|
||||
|
||||
'providers' => [
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => App\Models\User::class, // Verify model path
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
2. **config/session.php**
|
||||
```php
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||
'expire_on_close' => false,
|
||||
'encrypt' => false,
|
||||
'files' => storage_path('framework/sessions'),
|
||||
'connection' => env('SESSION_CONNECTION', null),
|
||||
'table' => 'sessions',
|
||||
'store' => env('SESSION_STORE', null),
|
||||
'lottery' => [2, 100],
|
||||
'cookie' => env('SESSION_COOKIE', Str::slug(env('APP_NAME', 'laravel'), '_').'_session'),
|
||||
'path' => '/',
|
||||
'domain' => env('SESSION_DOMAIN', null), // Should be NULL for localhost
|
||||
'secure' => env('SESSION_SECURE_COOKIE', false), // FALSE for HTTP
|
||||
'http_only' => true,
|
||||
'same_site' => 'lax', // NOT 'strict'
|
||||
```
|
||||
|
||||
3. **Verify LoginController redirect logic:**
|
||||
```php
|
||||
// Typical Laravel LoginController
|
||||
protected $redirectTo = '/dashboard'; // NOT '/login'!
|
||||
|
||||
// Or method:
|
||||
protected function redirectTo() {
|
||||
return '/dashboard'; // Verify this route exists and is accessible
|
||||
}
|
||||
|
||||
// Check authenticated() method isn't causing issues:
|
||||
protected function authenticated(Request $request, $user) {
|
||||
// Should NOT return redirect to login
|
||||
Log::info('User authenticated: ' . $user->id);
|
||||
}
|
||||
```
|
||||
|
||||
4. **Check middleware in routes:**
|
||||
```php
|
||||
// routes/web.php
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/dashboard', [DashboardController::class, 'index']);
|
||||
});
|
||||
|
||||
// Verify 'auth' middleware is defined in Kernel.php
|
||||
// and uses the correct guard
|
||||
```
|
||||
|
||||
**Testing Methodology:**
|
||||
|
||||
1. **Isolate the problem:**
|
||||
```bash
|
||||
# Create a minimal test route
|
||||
Route::get('/test-auth', function () {
|
||||
Auth::login(User::first());
|
||||
return [
|
||||
'authenticated' => Auth::check(),
|
||||
'user_id' => Auth::id(),
|
||||
'session_id' => session()->getId(),
|
||||
'session_data' => session()->all(),
|
||||
];
|
||||
});
|
||||
```
|
||||
|
||||
2. **Test session persistence separately:**
|
||||
```bash
|
||||
Route::get('/test-session-write', function () {
|
||||
session(['test_key' => 'test_value_' . time()]);
|
||||
return 'Session written: ' . session('test_key');
|
||||
});
|
||||
|
||||
Route::get('/test-session-read', function () {
|
||||
return 'Session read: ' . session('test_key', 'NOT FOUND');
|
||||
});
|
||||
```
|
||||
|
||||
3. **Test authentication without redirect:**
|
||||
```bash
|
||||
Route::post('/test-login', function (Request $request) {
|
||||
$credentials = $request->only('email', 'password');
|
||||
|
||||
if (Auth::attempt($credentials)) {
|
||||
return [
|
||||
'status' => 'success',
|
||||
'user' => Auth::user()->only(['id', 'email']),
|
||||
'session_id' => session()->getId(),
|
||||
];
|
||||
}
|
||||
|
||||
return ['status' => 'failed'];
|
||||
});
|
||||
```
|
||||
|
||||
**Critical Checklist Before Multi-tenancy:**
|
||||
|
||||
- [ ] Session driver works correctly (can write and read session data)
|
||||
- [ ] CSRF protection works (no 419 errors)
|
||||
- [ ] Auth::attempt() returns true for valid credentials
|
||||
- [ ] Auth::check() returns true immediately after Auth::attempt()
|
||||
- [ ] Session persists across requests (test with simple session()->put/get)
|
||||
- [ ] User can access protected routes after authentication
|
||||
- [ ] No infinite redirect loops
|
||||
- [ ] Login process completes in browser devtools Network tab (check for redirect chains)
|
||||
- [ ] Session cookie is set and sent back with subsequent requests (check devtools Application/Storage)
|
||||
|
||||
**DO NOT proceed with multi-tenancy until ALL checklist items pass.**
|
||||
|
||||
### Debugging Tools
|
||||
|
||||
```bash
|
||||
# Enable debug mode
|
||||
APP_DEBUG=true
|
||||
|
||||
# Tail logs in real-time
|
||||
tail -f storage/logs/laravel.log
|
||||
|
||||
# Check Redis connection (if using Redis sessions)
|
||||
redis-cli ping
|
||||
|
||||
# Check MySQL connection
|
||||
php artisan tinker
|
||||
>>> DB::connection()->getPdo();
|
||||
|
||||
# Dump session driver configuration
|
||||
php artisan tinker
|
||||
>>> config('session.driver');
|
||||
>>> config('session.files');
|
||||
>>> config('session.connection');
|
||||
|
||||
# Test file permissions
|
||||
ls -la storage/framework/sessions/
|
||||
# Should be writable by web server user
|
||||
```
|
||||
|
||||
### Next Steps After Resolving Authentication
|
||||
|
||||
1. Document the exact fix that resolved the issue
|
||||
2. Create test cases to prevent regression
|
||||
3. Only then begin multi-tenancy implementation
|
||||
4. Add monitoring/logging to detect authentication issues early
|
||||
### Multi-tenancy Setup
|
||||
- **Localhost Detection**: Fixed `TenantCouldNotBeIdentifiedOnDomainException`.
|
||||
- **Asset Loading**: Fixed 404 errors for tenant static assets.
|
||||
- **Database Isolation**: Successfully implemented per-tenant databases.
|
||||
|
||||
---
|
||||
|
||||
@@ -883,32 +548,28 @@ CLOUDFLARE_ZONE_ID=...
|
||||
|
||||
## Admin Dashboard for Tenant Management
|
||||
|
||||
The platform includes a comprehensive admin dashboard for managing tenants and monitoring platform health.
|
||||
The platform includes a basic admin dashboard for managing tenants.
|
||||
|
||||
### Dashboard Features
|
||||
### Current Implementation (MVP)
|
||||
- **Route**: `/super-admin` (protected by `super_admin` middleware)
|
||||
- **Features**:
|
||||
- Basic Tenant CRUD (Create, Read, Update, Delete)
|
||||
- Session management (Login/Logout)
|
||||
- **Tech Stack**: Custom Blade views (`resources/views/super-admin`) + Bootstrap/Tailwind (inherited)
|
||||
|
||||
**Tenant Management:**
|
||||
- View all active tenants with key metrics
|
||||
- Create/edit/delete tenant accounts
|
||||
- Suspend or activate tenant access
|
||||
- View tenant resource usage (storage, bandwidth, users)
|
||||
- Manage tenant subscriptions and billing
|
||||
### Pending Features (Roadmap)
|
||||
|
||||
**Analytics & Monitoring:**
|
||||
- Total active tenants count
|
||||
- Growth metrics (new tenants per month)
|
||||
- Resource utilization per tenant
|
||||
- Most active tenants (by usage)
|
||||
- Revenue tracking (if applicable)
|
||||
- System health overview
|
||||
|
||||
**Tenant Details View:**
|
||||
- Company information and contact details
|
||||
- Subdomain and custom domain settings
|
||||
- User count and activity logs
|
||||
- Storage usage and database size
|
||||
- Last login and activity timestamps
|
||||
- Custom branding settings (logo, colors)
|
||||
**Enhanced Tenant Management:**
|
||||
- View tenant resource usage (storage, bandwidth, users)
|
||||
- Manage tenant subscriptions and billing
|
||||
- Suspend or activate tenant access
|
||||
|
||||
**Bulk Operations:**
|
||||
- Bulk tenant creation via CSV import
|
||||
@@ -923,18 +584,11 @@ The platform includes a comprehensive admin dashboard for managing tenants and m
|
||||
- Feature flags management
|
||||
- Maintenance mode per tenant
|
||||
|
||||
### Access Control
|
||||
- Admin dashboard accessible only to super admins
|
||||
- Route: `/admin` (protected by `SuperAdmin` middleware)
|
||||
- Audit logs for all admin actions
|
||||
- Two-factor authentication required
|
||||
|
||||
### Implementation Notes
|
||||
- Built with Filament Admin Panel (recommended) or custom Blade views
|
||||
- Real-time updates using Livewire
|
||||
- Caching for performance (tenant list, metrics)
|
||||
- API endpoints for programmatic access
|
||||
- Webhooks for tenant lifecycle events (created, suspended, deleted)
|
||||
- Currently built with custom Blade views.
|
||||
- **Future Upgrade**: Consider migrating to Filament Admin Panel for richer UI/UX.
|
||||
- **Security**: Route protected by `super_admin` middleware.
|
||||
- **Audit**: Need to implement audit logs for admin actions.
|
||||
|
||||
## Notes for Gemini AI Assistant
|
||||
|
||||
|
||||
Reference in New Issue
Block a user