Add complete role management functionality for tenant administrators to manage user roles within their tenants.
Changes:
- Extended IUserTenantRoleRepository with pagination, role counting, and last owner check methods
- Extended IUserRepository with GetByIdAsync(Guid) and GetByIdsAsync for flexible user retrieval
- Extended IRefreshTokenRepository with GetByUserAndTenantAsync and UpdateRangeAsync
- Implemented repository methods in Infrastructure layer
- Created DTOs: UserWithRoleDto and PagedResultDto<T>
- Implemented ListTenantUsersQuery with pagination support
- Implemented AssignUserRoleCommand to assign/update user roles
- Implemented RemoveUserFromTenantCommand with token revocation
- Created TenantUsersController with 4 endpoints (list, assign, remove, get-roles)
- Added comprehensive PowerShell test script
Security Features:
- Only TenantOwner can assign/update/remove roles
- Prevents removal of last TenantOwner (lockout protection)
- Prevents manual assignment of AIAgent role (reserved for MCP)
- Cross-tenant access protection
- Automatic refresh token revocation when user removed
API Endpoints:
- GET /api/tenants/{id}/users - List users with roles (paginated)
- POST /api/tenants/{id}/users/{userId}/role - Assign/update role
- DELETE /api/tenants/{id}/users/{userId} - Remove user from tenant
- GET /api/tenants/roles - Get available roles
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
72 lines
2.3 KiB
C#
72 lines
2.3 KiB
C#
using ColaFlow.Modules.Identity.Domain.Aggregates.Tenants;
|
|
using ColaFlow.Modules.Identity.Domain.Aggregates.Users;
|
|
|
|
namespace ColaFlow.Modules.Identity.Domain.Repositories;
|
|
|
|
/// <summary>
|
|
/// Repository interface for User aggregate
|
|
/// </summary>
|
|
public interface IUserRepository
|
|
{
|
|
/// <summary>
|
|
/// Get user by ID
|
|
/// </summary>
|
|
Task<User?> GetByIdAsync(UserId userId, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Get user by Guid ID
|
|
/// </summary>
|
|
Task<User?> GetByIdAsync(Guid userId, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Get multiple users by their IDs
|
|
/// </summary>
|
|
Task<IReadOnlyList<User>> GetByIdsAsync(
|
|
IEnumerable<Guid> userIds,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Get user by email within a tenant
|
|
/// </summary>
|
|
Task<User?> GetByEmailAsync(TenantId tenantId, Email email, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Get user by external SSO ID within a tenant
|
|
/// </summary>
|
|
Task<User?> GetByExternalIdAsync(
|
|
TenantId tenantId,
|
|
AuthenticationProvider provider,
|
|
string externalUserId,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Check if an email already exists within a tenant
|
|
/// </summary>
|
|
Task<bool> ExistsByEmailAsync(TenantId tenantId, Email email, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Get all users for a tenant
|
|
/// </summary>
|
|
Task<IReadOnlyList<User>> GetAllByTenantAsync(TenantId tenantId, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Get active users count for a tenant
|
|
/// </summary>
|
|
Task<int> GetActiveUsersCountAsync(TenantId tenantId, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Add a new user
|
|
/// </summary>
|
|
Task AddAsync(User user, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Update an existing user
|
|
/// </summary>
|
|
Task UpdateAsync(User user, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Delete a user (hard delete)
|
|
/// </summary>
|
|
Task DeleteAsync(User user, CancellationToken cancellationToken = default);
|
|
}
|