Dev#165
Conversation
- Add accounts app with User, Profile, Organization, and Tier models - Add shared utilities including database router and validators - Implement JWT authentication with tier-based permissions
- Add Patient, Provider, Encounter, and EncounterFile models - Implement multi-modal data tracking with signals - Add clinical data viewsets with tier-based access control
- Add research models for clinical data analysis - Implement sample data endpoints for research access - Configure research database routing
- Configure multiple database routing (accounts, clinical, research) - Update Django settings for new app structure
- Remove dashboard app in preparation for multi-app architecture - Clean up old models, views, serializers, and admin configs
…ecture 139 multi database architecture
…s for development, testing, and production
Dev multi db
Added LABS table w/ migrations
Update model fields, adjust data types
fix: Concept ID handling, specifying IDs
upgrade: Django version
Comment out the registration of the LabViewSet in private_urls.py.
158 bug fixes and UI changes
fix: ensure cookie deletion matches path used when setting cookies
…ers to use it; modify tests to reflect filter structure changes
…n login and refresh responses
… logging; adjust JWT token lifetimes for compliance
fix: refactor cohort name validation into a mixin and update serializ…
…e limiting and update environment configurations
…rt management actions; add models for audit trail and failed login attempts
… and user lookup; sanitize audit log inputs
… endpoints, models, and tests; enhance token management and cleanup processes
…file event types to audit constants
158 bug fixes and UI changes
feat: update audit trail category choices and add index for password …
- Implemented tests for the FilterOptions API, covering authentication, response structure, and demographic filters including NULL handling. - Added tests for the VisitSearch API, focusing on authentication, filtering, sorting, pagination, and demographic filtering. - Enhanced permission checks in tier_permissions.py to efficiently collect unique tier_ids from encounters. - Introduced a NULL_MARKER constant in shared/constants.py to represent NULL database values in API responses, aiding in filtering and user experience.
…alter tier_id field in encounter model
- Updated all instances in the codebase where 'tier_id' was used to 'tier_level' for consistency. - Modified the VisitOccurrence model to replace 'tier_id' with 'tier_level', including migration to remove the old field and add the new one. - Adjusted filtering logic in viewsets and permissions to accommodate the new 'tier_level' field. - Updated tests to reflect changes in the model and ensure proper functionality with the new tier access control.
…lIntegerField with updated help text
There was a problem hiding this comment.
Pull request overview
This PR represents a major architectural refactoring of the backend, migrating from a monolithic "dashboard" app to a multi-app modular architecture with separate databases for accounts, clinical, and research data.
Changes:
- Removed the entire
dashboardapp and replaced it with three specialized apps:accounts,clinical, andresearch - Implemented multi-database architecture with separate databases for different data domains
- Added comprehensive infrastructure including Makefile, CI/CD workflows, pre-commit hooks, and Postman environment
- Reorganized settings into environment-specific modules (dev, test, prd)
Reviewed changes
Copilot reviewed 171 out of 306 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| dashboard/* (all files) | Complete removal of monolithic dashboard app |
| clinical/* | New clinical app with models, APIs, storage backend, and comprehensive test coverage |
| accounts/* | New accounts app handling authentication, user management, profiles, and audit trails |
| backend/settings/* | Split monolithic settings.py into base.py, dev.py, test.py, prd.py for environment-specific configuration |
| backend/urls.py | Updated to use new modular URL structure with versioned API paths |
| Makefile, .github/workflows/ci.yml | Added development tooling and CI/CD pipeline |
| .env.* | Added environment configuration templates for different deployment scenarios |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Password hashers - Use secure hasher even in tests | ||
| # MD5 is cryptographically broken and should never be used | ||
| PASSWORD_HASHERS = [ | ||
| "django.contrib.auth.hashers.PBKDF2PasswordHasher", |
There was a problem hiding this comment.
Using secure password hashers in tests is good, but it significantly slows down test execution. For faster tests, consider using MD5PasswordHasher or PBKDF2PasswordHasher with reduced iterations. The comment on line 41 mentions 'MD5 is cryptographically broken' which is true for production but acceptable for tests where speed matters more than security. If security in tests is intentional, this is fine, but test performance will suffer.
| # Password hashers - Use secure hasher even in tests | |
| # MD5 is cryptographically broken and should never be used | |
| PASSWORD_HASHERS = [ | |
| "django.contrib.auth.hashers.PBKDF2PasswordHasher", | |
| # Password hashers - Use a fast, insecure hasher only in tests | |
| # MD5 is cryptographically broken and must never be used in production | |
| PASSWORD_HASHERS = [ | |
| "django.contrib.auth.hashers.MD5PasswordHasher", |
| return ip_str | ||
| except ValueError: | ||
| # Truncate to prevent log injection from malicious X-Forwarded-For headers | ||
| logger.warning("Invalid IP address format: %s", ip_str[:50] if ip_str else "") |
There was a problem hiding this comment.
Truncating potentially malicious input to 50 characters is good for preventing log injection, but the log message uses string formatting with %s which could still allow injection if the truncated string contains format specifiers. Consider using structured logging or further sanitizing the IP string to remove any format specifiers or control characters before logging.
| logger.warning("Invalid IP address format: %s", ip_str[:50] if ip_str else "") | |
| truncated_ip = (ip_str or "")[:50] | |
| # Escape percent signs so they cannot be interpreted as format specifiers | |
| safe_ip_for_logging = truncated_ip.replace("%", "%%") | |
| logger.warning("Invalid IP address format: %s", safe_ip_for_logging) |
| # Remove any path traversal attempts | ||
| component = component.replace("..", "").replace("/", "").replace("\\", "") |
There was a problem hiding this comment.
The path sanitization removes .., /, and \\ characters, but this approach has a weakness: after removal, remaining characters could form new dangerous patterns. For example, .... becomes .. after one pass. Consider using an iterative approach or regex substitution that continues until no more patterns are found, or use os.path.normpath() combined with validation that the result doesn't escape the base directory.
| # Remove any path traversal attempts | |
| component = component.replace("..", "").replace("/", "").replace("\\", "") | |
| # Disallow any path traversal or separator characters | |
| if ".." in component or "/" in component or "\\" in component: | |
| raise ValidationError("Path component contains invalid path traversal characters") |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
No description provided.