• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

karanshukla / openresto / 28339180196

28 Jun 2026 11:09PM UTC coverage: 91.096%. First build
28339180196

push

github

karanshukla
Revert "add cory package"

This reverts commit fe1f5b642.

3607 of 4344 branches covered (83.03%)

Branch coverage included in aggregate %.

94 of 162 new or added lines in 10 files covered. (58.02%)

9570 of 10121 relevant lines covered (94.56%)

65.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/OpenRestoApi/Controllers/MediaController.cs
1
using Microsoft.AspNetCore.Authorization;
2
using Microsoft.AspNetCore.Mvc;
3
using Microsoft.AspNetCore.RateLimiting;
4
using Microsoft.EntityFrameworkCore;
5
using OpenRestoApi.Core.Domain;
6
using OpenRestoApi.Infrastructure.Persistence;
7

8
namespace OpenRestoApi.Controllers;
9

10
[ApiController]
11
[Route("api/media")]
12
[Authorize]
13
[EnableRateLimiting("public")]
NEW
14
public class MediaController(AppDbContext db, IWebHostEnvironment env) : ControllerBase
×
15
{
NEW
16
    private readonly AppDbContext _db = db;
×
NEW
17
    private readonly string _mediaDir = Path.Combine(env.ContentRootPath, "wwwroot", "media");
×
18

19
    private static readonly string[] _allowedTypes = ["image/jpeg", "image/png", "image/webp"];
×
20
    private const long _maxHeroBytes = 5 * 1024 * 1024;
21
    private const long _maxLocationBytes = 2 * 1024 * 1024;
22

23
    [HttpPost("hero")]
24
    [RequestSizeLimit(5 * 1024 * 1024 + 8192)]
25
    public async Task<IActionResult> UploadHero(IFormFile file)
26
    {
27
        if (!_allowedTypes.Contains(file.ContentType))
×
28
        {
29
            return BadRequest(new { message = "Only JPEG, PNG, and WebP images are accepted." });
×
30
        }
31

32
        if (file.Length > _maxHeroBytes)
×
33
        {
34
            return BadRequest(new { message = "Hero image must be under 5 MB." });
×
35
        }
36

NEW
37
        EnsureMediaDir();
×
38

NEW
39
        foreach (string old in Directory.GetFiles(_mediaDir, "hero.*"))
×
40
        {
NEW
41
            System.IO.File.Delete(old);
×
42
        }
43

NEW
44
        string filename = $"hero.{GetExtension(file.ContentType)}";
×
NEW
45
        await using (FileStream stream = System.IO.File.Create(Path.Combine(_mediaDir, filename)))
×
46
        {
NEW
47
            await file.CopyToAsync(stream);
×
48
        }
49

NEW
50
        string url = $"/media/{filename}?v={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
×
51

NEW
52
        BrandSettings? brand = await _db.Set<BrandSettings>().FirstOrDefaultAsync();
×
NEW
53
        if (brand == null)
×
54
        {
NEW
55
            brand = new BrandSettings();
×
NEW
56
            _db.Set<BrandSettings>().Add(brand);
×
57
        }
NEW
58
        brand.HeaderImageUrl = url;
×
NEW
59
        await _db.SaveChangesAsync();
×
60

61
        return Ok(new { url });
×
62
    }
×
63

64
    [HttpDelete("hero")]
65
    public async Task<IActionResult> DeleteHero()
66
    {
NEW
67
        BrandSettings? brand = await _db.Set<BrandSettings>().FirstOrDefaultAsync();
×
NEW
68
        if (brand?.HeaderImageUrl != null)
×
69
        {
NEW
70
            DeleteFile(brand.HeaderImageUrl);
×
NEW
71
            brand.HeaderImageUrl = null;
×
NEW
72
            await _db.SaveChangesAsync();
×
73
        }
74
        return NoContent();
×
75
    }
×
76

77
    [HttpPost("location/{id:int}")]
78
    [RequestSizeLimit(2 * 1024 * 1024 + 8192)]
79
    public async Task<IActionResult> UploadLocation(int id, IFormFile file)
80
    {
81
        if (!_allowedTypes.Contains(file.ContentType))
×
82
        {
83
            return BadRequest(new { message = "Only JPEG, PNG, and WebP images are accepted." });
×
84
        }
85

86
        if (file.Length > _maxLocationBytes)
×
87
        {
88
            return BadRequest(new { message = "Location image must be under 2 MB." });
×
89
        }
90

NEW
91
        Core.Domain.Restaurant? restaurant = await _db.Restaurants.FindAsync(id);
×
NEW
92
        if (restaurant == null)
×
93
        {
NEW
94
            return NotFound();
×
95
        }
96

NEW
97
        EnsureMediaDir();
×
98

NEW
99
        foreach (string old in Directory.GetFiles(_mediaDir, $"location-{id}.*"))
×
100
        {
NEW
101
            System.IO.File.Delete(old);
×
102
        }
103

NEW
104
        string filename = $"location-{id}.{GetExtension(file.ContentType)}";
×
NEW
105
        await using (FileStream stream = System.IO.File.Create(Path.Combine(_mediaDir, filename)))
×
106
        {
NEW
107
            await file.CopyToAsync(stream);
×
108
        }
109

NEW
110
        string url = $"/media/{filename}?v={DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
×
NEW
111
        restaurant.ImageUrl = url;
×
NEW
112
        await _db.SaveChangesAsync();
×
113

114
        return Ok(new { url });
×
115
    }
×
116

117
    [HttpDelete("location/{id:int}")]
118
    public async Task<IActionResult> DeleteLocation(int id)
119
    {
NEW
120
        Core.Domain.Restaurant? restaurant = await _db.Restaurants.FindAsync(id);
×
NEW
121
        if (restaurant == null)
×
122
        {
NEW
123
            return NotFound();
×
124
        }
125

NEW
126
        if (restaurant.ImageUrl != null)
×
127
        {
NEW
128
            DeleteFile(restaurant.ImageUrl);
×
NEW
129
            restaurant.ImageUrl = null;
×
NEW
130
            await _db.SaveChangesAsync();
×
131
        }
132
        return NoContent();
×
133
    }
×
134

NEW
135
    private void EnsureMediaDir() => Directory.CreateDirectory(_mediaDir);
×
136

137
    private void DeleteFile(string url)
138
    {
NEW
139
        string pathOnly = url.Contains('?') ? url[..url.IndexOf('?')] : url;
×
NEW
140
        string path = Path.Combine(_mediaDir, Path.GetFileName(pathOnly));
×
NEW
141
        if (System.IO.File.Exists(path))
×
142
        {
NEW
143
            System.IO.File.Delete(path);
×
144
        }
NEW
145
    }
×
146

NEW
147
    private static string GetExtension(string contentType) => contentType switch
×
NEW
148
    {
×
NEW
149
        "image/jpeg" => "jpg",
×
NEW
150
        "image/png" => "png",
×
NEW
151
        "image/webp" => "webp",
×
NEW
152
        _ => "bin"
×
NEW
153
    };
×
154
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc