Add PDF reports, file uploads, admin auth, and comprehensive tests

Features:
- PDF service for generating task reports with ReportLab-style formatting
- Storage service for file uploads (local and S3-compatible)
- Admin authentication middleware with JWT support
- Admin user model and repository

Infrastructure:
- Updated Docker configuration for admin panel builds
- Email service enhancements for task notifications
- Updated router with admin and file upload routes
- Environment configuration updates

Tests:
- Unit tests for handlers (auth, residence, task)
- Unit tests for models (user, residence, task)
- Unit tests for repositories (user, residence, task)
- Unit tests for services (residence, task)
- Integration test setup
- Test utilities for mocking database and services

Database:
- Admin user seed data
- Updated test data seeds

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-27 23:36:20 -06:00
parent 2817deee3c
commit 469f21a833
50 changed files with 6795 additions and 582 deletions

View File

@@ -3,18 +3,31 @@
-- Note: Run ./dev.sh seed first to populate lookup tables
-- Test Users (password is 'password123' hashed with bcrypt)
-- bcrypt hash for 'password123': $2a$10$rQEY6fXqPmGd5L5o5vJXt.Nk7NqKvHJBJFk5QbF1wqQKw1Z5K3X2a
-- bcrypt hash for 'password123': $2a$10$KB4rf2NNj0a80lwlwJhaFukE2/THJXbcGZMks7vR3zykyN4zkF6xi
INSERT INTO auth_user (id, username, password, email, first_name, last_name, is_active, is_staff, is_superuser, date_joined)
VALUES
(1, 'admin', '$2a$10$rQEY6fXqPmGd5L5o5vJXt.Nk7NqKvHJBJFk5QbF1wqQKw1Z5K3X2a', 'admin@example.com', 'Admin', 'User', true, true, true, NOW()),
(2, 'john', '$2a$10$rQEY6fXqPmGd5L5o5vJXt.Nk7NqKvHJBJFk5QbF1wqQKw1Z5K3X2a', 'john@example.com', 'John', 'Doe', true, false, false, NOW()),
(3, 'jane', '$2a$10$rQEY6fXqPmGd5L5o5vJXt.Nk7NqKvHJBJFk5QbF1wqQKw1Z5K3X2a', 'jane@example.com', 'Jane', 'Smith', true, false, false, NOW()),
(4, 'bob', '$2a$10$rQEY6fXqPmGd5L5o5vJXt.Nk7NqKvHJBJFk5QbF1wqQKw1Z5K3X2a', 'bob@example.com', 'Bob', 'Wilson', true, false, false, NOW())
(1, 'admin', '$2a$10$KB4rf2NNj0a80lwlwJhaFukE2/THJXbcGZMks7vR3zykyN4zkF6xi', 'admin@example.com', 'Admin', 'User', true, true, true, NOW()),
(2, 'john', '$2a$10$KB4rf2NNj0a80lwlwJhaFukE2/THJXbcGZMks7vR3zykyN4zkF6xi', 'john@example.com', 'John', 'Doe', true, false, false, NOW()),
(3, 'jane', '$2a$10$KB4rf2NNj0a80lwlwJhaFukE2/THJXbcGZMks7vR3zykyN4zkF6xi', 'jane@example.com', 'Jane', 'Smith', true, false, false, NOW()),
(4, 'bob', '$2a$10$KB4rf2NNj0a80lwlwJhaFukE2/THJXbcGZMks7vR3zykyN4zkF6xi', 'bob@example.com', 'Bob', 'Wilson', true, false, false, NOW())
ON CONFLICT (id) DO UPDATE SET
username = EXCLUDED.username,
password = EXCLUDED.password,
email = EXCLUDED.email,
first_name = EXCLUDED.first_name,
last_name = EXCLUDED.last_name;
last_name = EXCLUDED.last_name,
is_active = EXCLUDED.is_active;
-- User Profiles (email verified)
INSERT INTO user_userprofile (id, created_at, updated_at, user_id, verified, bio, phone_number, date_of_birth, profile_picture)
VALUES
(1, NOW(), NOW(), 1, true, '', '', NULL, ''),
(2, NOW(), NOW(), 2, true, '', '', NULL, ''),
(3, NOW(), NOW(), 3, true, '', '', NULL, ''),
(4, NOW(), NOW(), 4, true, '', '', NULL, '')
ON CONFLICT (user_id) DO UPDATE SET
verified = true,
updated_at = NOW();
-- User Subscriptions
INSERT INTO subscription_usersubscription (id, created_at, updated_at, user_id, tier, subscribed_at, expires_at, auto_renew, platform)
@@ -136,6 +149,7 @@ ON CONFLICT (id) DO UPDATE SET
-- Reset sequences
SELECT setval('auth_user_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM auth_user), false);
SELECT setval('user_userprofile_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM user_userprofile), false);
SELECT setval('subscription_usersubscription_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM subscription_usersubscription), false);
SELECT setval('residence_residence_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM residence_residence), false);
SELECT setval('task_contractor_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM task_contractor), false);