init 1.0.0

This commit is contained in:
2026-06-19 00:42:00 +02:00
commit 5ca960746b
67 changed files with 3261 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
using LiteDB;
using LehrerApp.Sync.Models;
namespace LehrerApp.Api;
public class SnapshotStore(string dataPath) : IDisposable
{
private readonly LiteDatabase _db =
new(Path.Combine(dataPath, "snapshots.db"));
private readonly Timer _cleanup;
public SnapshotStore(string dataPath, bool unused = false) : this(dataPath)
{
Directory.CreateDirectory(dataPath);
_cleanup = new(_ => Clean(), null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
}
private ILiteCollection<SnapshotEntry> Col => _db.GetCollection<SnapshotEntry>("snap");
public SnapshotUploadResponse Store(string userId, SnapshotUploadRequest req)
{
Col.DeleteMany(e => e.UserId == userId);
var code = NewCode();
var entry = new SnapshotEntry { Code = code, UserId = userId,
EncryptedPayload = req.EncryptedPayload,
EncryptedSyncKey = req.EncryptedSyncKey,
SourceDeviceType = req.DeviceType,
CreatedAt = DateTime.UtcNow, ExpiresAt = DateTime.UtcNow.AddHours(24) };
Col.Insert(entry);
return new() { Code = code, ExpiresAt = entry.ExpiresAt };
}
public SnapshotDownloadResponse? Retrieve(string userId, string code)
{
var e = Col.FindOne(x => x.UserId == userId && x.Code == code.ToUpperInvariant());
if (e is null || e.ExpiresAt < DateTime.UtcNow) { if (e is not null) Col.Delete(e.Id); return null; }
Col.Delete(e.Id);
return new() { EncryptedPayload = e.EncryptedPayload, EncryptedSyncKey = e.EncryptedSyncKey,
CreatedAt = e.CreatedAt, SourceDeviceType = e.SourceDeviceType };
}
private void Clean() => Col.DeleteMany(e => e.ExpiresAt < DateTime.UtcNow);
private static string NewCode()
{
string[] animals = ["TIGER","ADLER","DACHS","LUCHS","FALKE","IGEL","ELCH","FUCHS","RABE","WOLF","BISON","LAMM","EULE","BIBER","STORCH"];
string[] colors = ["BLAU","GRUEN","ROT","GOLD","GRAU","CYAN","ROSA","LILA","SAND","MINT"];
return $"{animals[Random.Shared.Next(animals.Length)]}-{Random.Shared.Next(10,99)}-{colors[Random.Shared.Next(colors.Length)]}";
}
public void Dispose() { _cleanup?.Dispose(); _db.Dispose(); }
}
internal class SnapshotEntry
{
public ObjectId Id { get; set; } = ObjectId.NewObjectId();
public string Code { get; set; } = "";
public string UserId { get; set; } = "";
public string EncryptedPayload { get; set; } = "";
public string EncryptedSyncKey { get; set; } = "";
public DeviceType SourceDeviceType { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime ExpiresAt { get; set; }
}