mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 04:32:32 +00:00
dd4975b73e
A caller whose token shows it is not a member of the token's tenant (acct = 1, a #EXT# user name, or an idp naming another tenant, a personal Microsoft account or an external sign-in provider) no longer seeds DomainName/OnboardedBy or queues the activation, is never the first-user Tenant Admin, and cannot set the activation-page address in the roleless signup window. Positive evidence only: a token without these signals stays a member's, and tid/idp are read under their inbound-mapped names as well. Activation promotes OnboardedBy only; the UpdatedBy fallback is gone and a stored #EXT# UPN is refused. Explicit grants (TenantAdmins row, app role) still apply. The once-per-interval log gate of the client-app binding becomes Helpers/LogThrottle and also throttles the new warning, which the polling activation page would otherwise repeat. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.2 KiB
C#
35 lines
1.2 KiB
C#
using System.Collections.Concurrent;
|
|
|
|
namespace AutopilotMonitor.Functions.Helpers;
|
|
|
|
/// <summary>
|
|
/// Lets one log line per key through per interval, for request paths that would otherwise repeat it on every
|
|
/// call (worker traces reach App Insights at Warning+ only, so a polled or hot path must not flood them).
|
|
/// Process-local and bounded: past <c>maxKeys</c> the memory is dropped, which at worst repeats a line early.
|
|
/// </summary>
|
|
public sealed class LogThrottle
|
|
{
|
|
private readonly ConcurrentDictionary<string, DateTime> _lastLogged = new();
|
|
private readonly TimeSpan _interval;
|
|
private readonly int _maxKeys;
|
|
|
|
public LogThrottle(TimeSpan interval, int maxKeys = 1000)
|
|
{
|
|
_interval = interval;
|
|
_maxKeys = maxKeys;
|
|
}
|
|
|
|
/// <summary>True when the line for <paramref name="key"/> may be written now; records that it was.</summary>
|
|
public bool ShouldLog(string key) => ShouldLog(key, DateTime.UtcNow);
|
|
|
|
internal bool ShouldLog(string key, DateTime nowUtc)
|
|
{
|
|
if (_lastLogged.TryGetValue(key, out var last) && nowUtc - last < _interval)
|
|
return false;
|
|
if (_lastLogged.Count >= _maxKeys)
|
|
_lastLogged.Clear();
|
|
_lastLogged[key] = nowUtc;
|
|
return true;
|
|
}
|
|
}
|