--- title: User Admin Feature --- ::: info When using ASP.NET Core **Identity Auth** refer to [Identity Auth Admin Users UI](/admin-ui-identity-users) instead ::: The User Admin Plugin is a lightweight API for providing user management functionality around Auth Repository APIs and enables remote programmatic access to manage your registered [User Auth Repository](/auth/authentication-and-authorization#user-auth-repository), featuring: - Works with existing `IUserAuthRepository` sync or async providers - Utilizes Progressive enhancement, e.g. search functionality utilizes `IQueryUserAuth` (if exists) performing a wildcard search over multiple fields, otherwise falls back to exact match on `UserName` or `Email` - Supports managing Auth Repositories utilizing custom `UserAuth` data models - Flexible UI options for customizing which fields to include in Search Results and Create/Edit UIs - Rich Metadata aggregating only App-specific Roles & Permissions defined in your App - User Events allow you to execute custom logic before & after each Created/Updated/Deleted User ### Installation The `AdminUsersFeature` plugin contains no additional dependencies that at a minimum can be registered with: ```csharp Plugins.Add(new AdminUsersFeature()); ```

/admin-ui/users

::: info An `IAuthRepository` is a required registered dependency to be able to use the `AdminUsersFeature` plugin. ::: ## Managing Users By default, the Add and Edit Users forms contains the default layout of common properties in [UserAuth.cs](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Auth/UserAuth.cs)
## Customization To customize this user interface to accommodate custom properties, the `UserFormLayout` needs to be overridden. For example, below we have a custom `UserAuth` called `AppUser` with additional properties. ```csharp // Custom User Table with extended Metadata properties public class AppUser : UserAuth { public Department Department { get; set; } public string? ProfileUrl { get; set; } public string? LastLoginIp { get; set; } public bool IsArchived { get; set; } public DateTime? ArchivedDate { get; set; } public DateTime? LastLoginDate { get; set; } } public enum Department { None, Marketing, Accounts, Legal, HumanResources, } ``` The `AdminUsersFeature` has multiple fiends that can be used to customize the UI including. | Property Name | Description | |---------------------------|--------------------------------------------------------------------| | `QueryUserAuthProperties` | Columns visible in query results for users. | | `QueryMediaRules` | Which columns *start* appearing at different screen sizes. | | `UserFormLayout` | Control which fields are used for Create/Edit and their placement. | ### Custom User Form Layout Similar to the [API Explorer](./api-explorer.md#formlayout) `FormLayout` customization, `UserFormLayout` is used to control placement and details about individual fields. ```csharp appHost.Plugins.Add(new ServiceStack.Admin.AdminUsersFeature { // Show custom fields in Search Results QueryUserAuthProperties = new() { nameof(AppUser.Id), nameof(AppUser.Email), nameof(AppUser.DisplayName), nameof(AppUser.Department), nameof(AppUser.CreatedDate), nameof(AppUser.LastLoginDate), }, QueryMediaRules = new() { MediaRules.ExtraSmall.Show(x => new { x.Id, x.Email, x.DisplayName }), MediaRules.Small.Show(x => x.Department), }, // Add Custom Fields to Create/Edit User Forms FormLayout = new() { Input.For(x => x.Email, x => x.Type = Input.Types.Email), Input.For(x => x.DisplayName), Input.For(x => x.UserName), Input.For(x => x.Company, c => c.FieldsPerRow(2)), Input.For(x => x.Department, c => c.FieldsPerRow(2)), Input.For(x => x.PhoneNumber, c => c.Type = Input.Types.Tel), Input.For(x => x.Nickname, c => { c.Help = "Public alias (3-12 lower alpha numeric chars)"; c.Pattern = "^[a-z][a-z0-9_.-]{3,12}$"; }), Input.For(x => x.ProfileUrl, c => c.Type = Input.Types.Url), Input.For(x => x.IsArchived, c => c.FieldsPerRow(2)), Input.For(x => x.ArchivedDate, c => c.FieldsPerRow(2)), } }); ``` Enabling the use of custom properties as well as formatting for ease of use. `UserFormLayout` updates the `Create` and `Edit` screens in the Admin UI. ## Admin User Services The Admin User back-end APIs themselves can also be used to manage users within your own Apps. All the Admin Users DTOs below contains everything needed to call its APIs from [.NET Service Clients](/csharp-client) which are all contained within **ServiceStack.Client** so no additional dependencies are needed. The APIs are fairly straight-forward with each DTO containing on the bare minimum Typed properties with all other UserAuth fields you want updated in the `UserAuthProperties` Dictionary. Whilst all User result-sets are returned in an unstructured Object Dictionary. ```csharp public abstract class AdminUserBase : IMeta { public string UserName { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string DisplayName { get; set; } public string Email { get; set; } public string Password { get; set; } public string ProfileUrl { get; set; } public Dictionary UserAuthProperties { get; set; } public Dictionary Meta { get; set; } } public partial class AdminCreateUser : AdminUserBase, IPost, IReturn { public List Roles { get; set; } public List Permissions { get; set; } } public partial class AdminUpdateUser : AdminUserBase, IPut, IReturn { public string Id { get; set; } public bool? LockUser { get; set; } public bool? UnlockUser { get; set; } public List AddRoles { get; set; } public List RemoveRoles { get; set; } public List AddPermissions { get; set; } public List RemovePermissions { get; set; } } public partial class AdminGetUser : IGet, IReturn { public string Id { get; set; } } public partial class AdminDeleteUser : IDelete, IReturn { public string Id { get; set; } } public class AdminDeleteUserResponse : IHasResponseStatus { public string Id { get; set; } public ResponseStatus ResponseStatus { get; set; } } public partial class AdminUserResponse : IHasResponseStatus { public string Id { get; set; } public Dictionary Result { get; set; } public ResponseStatus ResponseStatus { get; set; } } public partial class AdminQueryUsers : IGet, IReturn { public string Query { get; set; } public string OrderBy { get; set; } public int? Skip { get; set; } public int? Take { get; set; } } public class AdminUsersResponse : IHasResponseStatus { public List> Results { get; set; } public ResponseStatus ResponseStatus { get; set; } } ```