Дочистить код-стайл: var встроенных типов, приватные доки, доки интерфейсам
Гейт csharp_style_var_for_built_in_types=false:warning (ломает сборку), остаток выправлен dotnet format IDE0008 по 5 sln (только встроенные типы). Понижено 12 новых XML-доков private/internal, добавлены <summary> членам IContainerRules и ITenantContext, 3 англоязычных комментария переведены на русский.
This commit is contained in:
+2
-1
@@ -30,7 +30,8 @@ dotnet_style_qualification_for_method = false:warning
|
||||
dotnet_style_qualification_for_event = false:warning
|
||||
|
||||
# Члены
|
||||
csharp_style_var_for_built_in_types = false:silent
|
||||
# var — запрещён для встроенных типов (ломает сборку), для очевидных/прочих — silent (§4 код-стайла)
|
||||
csharp_style_var_for_built_in_types = false:warning
|
||||
csharp_style_var_when_type_is_apparent = false:silent
|
||||
csharp_style_var_elsewhere = false:silent
|
||||
|
||||
|
||||
@@ -111,8 +111,8 @@ public static class AuthEndpoints
|
||||
HttpContext context,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var cookieName = cookieOptions.Value.Name;
|
||||
var rawToken = context.Request.Cookies[cookieName];
|
||||
string cookieName = cookieOptions.Value.Name;
|
||||
string? rawToken = context.Request.Cookies[cookieName];
|
||||
// Пользователь разрешённой сессии — до её удаления (SessionMiddleware наполнил Items на старте запроса).
|
||||
CurrentUser? user = context.GetCurrentUser();
|
||||
var logout = await authService.LogoutAsync(rawToken, ct);
|
||||
@@ -166,7 +166,7 @@ public static class AuthEndpoints
|
||||
var result = await authService.ChangePasswordAsync(user.Login, body.OldPassword, body.NewPassword, ct);
|
||||
if (!result.Ok || result.NewToken is null)
|
||||
{
|
||||
var detail = result.Error == ChangePasswordResultDto.ErrorTooShort
|
||||
string detail = result.Error == ChangePasswordResultDto.ErrorTooShort
|
||||
? PasswordTooShortDetail
|
||||
: WrongOldPasswordDetail;
|
||||
return EndpointResults.BadRequest(detail);
|
||||
|
||||
@@ -91,8 +91,8 @@ public static class OperatorAuthEndpoints
|
||||
HttpContext context,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var cookieName = cookieOptions.Value.Name;
|
||||
var rawToken = context.Request.Cookies[cookieName];
|
||||
string cookieName = cookieOptions.Value.Name;
|
||||
string? rawToken = context.Request.Cookies[cookieName];
|
||||
// Оператор разрешённой сессии — до её удаления (OperatorSessionMiddleware наполнил Items).
|
||||
CurrentOperator? operatorIdentity = context.GetCurrentOperator();
|
||||
await operatorAuthService.LogoutAsync(rawToken, ct);
|
||||
|
||||
@@ -17,8 +17,8 @@ public sealed class OperatorBootstrapHostedService(
|
||||
await using var scope = scopeFactory.CreateAsyncScope();
|
||||
var operatorBootstrapService = scope.ServiceProvider.GetRequiredService<OperatorBootstrapService>();
|
||||
|
||||
var login = configuration[OperatorBootstrapService.LoginEnvKey];
|
||||
var password = configuration[OperatorBootstrapService.PasswordEnvKey];
|
||||
string? login = configuration[OperatorBootstrapService.LoginEnvKey];
|
||||
string? password = configuration[OperatorBootstrapService.PasswordEnvKey];
|
||||
bool hasLogin = !string.IsNullOrWhiteSpace(login);
|
||||
bool hasPassword = !string.IsNullOrWhiteSpace(password);
|
||||
bool allowDevelopmentDefaults = environment.IsDevelopment();
|
||||
@@ -47,7 +47,7 @@ public sealed class OperatorBootstrapHostedService(
|
||||
}
|
||||
}
|
||||
|
||||
var ensuredLogin = await operatorBootstrapService.EnsureOperatorAsync(
|
||||
string? ensuredLogin = await operatorBootstrapService.EnsureOperatorAsync(
|
||||
login, password, allowDevelopmentDefaults, ct);
|
||||
if (ensuredLogin is not null)
|
||||
{
|
||||
|
||||
@@ -34,11 +34,11 @@ public sealed class TenantBootstrapService(IServiceScopeFactory scopeFactory) :
|
||||
var authStore = scope.ServiceProvider.GetRequiredService<IAuthStore>();
|
||||
var passwordHasher = scope.ServiceProvider.GetRequiredService<IPasswordHasher>();
|
||||
|
||||
var login = NormalizeLogin(configuration[BootstrapLoginEnvKey] ?? DefaultAdminLogin);
|
||||
var password = configuration[BootstrapPasswordEnvKey] ?? DefaultAdminPassword;
|
||||
string login = NormalizeLogin(configuration[BootstrapLoginEnvKey] ?? DefaultAdminLogin);
|
||||
string password = configuration[BootstrapPasswordEnvKey] ?? DefaultAdminPassword;
|
||||
var environment = scope.ServiceProvider.GetRequiredService<IHostEnvironment>();
|
||||
|
||||
var seedDefaultTenant = environment.IsDevelopment()
|
||||
bool seedDefaultTenant = environment.IsDevelopment()
|
||||
|| configuration[DefaultTenantBootstrapEnvKey] == DefaultTenantBootstrapEnabledValue;
|
||||
if (seedDefaultTenant)
|
||||
{
|
||||
|
||||
@@ -26,8 +26,8 @@ public sealed class OperatorSessionMiddleware
|
||||
/// </summary>
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
var cookieName = _cookieOptions.CurrentValue.Name;
|
||||
if (context.Request.Cookies.TryGetValue(cookieName, out var rawToken)
|
||||
string cookieName = _cookieOptions.CurrentValue.Name;
|
||||
if (context.Request.Cookies.TryGetValue(cookieName, out string? rawToken)
|
||||
&& !string.IsNullOrWhiteSpace(rawToken))
|
||||
{
|
||||
// OperatorAuthService scoped: создаём scope на запрос через RequestServices.
|
||||
|
||||
@@ -35,8 +35,8 @@ public sealed class SessionMiddleware
|
||||
{
|
||||
try
|
||||
{
|
||||
var cookieName = _cookieOptions.CurrentValue.Name;
|
||||
if (context.Request.Cookies.TryGetValue(cookieName, out var rawToken)
|
||||
string cookieName = _cookieOptions.CurrentValue.Name;
|
||||
if (context.Request.Cookies.TryGetValue(cookieName, out string? rawToken)
|
||||
&& !string.IsNullOrWhiteSpace(rawToken))
|
||||
{
|
||||
// AuthService scoped: создаём scope на запрос через RequestServices.
|
||||
|
||||
@@ -69,7 +69,7 @@ DealMetricsHosting.AddDealMetrics(builder, metricsPort);
|
||||
|
||||
// Строка подключения Postgres — ТОЛЬКО из конфигурации (env/appsettings): dev-пароль в коде отсутствует
|
||||
// (Security review). Отсутствие строки = fail-fast на старте, а не тихий уход на несуществующую dev-БД.
|
||||
var connectionString = builder.Configuration.GetConnectionString("DealPostgres")
|
||||
string connectionString = builder.Configuration.GetConnectionString("DealPostgres")
|
||||
?? throw new InvalidOperationException("ConnectionStrings:DealPostgres не задан");
|
||||
builder.Services.AddDbContext<DealDbContext>(options => options.UseNpgsql(connectionString));
|
||||
builder.Services.AddSingleton<ITenantContext, TenantContext>();
|
||||
|
||||
@@ -2,9 +2,7 @@ using Grpc.Core;
|
||||
|
||||
namespace Deal.Infrastructure.Integrations.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения классификации gRPC-исключений клиентов автономных сервисов.
|
||||
/// </summary>
|
||||
// Расширения классификации gRPC-исключений клиентов автономных сервисов.
|
||||
internal static class RpcExceptionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -3,9 +3,7 @@ using System.Net.Sockets;
|
||||
|
||||
namespace Deal.Infrastructure.Integrations.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения <see cref="Uri"/> для SSRF-гейта интеграций
|
||||
/// </summary>
|
||||
// Расширения Uri для SSRF-гейта интеграций
|
||||
internal static class UriExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
+1
-3
@@ -2,9 +2,7 @@ using Deal.Infrastructure.Integrations.Storage.Options;
|
||||
|
||||
namespace Deal.Infrastructure.Integrations.Storage.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения <see cref="MinioStorageOptions"/>
|
||||
/// </summary>
|
||||
// Расширения MinioStorageOptions
|
||||
internal static class MinioStorageOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
namespace Deal.Infrastructure.Integrations.Storage.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения <see cref="string"/> для разбора конфигурационных значений.
|
||||
/// </summary>
|
||||
// Расширения string для разбора конфигурационных значений.
|
||||
internal static class StringExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -10,7 +10,7 @@ public static class TenantSchemaMigrator
|
||||
/// </summary>
|
||||
public static string CreateSchemaSql(string schemaName)
|
||||
{
|
||||
var escaped = schemaName.Replace("\"", "\"\"");
|
||||
string escaped = schemaName.Replace("\"", "\"\"");
|
||||
return $"CREATE SCHEMA IF NOT EXISTS \"{escaped}\"";
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ public sealed class DealDbDesignTimeFactory : IDesignTimeDbContextFactory<DealDb
|
||||
{
|
||||
public DealDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var connectionString = Environment.GetEnvironmentVariable("DEAL_PG_CONNECTION")
|
||||
string connectionString = Environment.GetEnvironmentVariable("DEAL_PG_CONNECTION")
|
||||
?? "Host=localhost;Port=5433;Database=deal;Username=deal;Password=deal_dev_password";
|
||||
var options = new DbContextOptionsBuilder<DealDbContext>()
|
||||
.UseNpgsql(connectionString)
|
||||
|
||||
@@ -10,7 +10,7 @@ public sealed class TenantDbDesignTimeFactory : IDesignTimeDbContextFactory<Tena
|
||||
{
|
||||
public TenantDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var connectionString = Environment.GetEnvironmentVariable("DEAL_PG_CONNECTION")
|
||||
string connectionString = Environment.GetEnvironmentVariable("DEAL_PG_CONNECTION")
|
||||
?? "Host=localhost;Port=5433;Database=deal;Username=deal;Password=deal_dev_password";
|
||||
var options = new DbContextOptionsBuilder<TenantDbContext>()
|
||||
.UseNpgsql(connectionString, npgsql => npgsql.MigrationsHistoryTable("__TenantMigrationsHistory"))
|
||||
|
||||
@@ -24,7 +24,7 @@ public sealed class TenantProvisioningService(ConnectionStringProvider connectio
|
||||
/// <inheritdoc />
|
||||
public async Task ProvisionAsync(TenantId tenantId, CancellationToken ct)
|
||||
{
|
||||
var schemaName = tenantId.SchemaName;
|
||||
string schemaName = tenantId.SchemaName;
|
||||
var provisionLock = SchemaProvisionLocks.GetOrAdd(schemaName, static _ => new SemaphoreSlim(1, 1));
|
||||
await provisionLock.WaitAsync(ct);
|
||||
try
|
||||
@@ -63,7 +63,7 @@ public sealed class TenantProvisioningService(ConnectionStringProvider connectio
|
||||
{
|
||||
// Строка уже с Search Path=tenant_<id> (ForSchemaDdl) — таблицы бессхемной модели TenantDbContext
|
||||
// лягут в схему тенанта. DDL применяется мигратор-ролью при её наличии (см. ConnectionStringProvider).
|
||||
var connectionString = connectionStringProvider.ForSchemaDdl(tenantId);
|
||||
string connectionString = connectionStringProvider.ForSchemaDdl(tenantId);
|
||||
var options = new DbContextOptionsBuilder<TenantDbContext>()
|
||||
.UseNpgsql(connectionString, npgsql => npgsql.MigrationsHistoryTable(TenantMigrationsHistoryTable, schemaName))
|
||||
.Options;
|
||||
|
||||
@@ -12,8 +12,14 @@ public interface IContainerRules
|
||||
/// </summary>
|
||||
public string Mode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ключевые слова
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Keywords { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Стек технологий
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Stack { get; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,9 +2,7 @@ using Deal.Modules.Kanban.Application.Models;
|
||||
|
||||
namespace Deal.Modules.Kanban.Application.ColumnRules;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения бюджетной группы правил колонки.
|
||||
/// </summary>
|
||||
// Расширения бюджетной группы правил колонки.
|
||||
internal static class BudgetRangeDtoExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
namespace Deal.Modules.Kanban.Application.ColumnRules;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения списков термов правил колонки.
|
||||
/// </summary>
|
||||
// Расширения списков термов правил колонки.
|
||||
internal static class TermListExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
namespace Deal.Modules.Kanban.Application.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения символов для нормализации бюджетной валюты.
|
||||
/// </summary>
|
||||
// Расширения символов для нормализации бюджетной валюты.
|
||||
internal static class CharExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
namespace Deal.Modules.Pipeline.Application.Parse;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения кодовых точек для чистки текста сообщений.
|
||||
/// </summary>
|
||||
// Расширения кодовых точек для чистки текста сообщений.
|
||||
internal static class CodePointExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
namespace Deal.Modules.Pipeline.Application.Parse;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения строк для разбора текста сообщений.
|
||||
/// </summary>
|
||||
// Расширения строк для разбора текста сообщений.
|
||||
internal static class StringExtensions
|
||||
{
|
||||
private static readonly string[] FooterHintsArray =
|
||||
|
||||
@@ -141,7 +141,7 @@ public static class SettingsKeys
|
||||
|
||||
public const string ExcludeTypes = "excludeTypes";
|
||||
|
||||
// ── Dict / special ──
|
||||
// ── Словари / особые ──
|
||||
|
||||
public const string ColState = "colState";
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
namespace Deal.Modules.Tenants.Application.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения записей аудита
|
||||
/// </summary>
|
||||
// Расширения записей аудита
|
||||
internal static class AuditRecordDtoExtensions
|
||||
{
|
||||
// События аудита «неудачный вход» (тенант/оператор).
|
||||
|
||||
@@ -36,7 +36,7 @@ public sealed class AuthService(
|
||||
string password,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var normalizedLogin = NormalizeLogin(login);
|
||||
string normalizedLogin = NormalizeLogin(login);
|
||||
if (string.IsNullOrEmpty(normalizedLogin) || string.IsNullOrEmpty(password))
|
||||
{
|
||||
return new LoginResultDto(null, null);
|
||||
@@ -61,7 +61,7 @@ public sealed class AuthService(
|
||||
Error: LoginResultDto.ErrorTenantSuspended);
|
||||
}
|
||||
|
||||
var token = await CreateSessionForUserAsync(user.Id, user.Login, impersonatedByOperatorId: null, ct);
|
||||
string token = await CreateSessionForUserAsync(user.Id, user.Login, impersonatedByOperatorId: null, ct);
|
||||
return new LoginResultDto(user.Login, token, user.Id, user.TenantId);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public sealed class AuthService(
|
||||
return null;
|
||||
}
|
||||
|
||||
var tokenHash = SessionTokens.HashToken(rawToken);
|
||||
string tokenHash = SessionTokens.HashToken(rawToken);
|
||||
var session = await authStore.FindSessionByTokenHashAsync(tokenHash, ct);
|
||||
await authStore.DeleteSessionAsync(tokenHash, ct);
|
||||
|
||||
@@ -111,7 +111,7 @@ public sealed class AuthService(
|
||||
string newPassword,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var normalizedLogin = NormalizeLogin(login);
|
||||
string normalizedLogin = NormalizeLogin(login);
|
||||
var user = await authStore.FindUserByLoginAsync(normalizedLogin, ct);
|
||||
if (user is null || oldPassword is null || !passwordHasher.Verify(oldPassword, user.PasswordHash))
|
||||
{
|
||||
@@ -125,7 +125,7 @@ public sealed class AuthService(
|
||||
|
||||
await authStore.DeleteSessionsByUserIdAsync(user.Id, ct);
|
||||
await authStore.UpdatePasswordHashAsync(user.Id, passwordHasher.Hash(newPassword), ct);
|
||||
var token = await CreateSessionForUserAsync(user.Id, user.Login, impersonatedByOperatorId: null, ct);
|
||||
string token = await CreateSessionForUserAsync(user.Id, user.Login, impersonatedByOperatorId: null, ct);
|
||||
return new ChangePasswordResultDto(Ok: true, Error: null, NewToken: token);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ public sealed class AuthService(
|
||||
return ImpersonationResultDto.Failed(ImpersonationResultDto.ErrorTenantNotFound);
|
||||
}
|
||||
|
||||
var normalizedLogin = NormalizeLogin(targetLogin);
|
||||
string normalizedLogin = NormalizeLogin(targetLogin);
|
||||
if (string.IsNullOrEmpty(normalizedLogin))
|
||||
{
|
||||
// login не задан — первый пользователь тенанта (по CreatedAt, порядок ListUsersByTenantIdAsync).
|
||||
@@ -159,7 +159,7 @@ public sealed class AuthService(
|
||||
}
|
||||
|
||||
UserIdentityDto firstUser = tenantUsers[0];
|
||||
var rawTokenForFirst = await CreateSessionForUserAsync(firstUser.Id, firstUser.Login, operatorId, ct);
|
||||
string rawTokenForFirst = await CreateSessionForUserAsync(firstUser.Id, firstUser.Login, operatorId, ct);
|
||||
return Success(rawTokenForFirst, firstUser.Id, firstUser.Login, firstUser.TenantId);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public sealed class AuthService(
|
||||
return ImpersonationResultDto.Failed(ImpersonationResultDto.ErrorUserNotFound);
|
||||
}
|
||||
|
||||
var rawToken = await CreateSessionForUserAsync(user.Id, user.Login, operatorId, ct);
|
||||
string rawToken = await CreateSessionForUserAsync(user.Id, user.Login, operatorId, ct);
|
||||
return Success(rawToken, user.Id, user.Login, user.TenantId);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ public sealed class AuthService(
|
||||
return null;
|
||||
}
|
||||
|
||||
var tokenHash = SessionTokens.HashToken(rawToken);
|
||||
string tokenHash = SessionTokens.HashToken(rawToken);
|
||||
var session = await authStore.FindSessionByTokenHashAsync(tokenHash, ct);
|
||||
UserIdentityDto? user = null;
|
||||
if (session is not null && session.ExpiresAt > DateTimeOffset.UtcNow)
|
||||
@@ -230,7 +230,7 @@ public sealed class AuthService(
|
||||
Guid? impersonatedByOperatorId,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var rawToken = SessionTokens.NewToken();
|
||||
string rawToken = SessionTokens.NewToken();
|
||||
var session = new SessionDto(
|
||||
TokenHash: SessionTokens.HashToken(rawToken),
|
||||
UserId: userId,
|
||||
|
||||
@@ -27,7 +27,7 @@ public sealed class OperatorAuthService(IOperatorAuthStore operatorAuthStore, IP
|
||||
string password,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var normalizedLogin = NormalizeLogin(login);
|
||||
string normalizedLogin = NormalizeLogin(login);
|
||||
if (string.IsNullOrEmpty(normalizedLogin) || string.IsNullOrEmpty(password))
|
||||
{
|
||||
return new OperatorLoginResultDto(null, null);
|
||||
@@ -39,7 +39,7 @@ public sealed class OperatorAuthService(IOperatorAuthStore operatorAuthStore, IP
|
||||
return new OperatorLoginResultDto(null, null);
|
||||
}
|
||||
|
||||
var token = await CreateSessionForOperatorAsync(operatorRecord, ct);
|
||||
string token = await CreateSessionForOperatorAsync(operatorRecord, ct);
|
||||
return new OperatorLoginResultDto(operatorRecord.Login, token, operatorRecord.Id);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public sealed class OperatorAuthService(IOperatorAuthStore operatorAuthStore, IP
|
||||
return null;
|
||||
}
|
||||
|
||||
var tokenHash = SessionTokens.HashToken(rawToken);
|
||||
string tokenHash = SessionTokens.HashToken(rawToken);
|
||||
var session = await operatorAuthStore.FindSessionByTokenHashAsync(tokenHash, ct);
|
||||
OperatorIdentityDto? operatorIdentity = null;
|
||||
if (session is not null && session.ExpiresAt > DateTimeOffset.UtcNow)
|
||||
@@ -83,7 +83,7 @@ public sealed class OperatorAuthService(IOperatorAuthStore operatorAuthStore, IP
|
||||
else if (session is not null)
|
||||
{
|
||||
// Очистка протухших сессий — только при обнаружении протухшей (редкий случай), не на каждый запрос
|
||||
// (hot-path, Security review).
|
||||
// (горячий путь запросов).
|
||||
await operatorAuthStore.DeleteExpiredSessionsAsync(ct);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public sealed class OperatorAuthService(IOperatorAuthStore operatorAuthStore, IP
|
||||
// Возвращает: Raw-токен для выдачи клиенту.
|
||||
private async Task<string> CreateSessionForOperatorAsync(StoredOperatorDto operatorRecord, CancellationToken ct)
|
||||
{
|
||||
var rawToken = SessionTokens.NewToken();
|
||||
string rawToken = SessionTokens.NewToken();
|
||||
var session = new OperatorSessionDto(
|
||||
TokenHash: SessionTokens.HashToken(rawToken),
|
||||
OperatorId: operatorRecord.Id,
|
||||
|
||||
@@ -43,8 +43,8 @@ public sealed class OperatorBootstrapService(IOperatorAuthStore operatorAuthStor
|
||||
bool allowDevelopmentDefaults,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var normalizedLogin = NormalizeLogin(login);
|
||||
var resolvedPassword = password;
|
||||
string normalizedLogin = NormalizeLogin(login);
|
||||
string? resolvedPassword = password;
|
||||
if (string.IsNullOrEmpty(normalizedLogin) || string.IsNullOrEmpty(resolvedPassword))
|
||||
{
|
||||
if (!allowDevelopmentDefaults)
|
||||
|
||||
@@ -26,7 +26,7 @@ public static class SessionTokens
|
||||
/// <returns>64 hex-символа.</returns>
|
||||
public static string HashToken(string rawToken)
|
||||
{
|
||||
var hash = SHA256.HashData(Encoding.UTF8.GetBytes(rawToken));
|
||||
byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes(rawToken));
|
||||
return Convert.ToHexString(hash).ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public sealed class TenantService(ITenantRepository tenantRepository, ITenantPro
|
||||
CreatedAt: DateTimeOffset.UtcNow),
|
||||
ct);
|
||||
|
||||
var tenantIdValue = id.ToString("N");
|
||||
string tenantIdValue = id.ToString("N");
|
||||
await tenantProvisioner.ProvisionAsync(new TenantId(tenantIdValue), ct);
|
||||
return new TenantId(tenantIdValue);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,14 @@ namespace Deal.SharedKernel.Tenants.Abstractions;
|
||||
/// </summary>
|
||||
public interface ITenantContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Идентификатор текущего тенанта или null для системного контекста
|
||||
/// </summary>
|
||||
public TenantId? TenantId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Признак наличия текущего тенанта
|
||||
/// </summary>
|
||||
public bool HasTenant { get; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,7 +18,7 @@ public static class UrlSafeToken
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(byteCount);
|
||||
|
||||
var bytes = new byte[byteCount];
|
||||
byte[] bytes = new byte[byteCount];
|
||||
RandomNumberGenerator.Fill(bytes);
|
||||
return Convert.ToBase64String(bytes)
|
||||
.TrimEnd('=')
|
||||
|
||||
@@ -37,7 +37,7 @@ public sealed class AuthStoreTests
|
||||
var userId = Guid.NewGuid();
|
||||
await CreateUserAsync(store, Guid.NewGuid(), "user@example.com");
|
||||
var operatorId = Guid.NewGuid();
|
||||
var tokenHash = "token-hash-impersonation";
|
||||
string tokenHash = "token-hash-impersonation";
|
||||
|
||||
await store.CreateSessionAsync(
|
||||
new SessionDto(tokenHash, userId, "user@example.com", DateTimeOffset.UtcNow.AddDays(30), operatorId),
|
||||
@@ -49,7 +49,7 @@ public sealed class AuthStoreTests
|
||||
Assert.Equal(userId, found.UserId);
|
||||
|
||||
// Обычная сессия (без маркера) читается как ImpersonatedByOperatorId=null.
|
||||
var plainHash = "token-hash-plain";
|
||||
string plainHash = "token-hash-plain";
|
||||
await store.CreateSessionAsync(
|
||||
new SessionDto(plainHash, userId, "user@example.com", DateTimeOffset.UtcNow.AddDays(30)),
|
||||
CancellationToken.None);
|
||||
|
||||
@@ -53,7 +53,7 @@ public sealed class TenantSchemaMigrationServiceTests
|
||||
[Fact]
|
||||
public async Task MigrateAllAsync_OneSchemaFails_ContinuesAndReportsFailed()
|
||||
{
|
||||
var failingSchema = $"tenant_{TenantA:N}";
|
||||
string failingSchema = $"tenant_{TenantA:N}";
|
||||
var provisioner = new FailingTenantProvisioner(failingSchema);
|
||||
var repository = new FakeTenantRepository(
|
||||
TenantRecord(TenantA, "A"),
|
||||
@@ -115,7 +115,7 @@ public sealed class TenantSchemaMigrationServiceTests
|
||||
public async Task MigrateAllAsync_SchemaFailsWithinPage_ContinuesOthers()
|
||||
{
|
||||
TenantRecordDto[] records = Records(3);
|
||||
var failingSchema = $"tenant_{records[0].Id:N}";
|
||||
string failingSchema = $"tenant_{records[0].Id:N}";
|
||||
var provisioner = new FailingTenantProvisioner(failingSchema);
|
||||
var repository = new FakeTenantRepository(records);
|
||||
var service = NewService(repository, provisioner);
|
||||
|
||||
@@ -7,7 +7,7 @@ public sealed class TenantSchemaMigratorTests
|
||||
[Fact]
|
||||
public void CreateSchemaSql_IsEscaped()
|
||||
{
|
||||
var sql = TenantSchemaMigrator.CreateSchemaSql("tenant_abc");
|
||||
string sql = TenantSchemaMigrator.CreateSchemaSql("tenant_abc");
|
||||
Assert.Contains("CREATE SCHEMA IF NOT EXISTS \"tenant_abc\"", sql);
|
||||
Assert.DoesNotContain("; DROP", sql);
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public sealed class TenantSchemaMigratorTests
|
||||
[Fact]
|
||||
public void CreateSchemaSql_EscapesQuotes()
|
||||
{
|
||||
var sql = TenantSchemaMigrator.CreateSchemaSql("tenant_a\"b");
|
||||
string sql = TenantSchemaMigrator.CreateSchemaSql("tenant_a\"b");
|
||||
Assert.Contains("\"tenant_a\"\"b\"", sql);
|
||||
Assert.DoesNotContain("\"tenant_a\"b\"", sql);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public sealed class PromptDefaultsTests
|
||||
[Fact]
|
||||
public void Fill_MoreThanSixtyKeywords_TakesFirstSixty()
|
||||
{
|
||||
var keywords = Enumerable.Range(1, 65).Select(index => $"слово-{index}").ToArray();
|
||||
string[] keywords = Enumerable.Range(1, 65).Select(index => $"слово-{index}").ToArray();
|
||||
|
||||
string result = PromptFiller.Fill("{keywords}", "сфера", keywords);
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ public sealed class AuthServiceTests
|
||||
[Fact]
|
||||
public async Task ResolveSessionAsync_WithExpiredSession_ReturnsNull()
|
||||
{
|
||||
var rawToken = "expired-session-raw-token";
|
||||
string rawToken = "expired-session-raw-token";
|
||||
_store.AddSession(new SessionDto(
|
||||
SessionTokens.HashToken(rawToken), UserId, UserLogin, DateTimeOffset.UtcNow.AddDays(-1)));
|
||||
|
||||
@@ -140,7 +140,7 @@ public sealed class AuthServiceTests
|
||||
[Fact]
|
||||
public async Task ResolveSessionAsync_WithValidSession_ReturnsUser()
|
||||
{
|
||||
var rawToken = "valid-session-raw-token";
|
||||
string rawToken = "valid-session-raw-token";
|
||||
_store.AddSession(new SessionDto(
|
||||
SessionTokens.HashToken(rawToken), UserId, UserLogin, DateTimeOffset.UtcNow.AddDays(30)));
|
||||
|
||||
@@ -157,7 +157,7 @@ public sealed class AuthServiceTests
|
||||
[Fact]
|
||||
public async Task ResolveSessionAsync_WhenTenantSuspended_ReturnsNullImmediately()
|
||||
{
|
||||
var rawToken = "suspended-tenant-session";
|
||||
string rawToken = "suspended-tenant-session";
|
||||
_store.AddSession(new SessionDto(
|
||||
SessionTokens.HashToken(rawToken), UserId, UserLogin, DateTimeOffset.UtcNow.AddDays(30)));
|
||||
await _tenantStore.UpdateStatusAsync(UserTenantId, TenantStatuses.Suspended, CancellationToken.None);
|
||||
@@ -181,8 +181,8 @@ public sealed class AuthServiceTests
|
||||
[Fact]
|
||||
public async Task LogoutAsync_WithToken_DeletesSession()
|
||||
{
|
||||
var rawToken = "logout-session-raw-token";
|
||||
var tokenHash = SessionTokens.HashToken(rawToken);
|
||||
string rawToken = "logout-session-raw-token";
|
||||
string tokenHash = SessionTokens.HashToken(rawToken);
|
||||
_store.AddSession(new SessionDto(tokenHash, UserId, UserLogin, DateTimeOffset.UtcNow.AddDays(30)));
|
||||
|
||||
await _service.LogoutAsync(rawToken, CancellationToken.None);
|
||||
@@ -330,8 +330,8 @@ public sealed class AuthServiceTests
|
||||
public async Task LogoutAsync_ForImpersonationSession_ReturnsStopInfoAndDeletesSession()
|
||||
{
|
||||
var operatorId = Guid.NewGuid();
|
||||
var rawToken = "impersonation-session-raw-token";
|
||||
var tokenHash = SessionTokens.HashToken(rawToken);
|
||||
string rawToken = "impersonation-session-raw-token";
|
||||
string tokenHash = SessionTokens.HashToken(rawToken);
|
||||
_store.AddSession(new SessionDto(tokenHash, UserId, UserLogin, DateTimeOffset.UtcNow.AddDays(30), operatorId));
|
||||
|
||||
var logout = await _service.LogoutAsync(rawToken, CancellationToken.None);
|
||||
@@ -347,8 +347,8 @@ public sealed class AuthServiceTests
|
||||
[Fact]
|
||||
public async Task LogoutAsync_ForNormalSession_ReturnsNull()
|
||||
{
|
||||
var rawToken = "normal-session-raw-token";
|
||||
var tokenHash = SessionTokens.HashToken(rawToken);
|
||||
string rawToken = "normal-session-raw-token";
|
||||
string tokenHash = SessionTokens.HashToken(rawToken);
|
||||
_store.AddSession(new SessionDto(tokenHash, UserId, UserLogin, DateTimeOffset.UtcNow.AddDays(30)));
|
||||
|
||||
var logout = await _service.LogoutAsync(rawToken, CancellationToken.None);
|
||||
|
||||
@@ -102,7 +102,7 @@ public sealed class FakeAuthStore : IAuthStore
|
||||
string passwordHash,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var index = _users.FindIndex(u => u.Id == userId);
|
||||
int index = _users.FindIndex(u => u.Id == userId);
|
||||
if (index >= 0)
|
||||
{
|
||||
var user = _users[index];
|
||||
|
||||
@@ -71,7 +71,7 @@ public sealed class OperatorAuthServiceTests
|
||||
[Fact]
|
||||
public async Task ResolveSessionAsync_WithValidSession_ReturnsOperatorIdentity()
|
||||
{
|
||||
var rawToken = "valid-operator-session-raw-token";
|
||||
string rawToken = "valid-operator-session-raw-token";
|
||||
_store.AddSession(new OperatorSessionDto(
|
||||
SessionTokens.HashToken(rawToken), OperatorId, OperatorLogin, DateTimeOffset.UtcNow.AddHours(12)));
|
||||
|
||||
@@ -89,7 +89,7 @@ public sealed class OperatorAuthServiceTests
|
||||
[Fact]
|
||||
public async Task ResolveSessionAsync_WithExpiredSession_ReturnsNull()
|
||||
{
|
||||
var rawToken = "expired-operator-session-raw-token";
|
||||
string rawToken = "expired-operator-session-raw-token";
|
||||
_store.AddSession(new OperatorSessionDto(
|
||||
SessionTokens.HashToken(rawToken), OperatorId, OperatorLogin, DateTimeOffset.UtcNow.AddHours(-1)));
|
||||
|
||||
@@ -104,7 +104,7 @@ public sealed class OperatorAuthServiceTests
|
||||
[Fact]
|
||||
public async Task ResolveSessionAsync_WhenOperatorWasDeleted_ReturnsNull()
|
||||
{
|
||||
var rawToken = "orphan-operator-session-raw-token";
|
||||
string rawToken = "orphan-operator-session-raw-token";
|
||||
_store.AddSession(new OperatorSessionDto(
|
||||
SessionTokens.HashToken(rawToken), Guid.NewGuid(), "deleted-operator", DateTimeOffset.UtcNow.AddHours(12)));
|
||||
|
||||
@@ -119,7 +119,7 @@ public sealed class OperatorAuthServiceTests
|
||||
const string suspendedLogin = "suspended-operator";
|
||||
var passwordHasher = new FakePasswordHasher();
|
||||
_store.AddOperator(new StoredOperatorDto(Guid.NewGuid(), suspendedLogin, "suspended", passwordHasher.Hash("x")));
|
||||
var rawToken = "suspended-operator-session-raw-token";
|
||||
string rawToken = "suspended-operator-session-raw-token";
|
||||
_store.AddSession(new OperatorSessionDto(
|
||||
SessionTokens.HashToken(rawToken), Guid.NewGuid(), suspendedLogin, DateTimeOffset.UtcNow.AddHours(12)));
|
||||
|
||||
@@ -141,8 +141,8 @@ public sealed class OperatorAuthServiceTests
|
||||
[Fact]
|
||||
public async Task LogoutAsync_WithToken_DeletesSession()
|
||||
{
|
||||
var rawToken = "logout-operator-session-raw-token";
|
||||
var tokenHash = SessionTokens.HashToken(rawToken);
|
||||
string rawToken = "logout-operator-session-raw-token";
|
||||
string tokenHash = SessionTokens.HashToken(rawToken);
|
||||
_store.AddSession(new OperatorSessionDto(tokenHash, OperatorId, OperatorLogin, DateTimeOffset.UtcNow.AddHours(12)));
|
||||
|
||||
await _service.LogoutAsync(rawToken, CancellationToken.None);
|
||||
|
||||
@@ -22,7 +22,7 @@ public sealed class OperatorBootstrapServiceTests
|
||||
[Fact]
|
||||
public async Task InDevelopment_WithoutEnvCredentials_SeedsDefaultOperator()
|
||||
{
|
||||
var login = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
string? login = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
|
||||
Assert.Equal(OperatorBootstrapService.DefaultOperatorLogin, login);
|
||||
|
||||
@@ -36,7 +36,7 @@ public sealed class OperatorBootstrapServiceTests
|
||||
[Fact]
|
||||
public async Task InDevelopment_WithEmptyEnvCredentials_SeedsDefaultOperator()
|
||||
{
|
||||
var login = await _service.EnsureOperatorAsync("", "", allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
string? login = await _service.EnsureOperatorAsync("", "", allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
|
||||
Assert.Equal(OperatorBootstrapService.DefaultOperatorLogin, login);
|
||||
Assert.Single(_store.Operators);
|
||||
@@ -45,8 +45,8 @@ public sealed class OperatorBootstrapServiceTests
|
||||
[Fact]
|
||||
public async Task RepeatedBootstrap_IsIdempotent_KeepsSingleOperator()
|
||||
{
|
||||
var first = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
var second = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
string? first = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
string? second = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: true, CancellationToken.None);
|
||||
|
||||
Assert.Equal(OperatorBootstrapService.DefaultOperatorLogin, first);
|
||||
Assert.Equal(OperatorBootstrapService.DefaultOperatorLogin, second);
|
||||
@@ -58,7 +58,7 @@ public sealed class OperatorBootstrapServiceTests
|
||||
[Fact]
|
||||
public async Task Production_WithoutEnvCredentials_SkipsBootstrap()
|
||||
{
|
||||
var login = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: false, CancellationToken.None);
|
||||
string? login = await _service.EnsureOperatorAsync(null, null, allowDevelopmentDefaults: false, CancellationToken.None);
|
||||
|
||||
Assert.Null(login);
|
||||
Assert.Empty(_store.Operators);
|
||||
@@ -68,7 +68,7 @@ public sealed class OperatorBootstrapServiceTests
|
||||
[Fact]
|
||||
public async Task Production_WithEnvCredentials_CreatesOperatorWithNormalizedLogin()
|
||||
{
|
||||
var login = await _service.EnsureOperatorAsync(
|
||||
string? login = await _service.EnsureOperatorAsync(
|
||||
" Root-Admin ", "root-password", allowDevelopmentDefaults: false, CancellationToken.None);
|
||||
|
||||
Assert.Equal("root-admin", login);
|
||||
@@ -83,7 +83,7 @@ public sealed class OperatorBootstrapServiceTests
|
||||
{
|
||||
_store.AddOperator(new StoredOperatorDto(Guid.NewGuid(), "existing-op", "active", _passwordHasher.Hash("old-password")));
|
||||
|
||||
var login = await _service.EnsureOperatorAsync("EXISTING-OP", "new-password", allowDevelopmentDefaults: false, CancellationToken.None);
|
||||
string? login = await _service.EnsureOperatorAsync("EXISTING-OP", "new-password", allowDevelopmentDefaults: false, CancellationToken.None);
|
||||
|
||||
Assert.Equal("existing-op", login);
|
||||
Assert.Single(_store.Operators);
|
||||
|
||||
@@ -13,7 +13,7 @@ public sealed class PasswordHasherTests
|
||||
[Fact]
|
||||
public void Hash_ReturnsArgon2idEncodedStringDifferentFromPassword()
|
||||
{
|
||||
var hash = _hasher.Hash("correct horse battery staple");
|
||||
string hash = _hasher.Hash("correct horse battery staple");
|
||||
|
||||
Assert.False(string.IsNullOrWhiteSpace(hash));
|
||||
Assert.StartsWith("$argon2id$", hash);
|
||||
@@ -23,7 +23,7 @@ public sealed class PasswordHasherTests
|
||||
[Fact]
|
||||
public void Verify_WithCorrectPassword_ReturnsTrue()
|
||||
{
|
||||
var hash = _hasher.Hash("secret42");
|
||||
string hash = _hasher.Hash("secret42");
|
||||
|
||||
Assert.True(_hasher.Verify("secret42", hash));
|
||||
}
|
||||
@@ -31,7 +31,7 @@ public sealed class PasswordHasherTests
|
||||
[Fact]
|
||||
public void Verify_WithWrongPassword_ReturnsFalse()
|
||||
{
|
||||
var hash = _hasher.Hash("secret42");
|
||||
string hash = _hasher.Hash("secret42");
|
||||
|
||||
Assert.False(_hasher.Verify("wrong-password", hash));
|
||||
}
|
||||
@@ -39,8 +39,8 @@ public sealed class PasswordHasherTests
|
||||
[Fact]
|
||||
public void Hash_SamePasswordTwice_DifferentHashesBecauseOfRandomSalt()
|
||||
{
|
||||
var first = _hasher.Hash("same-password");
|
||||
var second = _hasher.Hash("same-password");
|
||||
string first = _hasher.Hash("same-password");
|
||||
string second = _hasher.Hash("same-password");
|
||||
|
||||
Assert.NotEqual(first, second);
|
||||
Assert.True(_hasher.Verify("same-password", first));
|
||||
|
||||
@@ -10,8 +10,8 @@ public sealed class SessionTokensTests
|
||||
[Fact]
|
||||
public void NewToken_ReturnsUniqueLongEnoughTokens()
|
||||
{
|
||||
var first = SessionTokens.NewToken();
|
||||
var second = SessionTokens.NewToken();
|
||||
string first = SessionTokens.NewToken();
|
||||
string second = SessionTokens.NewToken();
|
||||
|
||||
Assert.NotEqual(first, second);
|
||||
Assert.True(first.Length > 32);
|
||||
@@ -21,7 +21,7 @@ public sealed class SessionTokensTests
|
||||
[Fact]
|
||||
public void NewToken_UsesBase64UrlAlphabetWithoutPadding()
|
||||
{
|
||||
var token = SessionTokens.NewToken();
|
||||
string token = SessionTokens.NewToken();
|
||||
|
||||
// 32 байта в Base64Url без padding: 43 символа, без '=' и без небезопасных '+'/ '/'.
|
||||
Assert.Equal(43, token.Length);
|
||||
@@ -33,8 +33,8 @@ public sealed class SessionTokensTests
|
||||
[Fact]
|
||||
public void HashToken_IsDeterministicHexSha256()
|
||||
{
|
||||
var first = SessionTokens.HashToken("raw-token-value");
|
||||
var second = SessionTokens.HashToken("raw-token-value");
|
||||
string first = SessionTokens.HashToken("raw-token-value");
|
||||
string second = SessionTokens.HashToken("raw-token-value");
|
||||
|
||||
Assert.Equal(first, second);
|
||||
Assert.Equal(64, first.Length);
|
||||
@@ -43,8 +43,8 @@ public sealed class SessionTokensTests
|
||||
[Fact]
|
||||
public void HashToken_DifferentTokensProduceDifferentHashes()
|
||||
{
|
||||
var first = SessionTokens.HashToken("raw-token-1");
|
||||
var second = SessionTokens.HashToken("raw-token-2");
|
||||
string first = SessionTokens.HashToken("raw-token-1");
|
||||
string second = SessionTokens.HashToken("raw-token-2");
|
||||
|
||||
Assert.NotEqual(first, second);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public sealed class ConversionRecomputerTests
|
||||
|
||||
int updated = await service.RecomputeAsync(CancellationToken.None);
|
||||
|
||||
// 100 USD → EUR: 100 * 92.5 / 99.9 = 92.5925… → round 2.
|
||||
// 100 USD → EUR: 100 * 92.5 / 99.9 = 92.5925… → округление до 2 знаков.
|
||||
Assert.Equal(1, updated);
|
||||
AssertConverted(store, "l_board", convFrom: 92.59, convTo: 92.59, "EUR");
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.Diagnostics;
|
||||
using Grpc.Core;
|
||||
using Grpc.Core.Interceptors;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
using Deal.Grpc.Hosting.Services;
|
||||
using Grpc.Core;
|
||||
using Grpc.Core.Interceptors;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Deal.Grpc.Hosting.Interceptors;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Grpc.Core;
|
||||
using Grpc.Core.Interceptors;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
using Deal.Grpc.Hosting.Services;
|
||||
using Grpc.Core;
|
||||
using Grpc.Core.Interceptors;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Deal.Grpc.Hosting.Interceptors;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Deal.Grpc.Hosting.Interceptors;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Deal.Grpc.Hosting.Options;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Deal.Grpc.Hosting.Interceptors;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting.Compact;
|
||||
using Deal.Grpc.Hosting.Interceptors;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
|
||||
namespace Deal.Grpc.Hosting.Services;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Deal.Grpc.Hosting.Interceptors;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OpenTelemetry.Metrics;
|
||||
using Deal.Grpc.Hosting.Interceptors;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
|
||||
namespace Deal.Grpc.Hosting.Services;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using System.Net;
|
||||
using Deal.Grpc.Hosting.Interceptors;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Https;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Deal.Grpc.Hosting.Interceptors;
|
||||
using Deal.Grpc.Hosting.Models;
|
||||
using Deal.Grpc.Hosting.Options;
|
||||
|
||||
namespace Deal.Grpc.Hosting.Services;
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ using Deal.Ml.Model;
|
||||
|
||||
namespace Deal.Ml.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения <see cref="string"/> для меток классов ML-модели.
|
||||
/// </summary>
|
||||
// Расширения string для меток классов ML-модели.
|
||||
internal static class LabelExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -40,7 +40,7 @@ public sealed class DialogHueTests
|
||||
[Fact]
|
||||
public void Compute_DifferentSources_DistributeAcrossPalette()
|
||||
{
|
||||
var hues = new[]
|
||||
string[] hues = new[]
|
||||
{
|
||||
DialogHue.Compute("-100111", "Канал А"),
|
||||
DialogHue.Compute("-100222", "Канал Б"),
|
||||
|
||||
@@ -2,9 +2,7 @@ using Grpc.Core;
|
||||
|
||||
namespace Deal.Telegram.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Расширения <see cref="Exception"/> для классификации сбоев telegram-service.
|
||||
/// </summary>
|
||||
// Расширения Exception для классификации сбоев telegram-service.
|
||||
internal static class ExceptionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user