drop the deigner.cs

This commit is contained in:
Paul Schneider 2026-07-04 16:06:02 +01:00
commit 90dfe9c13f
4 changed files with 60 additions and 109 deletions

View file

@ -1,82 +0,0 @@
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace Yavsc {
using System;
using System.Reflection;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public partial class ChatHubLabels {
private static System.Resources.ResourceManager resourceMan;
private static System.Globalization.CultureInfo resourceCulture;
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
public static System.Resources.ResourceManager ResourceManager {
get {
if (object.Equals(null, resourceMan)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager(("Yavsc.Abstract.Resources." + "Yavsc.ChatHub"), typeof(ChatHubLabels).GetTypeInfo().Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
public static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
public static string Authenticated_chat_user {
get {
return ResourceManager.GetString("Authenticated chat user", resourceCulture);
}
}
public static string LabnoJoinNoSend {
get {
return ResourceManager.GetString("LabnoJoinNoSend", resourceCulture);
}
}
public static string InvalidRoomName {
get {
return ResourceManager.GetString("InvalidRoomName", resourceCulture);
}
}
public static string InvalidUserName {
get {
return ResourceManager.GetString("InvalidUserName", resourceCulture);
}
}
public static string InvalidMessage {
get {
return ResourceManager.GetString("InvalidMessage", resourceCulture);
}
}
public static string InvalidReason {
get {
return ResourceManager.GetString("InvalidReason", resourceCulture);
}
}
}
}

View file

@ -264,21 +264,53 @@ namespace Yavsc.ApiControllers
return BadRequest(new { Error = "file write failed", Detail = ex.Message });
}
// Now persist the database row. The int[] is round-
// tripped via Npgsql's native int[] mapping; the
// migration (separate commit) introduces the column
// and the index.
var signature = new Signature
// Find-or-add: the (EstimateId, Type) pair is
// unique, so a second POST for the same side of the
// estimate replaces the previous signature. EF
// translates this into a single UPDATE when the
// row exists and an INSERT otherwise; the unique
// index in ApplicationDbContext is the
// database-level guarantee that the contract
// holds if two requests race.
var signature = await dbContext.Signatures
.FirstOrDefaultAsync(s => s.EstimateId == id && s.Type == type, token);
if (signature is null)
{
EstimateId = id,
SignerId = userId,
Type = type,
CoordinateMax = payload.CoordinateMax,
Strokes = payload.Strokes,
CapturedAtUtc = payload.CapturedAtUtc,
FilePath = Path.Combine(fi.DestDir, fi.FileName),
};
dbContext.Signatures.Add(signature);
signature = new Signature
{
EstimateId = id,
SignerId = userId,
Type = type,
};
dbContext.Signatures.Add(signature);
}
else
{
// Roll the signer's quota back by the size of
// the file we're about to orphan: the old
// FilePath is no longer referenced once we
// overwrite FilePath below.
try
{
var orphan = new FileInfo(signature.FilePath);
if (orphan.Exists)
{
var signerForOrphan = await dbContext.Users
.FirstOrDefaultAsync(u => u.Id == userId, token);
if (signerForOrphan is not null)
signerForOrphan.DiskUsage =
Math.Max(0, signerForOrphan.DiskUsage - orphan.Length);
}
}
catch { /* best effort — the file is being replaced anyway */ }
}
signature.SignerId = userId;
signature.CoordinateMax = payload.CoordinateMax;
signature.Strokes = payload.Strokes;
signature.CapturedAtUtc = payload.CapturedAtUtc;
signature.FilePath = Path.Combine(fi.DestDir, fi.FileName);
// Bump the signer's quota. The Signature row's
// SignerId is the IdentityUser.Id (a string), so we

View file

@ -35,7 +35,7 @@ namespace Yavsc.Server.Hubs
{
bool valid = ValidateStringLength(roomName,1,25);
if (valid) valid = IsLetterOrDigit(roomName);
if (!valid) NotifyUser(NotificationTypes.Error, "roomName", _locator.GetString(ChatHubLabels.InvalidRoomName));
if (!valid) NotifyUser(NotificationTypes.Error, "roomName", _locator.GetString("InvalidRoomName"));
return valid;
}
public bool ValidateUserName (string userName)
@ -52,14 +52,14 @@ namespace Yavsc.Server.Hubs
NotifyUser(
NotificationTypes.Error,
"userName",
_locator.GetString(ChatHubLabels.InvalidUserName));
_locator.GetString("InvalidUserName)"));
return valid;
}
public bool ValidateMessage (string message)
{
if (!ValidateStringLength(message, 1, 10240))
{
NotifyUser(NotificationTypes.Error, "message", _locator.GetString(ChatHubLabels.InvalidMessage));
NotifyUser(NotificationTypes.Error, "message", _locator.GetString("InvalidMessage"));
return false;
}
return true;
@ -68,7 +68,7 @@ namespace Yavsc.Server.Hubs
{
if (!ValidateStringLength(reason, 1,240))
{
NotifyUser(NotificationTypes.Error, "reason", ChatHubLabels.InvalidReason);
NotifyUser(NotificationTypes.Error, "reason", "InvalidReason");
return false;
}
return true;

View file

@ -69,16 +69,17 @@ namespace Yavsc.Models
builder.Entity<DeviceDeclaration>().Property(x => x.DeclarationDate).HasDefaultValueSql(NOW_SQL);
builder.Entity<BlogTag>().HasKey(x => new { x.PostId, x.TagId });
// Signature: composite index (EstimateId, Type,
// CapturedAtUtc DESC) to support the controller's
// "most recent signature per type" read pattern
// without an extra ORDER BY cost. The default
// EF-generated FK index on EstimateId alone is
// replaced by the composite to avoid duplicate
// indexes.
// Signature: unique constraint on (EstimateId, Type)
// — the most recent version replaces the previous
// one, so a partial unique index (not a regular one)
// is the right shape. The controller does a
// Find-or-Add so EF translates an upsert into a
// single UPDATE when the row already exists; the
// unique index is the database-level guarantee that
// the contract holds.
builder.Entity<Signature>()
.HasIndex(s => new { s.EstimateId, s.Type, s.CapturedAtUtc })
.IsDescending(false, false, true);
.HasIndex(s => new { s.EstimateId, s.Type })
.IsUnique();
builder.Entity<Signature>()
.HasOne(s => s.Estimate)
.WithMany(e => e.Signatures)