feat: initialize Next.js project with Prisma, authentication, and rankings page

This commit is contained in:
2026-03-27 14:50:00 -07:00
parent 96f7cb86d3
commit 66e4baa643
208 changed files with 8522 additions and 9035 deletions
+283
View File
@@ -0,0 +1,283 @@
# Authentication, Authorization, and Accounting (AAA) Design
## Overview
Implement a comprehensive AAA system for EuchreCamp with user authentication, role-based authorization, and activity logging.
## Authentication (Who are you?)
### User Model
```ruby
# Database Schema
table :users do
primary_key :id
foreign_key :player_id, :players # Links to existing player record
column :email, String, null: false, unique: true
column :password_digest, String, null: false
column :confirmed, Boolean, default: false
column :confirmation_token, String
column :confirmation_sent_at, DateTime
column :reset_password_token, String
column :reset_password_sent_at, DateTime
column :failed_login_attempts, Integer, default: 0
column :locked_until, DateTime
column :last_login_at, DateTime
column :last_login_ip, String
column :created_at, DateTime, null: false
column :updated_at, DateTime, null: false
end
# Indexes
add_index :users, :email, unique: true
add_index :users, :confirmation_token
add_index :users, :reset_password_token
```
### Authentication Flow
1. User enters email and password
2. System verifies email exists and account is not locked
3. BCrypt verifies password hash
4. If successful:
- Update `last_login_at` and `last_login_ip`
- Reset `failed_login_attempts`
- Create session/token
5. If failed:
- Increment `failed_login_attempts`
- Lock account after 5 failed attempts (15 minutes)
### Session Management
- Use signed cookies for session storage
- Session expires after 30 days of inactivity
- Session invalidation on password change
- Concurrent session limits (optional)
### Password Requirements
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one special character
### Registration Flow
1. User registers with email and password
2. System creates user record with `confirmed: false`
3. Send confirmation email with unique token
4. User clicks link to confirm account
5. Account activated and ready for login
### Password Reset Flow
1. User requests password reset
2. System generates unique token (expires in 1 hour)
3. Send reset email with token link
4. User enters new password
5. System validates and updates password hash
6. Invalidate all existing sessions
## Authorization (What can you do?)
### Role-Based Access Control (RBAC)
#### Roles
```ruby
ROLES = {
player: 0, # Default user - can view rankings, own profile
tournament_admin: 1, # Can manage specific tournaments
club_admin: 2, # Superuser - full access
system_admin: 3 # Technical admin access
}
```
#### Permission Matrix
| Permission | Player | Tournament Admin | Club Admin | System Admin |
|------------|--------|------------------|------------|--------------|
| View rankings | ✅ | ✅ | ✅ | ✅ |
| View own profile | ✅ | ✅ | ✅ | ✅ |
| Edit own profile | ✅ | ✅ | ✅ | ✅ |
| View other profiles | ✅ | ✅ | ✅ | ✅ |
| Record own matches | ✅ | ✅ | ✅ | ✅ |
| Create tournaments | ❌ | ✅ | ✅ | ✅ |
| Manage own tournaments | ❌ | ✅ | ✅ | ✅ |
| Manage all tournaments | ❌ | ❌ | ✅ | ✅ |
| Manage all players | ❌ | ❌ | ✅ | ✅ |
| Club settings | ❌ | ❌ | ✅ | ✅ |
| System settings | ❌ | ❌ | ❌ | ✅ |
### Implementation
```ruby
module EuchreCamp
module Auth
class Authorization
def self.can?(user, action, resource = nil)
case action
when :view_rankings
true # All users can view rankings
when :edit_profile
resource.nil? || resource.id == user.player_id
when :create_tournament
user.club_admin? || user.system_admin?
when :manage_tournament
user.club_admin? || user.system_admin? ||
(user.tournament_admin? && resource.admin_id == user.player_id)
when :manage_players
user.club_admin? || user.system_admin?
else
false
end
end
end
end
end
```
### Middleware
- Authentication middleware checks for valid session
- Authorization middleware verifies permissions
- Redirect unauthenticated users to login
- Show 403 Forbidden for unauthorized actions
## Accounting (What did you do?)
### Activity Logging
```ruby
table :activity_logs do
primary_key :id
foreign_key :user_id, :users
column :action, String, null: false # e.g., 'login', 'create_tournament', 'record_match'
column :resource_type, String # e.g., 'tournament', 'match', 'player'
column :resource_id, Integer
column :ip_address, String
column :user_agent, String
column :details, JSON # Additional context
column :created_at, DateTime, null: false
end
add_index :activity_logs, [:user_id, :created_at]
add_index :activity_logs, [:resource_type, :resource_id]
```
### Tracked Events
- Authentication events (login, logout, password change)
- Tournament management (create, update, delete, schedule)
- Match recording (create, update, delete)
- Player management (create, update)
- Settings changes
### Audit Reports
- User activity timeline
- Tournament lifecycle audit
- Match result verification log
- System changes overview
## Implementation Plan
### Phase 1: Authentication (Week 1-2)
- [ ] Create users table and model
- [ ] Implement BCrypt password hashing
- [ ] Build login/logout actions
- [ ] Create registration flow
- [ ] Add session management
- [ ] Password reset functionality
### Phase 2: Authorization (Week 2-3)
- [ ] Define roles and permissions
- [ ] Implement RBAC middleware
- [ ] Add role assignment UI (for club admins)
- [ ] Protect routes based on roles
- [ ] Add permission checks to actions
### Phase 3: Accounting (Week 3-4)
- [ ] Create activity logging system
- [ ] Track key events
- [ ] Build audit reports UI
- [ ] Add activity feed to dashboard
### Phase 4: Security Hardening (Week 4-5)
- [ ] Rate limiting on login attempts
- [ ] IP-based lockout
- [ ] Secure cookie settings
- [ ] CSRF protection
- [ ] Security headers
- [ ] Session fixation prevention
## Security Considerations
### Password Security
- Use BCrypt with cost factor 12+
- Never store plaintext passwords
- Enforce strong password policy
- Rate limit password attempts
### Session Security
- Use signed, encrypted cookies
- Regenerate session ID on privilege escalation
- Set appropriate expiration times
- Invalidate on password change
### Access Control
- Principle of least privilege
- Defense in depth
- Fail securely (deny by default)
- Log all access attempts
### Data Protection
- Encrypt sensitive data at rest
- Secure transmission (HTTPS only)
- Regular security audits
- Compliance with privacy regulations
## API Endpoints
### Authentication
```
POST /auth/login # Login with email/password
POST /auth/logout # Logout current session
POST /auth/register # Create new account
POST /auth/confirm # Confirm email address
POST /auth/forgot # Request password reset
POST /auth/reset # Reset password with token
```
### Users
```
GET /users/me # Get current user profile
PATCH /users/me # Update own profile
GET /users/:id # Get user profile (public)
```
### Admin
```
GET /admin/users # List users (club admin only)
PATCH /admin/users/:id # Update user roles (club admin only)
GET /admin/activity # View audit logs (club admin only)
```
## Testing Strategy
### Unit Tests
- Password hashing verification
- Permission calculations
- Session management
- Activity logging
### Integration Tests
- Login/logout flow
- Registration process
- Password reset
- Role-based access
### Security Tests
- SQL injection prevention
- XSS prevention
- CSRF protection
- Rate limiting
- Session security
## Migration Steps
1. Create users table and related migrations
2. Add foreign key from users to players
3. Migrate existing player data to users (optional)
4. Update navigation to show login/logout links
5. Add authentication checks to existing actions
6. Implement role assignment for existing admins
7. Set up activity logging for new features