Media Repository - Structure Analysis¶
Repository: PsyterMediaUploadAPI
Type: ASP.NET Web API (.NET Framework 4.7.2)
Purpose: Dedicated media upload/management service for Psyter platform
Audit Date: November 10, 2025
Executive Summary¶
The Media repository is a specialized ASP.NET Web API service designed to handle file uploads, PDF generation, and media management for the Psyter telemedicine platform. It serves as a standalone microservice focusing exclusively on media operations with OAuth 2.0 authentication.
Key Characteristics:
- Single-purpose API (media handling only)
- OAuth 2.0 bearer token authentication
- iTextSharp PDF generation for agreements
- File validation and security
- Direct SQL Server integration
- CORS-enabled for cross-origin requests
Architecture Overview¶
1. Technology Stack¶
| Component | Technology | Version |
|---|---|---|
| Framework | ASP.NET Web API | .NET 4.7.2 |
| Language | C# | 6.0 |
| Authentication | OWIN OAuth 2.0 | 3.1.0 |
| PDF Generation | iTextSharp | 5.5.13.4 |
| Database | SQL Server | - |
| Mapping | AutoMapper | 7.0.1 |
| JSON | Newtonsoft.Json | 11.0.2 |
| Logging | log4net | 2.0.8 |
2. Project Structure¶
PsyterMediaUploadAPI/
├── App_Start/
│ ├── RouteConfig.cs # MVC routing configuration
│ ├── Startup.cs # OWIN startup configuration
│ └── WebApiConfig.cs # Web API routing
├── Controllers/
│ ├── BaseController.cs # Base controller with response helpers
│ └── MediaController.cs # Main media operations controller
├── Helper/
│ ├── iTextSharpHelper.cs # PDF generation utilities
│ └── SecurityHelper.cs # Encryption/decryption utilities
├── Models/
│ ├── ApplicationSettingResponse.cs
│ ├── BaseResponse.cs # Standard API response model
│ ├── CommonObject.cs
│ ├── Enums.cs # All enumerations
│ ├── FileObject.cs # File metadata model
│ └── MediaRequest.cs # Request models
├── Providers/
│ ├── AuthorizeAttribute.cs # Custom authorization
│ ├── MyAuthorizationServerProvider.cs # OAuth provider
│ └── RefreshTokenProvider.cs
├── Repository/
│ ├── ApplicationRepository.cs # App configuration queries
│ ├── BaseRepository.cs # Database connection/utilities
│ ├── DbConstantDesigner.cs # Stored procedure constants
│ ├── HelperClass.cs
│ ├── MediaRepository.cs # Media data operations
│ └── UtilityMethod.cs
├── Content/
│ ├── html_templates/ # Agreement PDF templates
│ │ ├── agreement_template.html # English template
│ │ ├── agreement_template_ar.html # Arabic template
│ │ ├── footer-logo.png
│ │ └── logo.png
│ └── fonts/ # PDF fonts (Arabic/English)
├── Media/ # Upload directory (runtime)
├── Web.config # Configuration
└── Global.asax.cs # Application startup
Component Architecture¶
1. Controllers Layer¶
MediaController¶
Primary Responsibilities:
- File upload handling with multipart form data
- File validation (type, size, extension, MIME type)
- Directory management for organized storage
- PDF generation for agreements
- File deletion operations
- Media path configuration retrieval
Key Endpoints:
POST /Media/UploadMedia
POST /Media/DeleteMediaFile
POST /Media/RegenrateAgreement
Upload Categories Supported:
- ProfileImage
- EducationHistory
- SCRC (Saudi Commission for Health Specialties)
- ShortBio (video)
- PaymentAttachment
- HomeWork (care provider assignments)
- HomeWorkSubmission (client submissions)
- ArticleImages
- AgreementAcceptance (signature + PDF)
- BookingInvoices
- NationalID
BaseController¶
Purpose: Common response formatting and error handling
Methods:
- GetSuccessResponse() - Success with data/reason
- GetErrorResponse() - Exception handling
- GetInvalidResponse() - Validation failures
- GetResponse() - Generic response wrapper
2. Authentication & Authorization¶
OWIN OAuth 2.0 Implementation¶
Flow:
1. Client requests token from /authenticate endpoint
2. Provides ApplicationToken parameter
3. Server validates token via User_Authenticate_MediaAPI stored procedure
4. Returns bearer token on success
5. Subsequent requests include bearer token in Authorization header
Key Classes:
- MyAuthorizationServerProvider - Token generation/validation
- RefreshTokenProvider - Token refresh logic
- AuthorizeAttribute - Endpoint protection
Security Configuration:
AllowInsecureHttp = true // ⚠️ SECURITY RISK
AccessTokenExpireTimeSpan = 1 day
TokenEndpointPath = "/authenticate"
3. File Upload Processing¶
Upload Flow¶
1. Request arrives at UploadMedia endpoint
2. Extract parameters (UserId, UserType, UploadCategory, HomeWorkId)
3. Validate request parameters
4. Validate file (MIME type, size, extension, content)
5. Determine storage path based on category
6. Create directory if needed
7. Save file with GUID filename
8. Special handling for AgreementAcceptance (generate PDF)
9. Save metadata to database (HomeWork/HomeWorkSubmission only)
10. Return file details in response
File Validation Layers¶
1. MIME Type Validation
- Checks Content-Type header
- Uses MimeMultipart attribute filter
2. Extension Validation
- Whitelist per category
- Case-insensitive comparison
3. Size Validation
- Max: 100 MB (configurable via Web.config)
- Applied to each file individually
4. Content Validation
- Reads first 4 bytes of Base64 content
- Validates actual file type matches extension
- Prevents file type spoofing
Example Extension Whitelist:
ProfileImage: .png, .jpg, .jpeg
EducationHistory: .doc, .docx, .xlsx, .pdf, .jpg, .jpeg, .png
ShortBio: .mp4
HomeWork: .doc, .docx, .xlsx, .pdf, .jpg, .jpeg, .png, .txt
SCRC: .png, .jpg, .jpeg, .pdf
File Naming Convention¶
Pattern: {Category}_{GUID}.{extension}
Example: ProfileImage_a3f2b1c4-5d6e-7f8g-9h0i-1j2k3l4m5n6o.png
Storage Structure¶
/Media/
├── CareProvider/
│ └── User_{UserId}/
│ ├── ProfileImage/
│ ├── EducationHistory/
│ ├── SCRC/
│ ├── ShortBio/
│ ├── HomeWork/
│ │ └── HomeWork_{HomeWorkId}/
│ ├── AgreementAcceptance/
│ └── NationalID/
├── Client/
│ └── User_{UserId}/
│ ├── ProfileImage/
│ ├── PaymentAttachment/
│ ├── HomeWorkSubmission/
│ │ └── HomeWork_{HomeWorkId}/
│ └── NationalID/
├── ActicleImages/
└── BookingInvoices/
4. PDF Generation (iTextSharp)¶
Agreement PDF Creation Flow¶
Purpose: Generate bilingual (English/Arabic) agreement PDFs with user signatures
Process:
1. Retrieve user agreement data from database
2. Load HTML template (English/Arabic)
3. Replace placeholders with user data:
- {USER_NAME} - User’s full name
- {AGREEMENT_CONTENT} - Agreement text (from DB)
- {IMG_SIGNATURE} - Signature image URL
- {CURRENT_DATE} - Current date (UTC+3)
- {BASE_URL} - Application base URL
4. Generate PDF for each language
5. Combine both PDFs into single document
6. Save combined PDF
7. Update database with file path
Templates:
- agreement_template.html - English version
- agreement_template_ar.html - Arabic version
Custom Footer:
- Website URL (left)
- Logo (center)
- Page number (right)
- Teal background (#00A9AD)
Font Support:
- ProximaNovaA-Regular.ttf (English)
- Alexandria-Regular.ttf (Arabic)
- NotoSansArabic-Regular.ttf (Arabic fallback)
Direction Handling:
- Detects Arabic characters using regex: [\u0600-\u06ff]|[\u0750-\u077f]|[\ufb50-\ufc3f]|[\ufe70-\ufefc]
- Applies RTL direction for Arabic names
5. Repository Layer¶
BaseRepository¶
Responsibilities:
- SQL connection management
- Connection string decryption
- Command creation and disposal
- Data mapping utilities
- Serialization/deserialization
Key Features:
- Encrypted connection strings (custom encryption)
- Configurable command timeout (default: 600 seconds)
- Generic DataTable-to-Object mapping
- DataReader-to-Object mapping
- Deep copy utilities
MediaRepository¶
Operations:
- GetAppConfigSettingsByGroupId() - Retrieve media path configuration
- SaveHomeWorkImages() - Persist homework file metadata
- DeleteMediaFromDB() - Remove file metadata
- GetUserAgreementDetails() - Fetch agreement template data
- UpdateAgreementFilePath() - Update agreement PDF path
Stored Procedures:
User_Authenticate_MediaAPI
AppConfig_GetAppConfigSettingsByGroupId
HW_SaveHomeWorkFilesDetail_FromMediaServer
HW_DeleteHomeWorkFile
SP_GetUserAgreementData
SP_UpdatetUserAgreementFilePath
6. Security Components¶
SecurityHelper & Cryptography Classes¶
Encryption Methods:
1. Password Hashing:
- Triple MD5 hash
- Base64 encoded
- Used for password storage
-
DES Encryption:
- Key:&%#@?,:*(8 bytes)
- IV: Hardcoded 8-byte array
- Used for general text encryption -
AES Encryption:
- 256-bit key size
- PBKDF1 (PasswordDeriveBytes)
- SHA1 hash algorithm
- 2 iterations
- Used for connection strings and secure data -
SHA-256/SHA-512:
- For checksums and integrity
- Hex string output
Connection String Security:
- Encrypted in Web.config
- Decrypted at runtime
- Components encrypted: Data Source, Initial Catalog, User Id, Password
Data Flow Diagrams¶
1. File Upload Flow¶
Mobile/Web Client
│
├─ Authenticate via main API
│ └─ Receive ApplicationToken
│
├─ Request bearer token from /authenticate
│ ├─ Send ApplicationToken
│ └─ Receive bearer token
│
└─ Upload file to /Media/UploadMedia
├─ Headers: Authorization: Bearer {token}
├─ Form Data:
│ ├─ UserId
│ ├─ UserType
│ ├─ UploadCategory
│ ├─ HomeWorkId (optional)
│ └─ File(s)
│
├─ MediaController validates request
│ ├─ Check parameters
│ ├─ Validate file size
│ ├─ Validate file type
│ ├─ Validate MIME type
│ └─ Validate content signature
│
├─ Determine storage path
│ └─ Create directories
│
├─ Save file with GUID name
│
├─ Special processing:
│ ├─ AgreementAcceptance → Generate PDF
│ └─ HomeWork/Submission → Save to DB
│
└─ Return file details
├─ FileName
├─ FilePath (relative)
└─ FileType
2. Agreement PDF Generation Flow¶
Upload Signature Image
│
├─ Save signature file
│
└─ Generate Agreement PDF
│
├─ Retrieve user data from DB
│ ├─ Agreement HTML content
│ ├─ User details
│ └─ Configuration
│
├─ Generate English PDF
│ ├─ Load template HTML
│ ├─ Replace placeholders
│ ├─ Convert HTML to PDF
│ └─ Apply custom footer
│
├─ Generate Arabic PDF
│ ├─ Load Arabic template
│ ├─ Replace placeholders
│ ├─ Apply RTL if needed
│ ├─ Convert HTML to PDF
│ └─ Apply custom footer
│
├─ Combine PDFs
│ ├─ Create new document
│ ├─ Add Arabic pages first
│ └─ Add English pages
│
├─ Save combined PDF
│
├─ Update database
│ ├─ AgreementPDFFilePath
│ └─ SignatureFilePath
│
└─ Return file details
Configuration Management¶
Web.config Settings¶
AppSettings¶
MaxFileSize: 104857600 (100 MB)
commandTimeout: 600 seconds
Connection String¶
Encrypted format with custom encryption:
- Data Source (encrypted)
- Initial Catalog (encrypted)
- User Id (encrypted)
- Password (encrypted)
- Persist Security Info: True
Two environments:
- Dev connection (active)
- Live connection (commented)
Request Size Limits¶
maxRequestLength: 104857600 (100 MB) - ASP.NET
maxAllowedContentLength: 104857600 - IIS
CORS¶
app.UseCors(CorsOptions.AllowAll)
Machine Key¶
- Hardcoded in Web.config
- Decryption: AES
- Validation: HMACSHA256
- ⚠️ Should be different per environment
Design Patterns Used¶
1. Repository Pattern¶
BaseRepository- Common data accessMediaRepository- Media-specific operationsApplicationRepository- Configuration operations
2. Provider Pattern¶
MyAuthorizationServerProvider- OAuth logicRefreshTokenProvider- Token refreshUploadMultipartFormProvider- File upload handling
3. Helper/Utility Pattern¶
iTextSharpHelper- PDF operationsSecurityHelper- Encryption operationsUtilityMethod- Data conversion
4. Action Filter Pattern¶
MimeMultipart- MIME type validationAuthorize- Authentication enforcement
5. Factory Pattern¶
CreateDbCommand()- SQL command creationCreateDbConnection()- Connection instantiation
Dependencies Analysis¶
NuGet Packages¶
| Package | Version | Purpose | Risk Level |
|---|---|---|---|
| AutoMapper | 7.0.1 | Object mapping | Low |
| BouncyCastle | 1.8.9 | Cryptography | Medium (outdated) |
| BouncyCastle.Cryptography | 2.4.0 | Cryptography | Low |
| iTextSharp | 5.5.13.4 | PDF generation | High (unmaintained) |
| itextsharp.xmlworker | 5.5.13.4 | HTML to PDF | High (unmaintained) |
| log4net | 2.0.8 | Logging | Low |
| Microsoft.Owin | 3.1.0 | OWIN middleware | Medium (old) |
| Microsoft.Owin.Security.OAuth | 3.1.0 | OAuth 2.0 | Medium (old) |
| Newtonsoft.Json | 11.0.2 | JSON serialization | Medium (outdated) |
Critical Dependencies¶
- iTextSharp - Last updated 2019, no longer maintained
- OWIN - Legacy technology, replaced by ASP.NET Core
- .NET Framework 4.7.2 - End of support approaching
API Endpoints¶
Authentication¶
POST /authenticate¶
Purpose: Obtain bearer token for API access
Request Body:
grant_type: client_credentials
ApplicationToken: {token from main API}
Response:
{
"access_token": "bearer_token_here",
"token_type": "bearer",
"expires_in": 86400
}
Media Operations¶
POST /Media/UploadMedia¶
Purpose: Upload media files
Authorization: Bearer token required
Form Data:
- UserId (required) - User identifier
- UserType (required) - 0=Client, 1=CareProvider, 2=Admin
- UploadCategory (required) - MediaCategory enum value
- HomeWorkId (optional) - Required for HomeWork/HomeWorkSubmission
- UserFullName (optional) - Required for AgreementAcceptance
- Culture (optional) - Language for agreement (en-US/ar-SA)
- File(s) (required) - One or more files
Response:
{
"Data": [
{
"FileName": "ProfileImage_guid.png",
"FilePath": "/Media/CareProvider/User_123/ProfileImage/ProfileImage_guid.png",
"FileType": ".png"
}
],
"Status": 1,
"Reason": 1,
"ReasonText": "Success"
}
POST /Media/DeleteMediaFile¶
Purpose: Delete uploaded media file
Authorization: Bearer token required
Request Body:
{
"UserId": 123,
"MediaId": 456,
"MediaCategory": 6
}
Response:
{
"Data": null,
"Status": 1,
"Reason": 1,
"ReasonText": "Success"
}
POST /Media/RegenrateAgreement¶
Purpose: Regenerate agreement PDF for care provider
Authorization: Bearer token required
Request Body:
{
"UserLoginInfoId": 123,
"FullName": "Dr. John Doe",
"SignatureMediaPath": "/Media/CareProvider/User_123/AgreementAcceptance/signature.png"
}
Response:
{
"Data": {
"FileName": "AgreementAcceptance_guid.pdf",
"FilePath": "/Media/CareProvider/User_123/AgreementAcceptance/AgreementAcceptance_guid.pdf",
"FileType": ".pdf"
},
"Status": 1,
"Reason": 1
}
Error Handling Strategy¶
Error Response Format¶
{
"Data": null,
"Status": 0,
"Reason": 3,
"ReasonText": "Invalid Parameters"
}
Error Reasons Enum¶
NONE = -1
ERROR = 0
SUCCESS = 1
EMPTY_PARAMETERS = 2
INVALID_PARAMETERS = 3
SQL_SERVER_EXCEPTION = 4
NOT_FOUND = 5
CANT_DELETE = 6
PHYSICAL_DIRECTORY_NOT_FOUND = 7
INVALID_MIME_TYPE = 8
CANT_UPLOAD_MORE_THAN_ONE_FILE = 9
CANT_UPLOAD_MORE_THAN_3_FILES = 10
FILE_SIZE_IS_LARGER_THAN_ALLOWED = 11
FILE_EXTENSION_NOT_ALLOWED = 12
FILE_MIMETYPE_NOT_ALLOWED = 13
Exception Handling Approach¶
- Try-catch in all controller methods
- SQL exceptions identified and categorized
- Generic exceptions return
E_ResponseReason.ERROR - No detailed error messages exposed to client
- ⚠️ No logging implementation visible
Deployment Configuration¶
Azure Pipelines¶
Trigger: Master branch commits
Build Steps:
1. NuGet package restore
2. MSBuild with deployment package creation
3. Publish build artifacts
4. Copy files to deployment directory:
- Target: D:\ROOT\Development\Psyter\Master\MediaAPIs
Agent Pool: DevWebServerAgentPool
Security Considerations¶
Current Security Measures¶
✅ OAuth 2.0 bearer token authentication
✅ File type validation (extension + content)
✅ File size limits
✅ Encrypted connection strings
✅ MIME type validation
✅ Base64 content signature verification
Security Concerns¶
⚠️ AllowInsecureHttp = true - Allows HTTP for OAuth
⚠️ Hardcoded encryption keys in code
⚠️ Machine key in Web.config
⚠️ No request rate limiting
⚠️ No file scanning for malware
⚠️ Direct file system access
⚠️ Custom errors mode set to “Off”
⚠️ No audit logging for file operations
⚠️ Persist Security Info = True in connection string
Performance Considerations¶
Optimization Features¶
- Async/await for I/O operations
- Direct file stream writing
- DataReader for database queries
- Connection pooling (SQL Server default)
Performance Concerns¶
- No caching implementation
- No CDN integration
- Synchronous file writes in some paths
- No image optimization/compression
- Large file uploads block thread
- No chunked upload support
- PDF generation is CPU-intensive
- No background job processing
Maintainability Assessment¶
Strengths¶
✅ Clear separation of concerns
✅ Consistent naming conventions
✅ Reusable base classes
✅ Centralized configuration
✅ Stored procedure abstraction
Weaknesses¶
❌ No unit tests
❌ No integration tests
❌ Limited inline documentation
❌ Hardcoded values (file paths, magic numbers)
❌ No dependency injection
❌ Tight coupling to SQL Server
❌ No interface abstractions
❌ Commented-out code in multiple places
Integration Points¶
External Systems¶
-
Main PsyterAPI
- Provides ApplicationToken
- Validates user authentication -
SQL Server Database
- Shared database with main API
- Stored procedures for data operations -
File System
- Physical media storage
- Configured via database settings -
Mobile/Web Clients
- Direct file uploads
- Bearer token authentication
Database Dependencies¶
User_Authenticate_MediaAPI- AuthenticationAppConfig_GetAppConfigSettingsByGroupId- ConfigurationHW_SaveHomeWorkFilesDetail_FromMediaServer- Homework filesHW_DeleteHomeWorkFile- File deletionSP_GetUserAgreementData- Agreement templateSP_UpdatetUserAgreementFilePath- Agreement path update
Recommendations Summary¶
Critical Priority¶
- Upgrade to ASP.NET Core for better performance and security
- Replace iTextSharp with maintained alternative (QuestPDF, etc.)
- Enable HTTPS-only authentication
- Implement comprehensive logging
- Add malware scanning for uploaded files
High Priority¶
- Implement dependency injection
- Add unit and integration tests
- Extract hardcoded values to configuration
- Implement request rate limiting
- Add background job processing for PDF generation
Medium Priority¶
- Implement caching strategy
- Add CDN for media delivery
- Implement chunked file uploads
- Add image optimization
- Create API documentation (Swagger)
Conclusion¶
The Media repository serves as a dedicated microservice for file management in the Psyter platform. While functional, it shows signs of technical debt with legacy dependencies and security concerns. The code is well-structured but lacks modern best practices like dependency injection, comprehensive testing, and proper logging.
Overall Assessment: NEEDS MODERNIZATION
- Core functionality: ✅ Working
- Security posture: ⚠️ Needs improvement
- Maintainability: ⚠️ Moderate
- Performance: ⚠️ Adequate but not optimized
- Future-readiness: ❌ Legacy technology stack