A login's storage is counted, and can have a quota
MediaAttachment.Size was stored and never summed: nobody, the administrator included, could tell what media took, and nothing bounded it. Counted.Media and MediaOfRoot sum what is kept (not trashed). A login sees what its personas' uploads and pictures take at /clientapi/user/storage (ViewStorage), with its quota when the server sets one; Media:QuotaBytesPerRoot (0, no quota, by default) refuses an upload or a picture over it with 422, whichever persona sends it; the statistics overview gains the media totals, the proxy cache and the trash (ViewMediaTotals). Tests: a login's storage counts what its personas keep and forgets what is trashed; two uploads from two personas of one login are refused together past the quota. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
5252b8f320
commit
dc63fa57b8
11 files changed
+134
-3
No files matched your search
@@ -328,6 +328,15 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
// }
|
||||
//}
|
||||
|
||||
// what the login's media take, every persona's, and its quota when the server sets one
|
||||
[HttpGet, Route("/clientapi/user/storage"), Authorize(Policy = Policies.IsUser)]
|
||||
public async Task<IActionResult> GetStorage([FromServices] Microsoft.Extensions.Options.IOptionsMonitor<Domain.Media.MediaOptions> media, CancellationToken token)
|
||||
{
|
||||
var (bytes, files) = await Domain.Privacy.Counted.MediaOfRoot(User.GetUserId(), token);
|
||||
var quota = media.CurrentValue.QuotaBytesPerRoot;
|
||||
return Ok(new PrivaPub.ClientModels.User.ViewStorage { MediaBytes = bytes, MediaFiles = files, QuotaBytes = quota > 0 ? quota : null });
|
||||
}
|
||||
|
||||
[HttpGet, Route("/clientapi/user/settings"), Authorize(Policy = Policies.IsUser)]
|
||||
public async Task<IActionResult> GetUserSettings()
|
||||
{
|
||||
|
||||
@@ -32,8 +32,16 @@ namespace PrivaPub.Controllers.ClientToServer
|
||||
Ok(await _queries.Crawler(_options.CurrentValue.Crawler.Enabled, _options.CurrentValue.Crawler.RevisitDays, token));
|
||||
|
||||
[HttpGet, Route("/clientapi/admin/statistics/overview")]
|
||||
public async Task<IActionResult> Overview([FromQuery] int days = 30, CancellationToken token = default) =>
|
||||
Ok(await _queries.Overview(days, token));
|
||||
public async Task<IActionResult> Overview([FromServices] Domain.Media.IMediaService media, [FromQuery] int days = 30, CancellationToken token = default)
|
||||
{
|
||||
var overview = await _queries.Overview(days, token);
|
||||
overview.Media.ProxyCacheBytes = Bytes(media.ProxyRoot);
|
||||
overview.Media.TrashBytes = Bytes(media.TrashRoot);
|
||||
return Ok(overview);
|
||||
}
|
||||
|
||||
static long Bytes(string root) =>
|
||||
Directory.Exists(root) ? new DirectoryInfo(root).EnumerateFiles("*", SearchOption.AllDirectories).Sum(f => f.Length) : 0;
|
||||
|
||||
[HttpGet, Route("/clientapi/admin/statistics/hosts")]
|
||||
public async Task<IActionResult> Hosts([FromQuery] int days = 30, [FromQuery] string sort = default, [FromQuery] string software = default,
|
||||
|
||||
Reference in new issue
Block a user