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
@@ -1,3 +1,4 @@
|
||||
using MongoDB.Driver;
|
||||
using MongoDB.Entities;
|
||||
|
||||
using PrivaPub.Federation.Actors;
|
||||
@@ -64,6 +65,24 @@ namespace PrivaPub.Domain.Privacy
|
||||
return distinct.Count == 0 ? 0 : await DB.Default.CountAsync<Avatar>(a => distinct.Contains(a.ID) && !a.DeletionAt.HasValue, token);
|
||||
}
|
||||
|
||||
// the media kept (not trashed) that which holds: their bytes and how many
|
||||
public static async Task<(long Bytes, long Files)> Media(Expression<Func<Models.Media.MediaAttachment, bool>> which, CancellationToken token)
|
||||
{
|
||||
var totals = await DB.Default.Fluent<Models.Media.MediaAttachment>()
|
||||
.Match(m => m.TrashedAt == null)
|
||||
.Match(which)
|
||||
.Group(m => true, g => new { Bytes = g.Sum(m => m.Size), Files = g.LongCount() })
|
||||
.FirstOrDefaultAsync(token);
|
||||
return totals == default ? (0, 0) : (totals.Bytes, totals.Files);
|
||||
}
|
||||
|
||||
// a login's media: every persona's uploads and pictures
|
||||
public static async Task<(long Bytes, long Files)> MediaOfRoot(string rootId, CancellationToken token)
|
||||
{
|
||||
var personas = (await DB.Default.Find<Models.User.RootToAvatar>().Match(r => r.RootId == rootId).ExecuteAsync(token)).Select(r => r.AvatarId).ToList();
|
||||
return await Media(m => personas.Contains(m.OwnerAvatarId), token);
|
||||
}
|
||||
|
||||
public static async Task<long> LocalPosts(CancellationToken token)
|
||||
{
|
||||
var barred = await BarredPersonas(token);
|
||||
|
||||
Reference in new issue
Block a user