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

  1. DES Encryption:
    - Key: &%#@?,:* (8 bytes)
    - IV: Hardcoded 8-byte array
    - Used for general text encryption

  2. AES Encryption:
    - 256-bit key size
    - PBKDF1 (PasswordDeriveBytes)
    - SHA1 hash algorithm
    - 2 iterations
    - Used for connection strings and secure data

  3. 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 access
  • MediaRepository - Media-specific operations
  • ApplicationRepository - Configuration operations

2. Provider Pattern

  • MyAuthorizationServerProvider - OAuth logic
  • RefreshTokenProvider - Token refresh
  • UploadMultipartFormProvider - File upload handling

3. Helper/Utility Pattern

  • iTextSharpHelper - PDF operations
  • SecurityHelper - Encryption operations
  • UtilityMethod - Data conversion

4. Action Filter Pattern

  • MimeMultipart - MIME type validation
  • Authorize - Authentication enforcement

5. Factory Pattern

  • CreateDbCommand() - SQL command creation
  • CreateDbConnection() - 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

  1. iTextSharp - Last updated 2019, no longer maintained
  2. OWIN - Legacy technology, replaced by ASP.NET Core
  3. .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

  1. Main PsyterAPI
    - Provides ApplicationToken
    - Validates user authentication

  2. SQL Server Database
    - Shared database with main API
    - Stored procedures for data operations

  3. File System
    - Physical media storage
    - Configured via database settings

  4. Mobile/Web Clients
    - Direct file uploads
    - Bearer token authentication

Database Dependencies

  • User_Authenticate_MediaAPI - Authentication
  • AppConfig_GetAppConfigSettingsByGroupId - Configuration
  • HW_SaveHomeWorkFilesDetail_FromMediaServer - Homework files
  • HW_DeleteHomeWorkFile - File deletion
  • SP_GetUserAgreementData - Agreement template
  • SP_UpdatetUserAgreementFilePath - Agreement path update

Recommendations Summary

Critical Priority

  1. Upgrade to ASP.NET Core for better performance and security
  2. Replace iTextSharp with maintained alternative (QuestPDF, etc.)
  3. Enable HTTPS-only authentication
  4. Implement comprehensive logging
  5. Add malware scanning for uploaded files

High Priority

  1. Implement dependency injection
  2. Add unit and integration tests
  3. Extract hardcoded values to configuration
  4. Implement request rate limiting
  5. Add background job processing for PDF generation

Medium Priority

  1. Implement caching strategy
  2. Add CDN for media delivery
  3. Implement chunked file uploads
  4. Add image optimization
  5. 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