using PnvPanel.Application.Common.Models;
namespace PnvPanel.Application.Common.Interfaces;
public sealed record AuthenticatedUser(Guid Id, string UserName, string Role);
public sealed record CurrentUserProfile(
Guid Id,
string UserName,
Guid RoleId,
string Role,
bool IsActivated,
bool IsBlocked,
int MaxConfigs,
int MaxIpLimit,
string SubscriptionToken,
bool BillingEnabled,
DateTimeOffset? BillingPaidUntil,
bool BillingSuspended
);
/// Срез биллинг-полей пользователя — для фоновой джобы приостановки (см. BillingService),
/// не требует полного CurrentUserProfile (роль/квоты там не нужны).
public sealed record BillingUserDto(
Guid UserId,
DateTimeOffset? PaidUntil,
bool Suspended,
DateTimeOffset? LastWarnedForPaidUntil
);
public sealed record UserSummaryDto(
Guid Id,
string UserName,
string Role,
bool IsActivated,
bool IsBlocked,
DateTimeOffset? ActivatedAt,
bool BillingEnabled,
DateTimeOffset? BillingPaidUntil,
/// Есть Subscription-заявка на оплату в AwaitingConfirmation — конфиги не гасятся, пока
/// админ не решит (см. BillingService). Заполняется в ListUsersQueryHandler (не здесь — Identity
/// не должен знать про PaymentRequests), false по умолчанию для мест, не подгружающих это поле.
bool BillingPendingReview = false
);
public sealed record UserStatsDto(int Total, int Activated);
public sealed record TelegramLinkInfo(bool IsLinked, long? TelegramUserId, string? Username);
public interface IIdentityService
{
Task> CreateUserAsync(
string userName,
string password,
CancellationToken cancellationToken
);
Task> ValidateCredentialsAsync(
string userName,
string password,
CancellationToken cancellationToken
);
Task GetProfileAsync(Guid userId, CancellationToken cancellationToken);
Task ChangePasswordAsync(
Guid userId,
string currentPassword,
string newPassword,
CancellationToken cancellationToken
);
Task ChangeUserNameAsync(
Guid userId,
string newUserName,
CancellationToken cancellationToken
);
///
/// Помечает пользователя активированным. Изменение не коммитится немедленно (в отличие от
/// CreateUserAsync/ChangePasswordAsync) — оно попадает в трекер того же DbContext и сохраняется
/// вместе с изменением ActivationRequest одной транзакцией через UnitOfWorkBehavior.
///
Task ActivateUserAsync(
Guid userId,
Guid activatedBy,
CancellationToken cancellationToken
);
Task> GetUserNamesAsync(
IReadOnlyCollection userIds,
CancellationToken cancellationToken
);
/// Удаляет аккаунт (самоудаление). Конфиги должны быть отозваны заранее вызывающей стороной.
Task DeleteUserAsync(Guid userId, CancellationToken cancellationToken);
/// Для агрегированной подписки /sub/{userToken} (все активные конфиги пользователя).
Task FindUserIdBySubscriptionTokenAsync(
string token,
CancellationToken cancellationToken
);
/// Блокировка: вход запрещён (см. ValidateCredentialsAsync). Конфиги гасит вызывающая сторона.
Task BlockUserAsync(Guid userId, CancellationToken cancellationToken);
Task UnblockUserAsync(Guid userId, CancellationToken cancellationToken);
/// Сброс пароля админом — для пользователей без привязанного Telegram (M7).
Task ResetPasswordAsync(
Guid userId,
string newPassword,
CancellationToken cancellationToken
);
Task> ListUsersAsync(
int page,
int pageSize,
string? search,
CancellationToken cancellationToken
);
Task GetUserStatsAsync(CancellationToken cancellationToken);
Task LinkTelegramAsync(
Guid userId,
long telegramUserId,
string? telegramUsername,
CancellationToken cancellationToken
);
Task UnlinkTelegramAsync(Guid userId, CancellationToken cancellationToken);
Task FindUserIdByTelegramUserIdAsync(
long telegramUserId,
CancellationToken cancellationToken
);
Task GetTelegramLinkInfoAsync(
Guid userId,
CancellationToken cancellationToken
);
/// Telegram ID активных (активированных, не заблокированных) пользователей с привязкой —
/// для рассылки уведомлений вроде публикации новости.
Task> GetActivatedLinkedTelegramUserIdsAsync(
CancellationToken cancellationToken
);
/// Все Id пользователей, кроме указанного — для полного сброса панели (сохраняется
/// только текущий админ).
Task> ListAllUserIdsExceptAsync(
Guid exceptUserId,
CancellationToken cancellationToken
);
/// Пользователи с billing-ролью (role.BillingEnabled), не заблокированные — обход для
/// BillingService (приостановка за неуплату / предупреждения).
Task> ListBillingUsersAsync(CancellationToken cancellationToken);
/// Гасит конфиги за неуплату на уровне пользователя (BillingSuspended=true) — сами
/// конфиги гасит вызывающая сторона (см. BillingService, по образцу BlockUserCommandHandler).
Task SuspendBillingAsync(Guid userId, CancellationToken cancellationToken);
/// Продлевает оплаченный период, снимает приостановку и сбрасывает флаг "предупреждение
/// отправлено" (новый срок ещё не близко к истечению). Используется и при подтверждении оплаты,
/// и при первичной выдаче грейс-периода.
Task ExtendBillingPaidUntilAsync(
Guid userId,
DateTimeOffset paidUntil,
CancellationToken cancellationToken
);
Task MarkBillingWarningSentAsync(
Guid userId,
DateTimeOffset paidUntil,
CancellationToken cancellationToken
);
}