Initial commit: base slice (auth, roles, users, admin) scaffold

Backend: .NET 10 Clean Architecture + LiteCqrs.Net + EF Core/PostgreSQL +
Identity/JWT. Frontend: React 19 + Vite + TanStack Query/Router + Tailwind v4
with a retro CRT theme. Docker/compose deployment mirroring PnvPanel's
conventions, scoped down to the current base feature set.
This commit is contained in:
Leonid Pershin
2026-07-24 05:40:34 +03:00
commit 8a3eebc48f
156 changed files with 9335 additions and 0 deletions
@@ -0,0 +1,39 @@
namespace TeleWave.Domain.Auth;
/// <summary>
/// Refresh-токен пользователя. Хранится только SHA-256 хэш (см. IRefreshTokenService в Infrastructure) —
/// сырой токен нигде не персистится, кроме httpOnly-cookie на клиенте.
/// </summary>
public class RefreshToken
{
public Guid Id { get; private set; }
public Guid UserId { get; private set; }
public string TokenHash { get; private set; } = string.Empty;
public DateTimeOffset ExpiresAt { get; private set; }
public DateTimeOffset CreatedAt { get; private set; }
public DateTimeOffset? RevokedAt { get; private set; }
/// <summary>Хэш токена, которым этот был заменён при ротации — цепочка для обнаружения повторного
/// использования уже отозванного токена (признак компрометации).</summary>
public string? ReplacedByTokenHash { get; private set; }
private RefreshToken() { }
public static RefreshToken Issue(Guid userId, string tokenHash, DateTimeOffset expiresAt) =>
new()
{
Id = Guid.NewGuid(),
UserId = userId,
TokenHash = tokenHash,
ExpiresAt = expiresAt,
CreatedAt = DateTimeOffset.UtcNow,
};
public bool IsActive => RevokedAt is null && ExpiresAt > DateTimeOffset.UtcNow;
public void Revoke(string? replacedByTokenHash = null)
{
RevokedAt = DateTimeOffset.UtcNow;
ReplacedByTokenHash = replacedByTokenHash;
}
}
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>