feat: video ingestion with file storage and upload UI #2

Merged
twerner merged 6 commits from feature/video-ingestion into dev 2026-05-19 11:37:31 +00:00
Collaborator

Summary

Implements video ingestion via file upload and URL import.

Changes

  • IFileStorageService abstraction + LocalFileStorageService (disk-backed)
  • UploadedVideoRepository — Update/Delete implemented
  • EF Core InitialCreate migration — all 5 entity tables
  • Blazor upload page (/upload) — file picker, URL import, progress
  • NavMenu — Upload link added
  • Config — FileStorage:BasePath
  • ADR 0001 — video ingestion architecture

Migration

Requires dotnet ef database update against PostgreSQL.

## Summary Implements video ingestion via file upload and URL import. ### Changes - **IFileStorageService** abstraction + LocalFileStorageService (disk-backed) - **UploadedVideoRepository** — Update/Delete implemented - **EF Core InitialCreate migration** — all 5 entity tables - **Blazor upload page** (/upload) — file picker, URL import, progress - **NavMenu** — Upload link added - **Config** — FileStorage:BasePath - **ADR 0001** — video ingestion architecture ### Migration Requires `dotnet ef database update` against PostgreSQL.
- IFileStorageService abstraction with LocalFileStorageService (disk-backed)
- UploadedVideoRepository Update/Delete implementations
- EF Core InitialCreate migration with fixed navigation configuration
- Blazor upload page (/upload) supporting file upload and URL import
- NavMenu extended with Upload link
- FileStorage:BasePath configuration in appsettings.json
- ADR 0001 documenting video ingestion architecture
- Updated concept.md, AGENTS.md, and todo.md
chore: add Microsoft.EntityFrameworkCore.Design package for migrations
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 23s
65c76a2054
Merge branch 'dev' into feature/video-ingestion
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 23s
685d1e60c9
fix: update model, safety checks, validation
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 27s
59c938bd01
feat: enhance security and database integrity fixes
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 33s
bc03062286
- Add missing index on RecipeExtractionResult.UploadedVideoId to initial migration
- Fix decimal precision consistency in Ingredients and InstructionSteps
- Implement comprehensive file validation service with content type and size limits
- Add URL validation attribute for SourceUrl to prevent SSRF attacks
- Configure file validation settings in appsettings.json
- Add path traversal protection and file signature validation
- Include proper dependency injection for validation service

Addresses critical security and performance issues identified in AI review

🤖 AI Code Review

Code Review: Video Ingestion Feature

🐛 Potential Bugs

🔴 Critical: Missing Navigation Properties
In AppDbContext.cs, the changes add .WithOne(e => e.Recipe) for Ingredient and InstructionStep relationships (lines 55-62), but the corresponding navigation properties (public Recipe Recipe { get; set; }) need to exist in those entity classes. Verify these are present.

🔴 Critical: Migration Index Filter Syntax
In AppDbContext.cs line 78-79, the filtered unique index uses:

.HasFilter("\"SourceUrl\" IS NOT NULL")

This should use the correct column name casing. If the column is named SourceUrl, the filter should be "\"SourceUrl\" IS NOT NULL" (double quotes escaped) or simply SourceUrl IS NOT NULL depending on PostgreSQL configuration.

🔒 Security Issues

🔴 Critical: SSRF Vulnerability in URL Validation
The ValidVideoUrlAttribute.cs blocks localhost but doesn't prevent Server-Side Request Forgery to internal resources:

  • Missing validation for private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • Missing DNS rebinding protection
  • Missing validation for 169.254.x.x (AWS metadata endpoint)

🔴 Important: Overly Restrictive Domain Whitelist
Lines 34-35 only allow youtube.com and vimeo.com, but then tries to allow generic domains with path validation. This creates inconsistent behavior. Either:

  • Allow all domains with path validation, OR
  • Keep a strict whitelist

Performance

🟡 Optional: Missing Index on UploadedAtUtc
Consider adding an index on UploadedAtUtc for common query patterns like "recent uploads".

🏗️ Code Quality

🟡 Important: Missing Newline at End of File
ValidVideoUrlAttribute.cs and AppDbContext.cs are missing trailing newlines.

🟡 Optional: Complex Validation Logic
The URL validation in ValidVideoUrlAttribute.cs could be extracted into smaller, testable methods for better maintainability.

Positives

Good: Proper EF Core Configuration

  • Decimal precision correctly applied with HasPrecision(5, 4) for confidence values
  • Appropriate string length constraints
  • Cascade delete configured correctly

Good: Database Index Strategy

  • Unique filtered index on SourceUrl allows NULL values while enforcing uniqueness
  • Foreign key indexes on relationship columns

💡 Recommendations

1. Enhance URL Validation Security

// Add private IP validation
private static bool IsPrivateIp(string host)
{
    if (IPAddress.TryParse(host, out var ip))
    {
        // Check private IP ranges
        return ip.ToString().StartsWith("10.") ||
               ip.ToString().StartsWith("192.168.") ||
               (ip.ToString().StartsWith("172.") && 
                ip.ToString().Split('.')[1].ToInt32() is >= 16 and <= 31);
    }
    return false;
}

2. Fix Migration Index Filter

entity.HasIndex(e => e.SourceUrl)
    .IsUnique()
    .HasFilter("SourceUrl IS NOT NULL");  // Remove escaped quotes

3. Add File Validation
Consider adding content-type validation and file size limits in IFileStorageService implementation.

4. Configuration Validation
Add validation for FileStorage:BasePath to ensure the directory exists and is writable at startup.


Generated by [poolside/laguna-xs.2:free] via AI Code Review Action

## 🤖 AI Code Review ## Code Review: Video Ingestion Feature ### 🐛 Potential Bugs 🔴 **Critical: Missing Navigation Properties** In `AppDbContext.cs`, the changes add `.WithOne(e => e.Recipe)` for `Ingredient` and `InstructionStep` relationships (lines 55-62), but the corresponding navigation properties (`public Recipe Recipe { get; set; }`) need to exist in those entity classes. Verify these are present. 🔴 **Critical: Migration Index Filter Syntax** In `AppDbContext.cs` line 78-79, the filtered unique index uses: ```csharp .HasFilter("\"SourceUrl\" IS NOT NULL") ``` This should use the correct column name casing. If the column is named `SourceUrl`, the filter should be `"\"SourceUrl\" IS NOT NULL"` (double quotes escaped) or simply `SourceUrl IS NOT NULL` depending on PostgreSQL configuration. ### 🔒 Security Issues 🔴 **Critical: SSRF Vulnerability in URL Validation** The `ValidVideoUrlAttribute.cs` blocks localhost but doesn't prevent Server-Side Request Forgery to internal resources: - Missing validation for private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) - Missing DNS rebinding protection - Missing validation for `169.254.x.x` (AWS metadata endpoint) 🔴 **Important: Overly Restrictive Domain Whitelist** Lines 34-35 only allow youtube.com and vimeo.com, but then tries to allow generic domains with path validation. This creates inconsistent behavior. Either: - Allow all domains with path validation, OR - Keep a strict whitelist ### ⚡ Performance 🟡 **Optional: Missing Index on UploadedAtUtc** Consider adding an index on `UploadedAtUtc` for common query patterns like "recent uploads". ### 🏗️ Code Quality 🟡 **Important: Missing Newline at End of File** `ValidVideoUrlAttribute.cs` and `AppDbContext.cs` are missing trailing newlines. 🟡 **Optional: Complex Validation Logic** The URL validation in `ValidVideoUrlAttribute.cs` could be extracted into smaller, testable methods for better maintainability. ### ✅ Positives ✅ **Good: Proper EF Core Configuration** - Decimal precision correctly applied with `HasPrecision(5, 4)` for confidence values - Appropriate string length constraints - Cascade delete configured correctly ✅ **Good: Database Index Strategy** - Unique filtered index on `SourceUrl` allows NULL values while enforcing uniqueness - Foreign key indexes on relationship columns ### 💡 Recommendations **1. Enhance URL Validation Security** ```csharp // Add private IP validation private static bool IsPrivateIp(string host) { if (IPAddress.TryParse(host, out var ip)) { // Check private IP ranges return ip.ToString().StartsWith("10.") || ip.ToString().StartsWith("192.168.") || (ip.ToString().StartsWith("172.") && ip.ToString().Split('.')[1].ToInt32() is >= 16 and <= 31); } return false; } ``` **2. Fix Migration Index Filter** ```csharp entity.HasIndex(e => e.SourceUrl) .IsUnique() .HasFilter("SourceUrl IS NOT NULL"); // Remove escaped quotes ``` **3. Add File Validation** Consider adding content-type validation and file size limits in `IFileStorageService` implementation. **4. Configuration Validation** Add validation for `FileStorage:BasePath` to ensure the directory exists and is writable at startup. --- *Generated by [poolside/laguna-xs.2:free] via AI Code Review Action*
twerner deleted branch feature/video-ingestion 2026-05-19 11:37:31 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
twerner/Video2Recipe!2
No description provided.