2020-06-19 12:11:46 -04:00
using System ;
2020-06-17 15:08:58 -04:00
using System.Collections.Generic ;
using System.ComponentModel.DataAnnotations ;
using System.Linq ;
using System.Threading.Tasks ;
using Jellyfin.Api.Constants ;
2020-06-18 12:09:58 -04:00
using Jellyfin.Api.Helpers ;
using Jellyfin.Api.Models.UserDtos ;
2020-06-17 15:08:58 -04:00
using Jellyfin.Data.Enums ;
using MediaBrowser.Common.Net ;
using MediaBrowser.Controller.Authentication ;
using MediaBrowser.Controller.Configuration ;
using MediaBrowser.Controller.Devices ;
using MediaBrowser.Controller.Library ;
using MediaBrowser.Controller.Net ;
using MediaBrowser.Controller.Session ;
2020-06-18 12:09:58 -04:00
using MediaBrowser.Model.Configuration ;
2020-06-17 15:08:58 -04:00
using MediaBrowser.Model.Dto ;
using MediaBrowser.Model.Users ;
using Microsoft.AspNetCore.Authorization ;
2020-06-18 12:09:58 -04:00
using Microsoft.AspNetCore.Http ;
2020-06-17 15:08:58 -04:00
using Microsoft.AspNetCore.Mvc ;
using Microsoft.AspNetCore.Mvc.ModelBinding ;
namespace Jellyfin.Api.Controllers
{
/// <summary>
/// User controller.
/// </summary>
2020-08-04 10:27:54 -04:00
[Route("Users")]
2020-06-17 15:08:58 -04:00
public class UserController : BaseJellyfinApiController
{
private readonly IUserManager _userManager ;
private readonly ISessionManager _sessionManager ;
private readonly INetworkManager _networkManager ;
private readonly IDeviceManager _deviceManager ;
private readonly IAuthorizationContext _authContext ;
private readonly IServerConfigurationManager _config ;
/// <summary>
/// Initializes a new instance of the <see cref="UserController"/> class.
/// </summary>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
/// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
public UserController (
IUserManager userManager ,
ISessionManager sessionManager ,
INetworkManager networkManager ,
IDeviceManager deviceManager ,
IAuthorizationContext authContext ,
IServerConfigurationManager config )
{
_userManager = userManager ;
_sessionManager = sessionManager ;
_networkManager = networkManager ;
_deviceManager = deviceManager ;
_authContext = authContext ;
_config = config ;
}
/// <summary>
/// Gets a list of users.
/// </summary>
/// <param name="isHidden">Optional filter by IsHidden=true or false.</param>
/// <param name="isDisabled">Optional filter by IsDisabled=true or false.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">Users returned.</response>
/// <returns>An <see cref="IEnumerable{UserDto}"/> containing the users.</returns>
2020-06-17 15:08:58 -04:00
[HttpGet]
2020-06-22 09:44:11 -04:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
2020-06-17 15:08:58 -04:00
public ActionResult < IEnumerable < UserDto > > GetUsers (
[FromQuery] bool? isHidden ,
2020-06-24 16:43:28 -04:00
[FromQuery] bool? isDisabled )
2020-06-17 15:08:58 -04:00
{
2020-06-18 12:09:58 -04:00
var users = Get ( isHidden , isDisabled , false , false ) ;
return Ok ( users ) ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Gets a list of publicly visible users for display on a login screen.
/// </summary>
2020-06-18 12:09:58 -04:00
/// <response code="200">Public users returned.</response>
/// <returns>An <see cref="IEnumerable{UserDto}"/> containing the public users.</returns>
2020-06-17 15:08:58 -04:00
[HttpGet("Public")]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
2020-06-17 15:08:58 -04:00
public ActionResult < IEnumerable < UserDto > > GetPublicUsers ( )
{
// If the startup wizard hasn't been completed then just return all users
if ( ! _config . Configuration . IsStartupWizardCompleted )
{
2020-06-19 12:11:46 -04:00
return Ok ( Get ( false , false , false , false ) ) ;
2020-06-17 15:08:58 -04:00
}
2020-06-18 12:09:58 -04:00
return Ok ( Get ( false , false , true , true ) ) ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Gets a user by Id.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">User returned.</response>
/// <response code="404">User not found.</response>
/// <returns>An <see cref="UserDto"/> with information about the user or a <see cref="NotFoundResult"/> if the user was not found.</returns>
2020-06-20 20:02:07 -04:00
[HttpGet("{userId}")]
2020-06-18 13:35:29 -04:00
[Authorize(Policy = Policies.IgnoreSchedule)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
2020-06-20 20:02:07 -04:00
public ActionResult < UserDto > GetUserById ( [ FromRoute ] Guid userId )
2020-06-17 15:08:58 -04:00
{
2020-06-20 20:02:07 -04:00
var user = _userManager . GetUserById ( userId ) ;
2020-06-17 15:08:58 -04:00
if ( user = = null )
{
2020-06-18 12:09:58 -04:00
return NotFound ( "User not found" ) ;
2020-06-17 15:08:58 -04:00
}
var result = _userManager . GetUserDto ( user , HttpContext . Connection . RemoteIpAddress . ToString ( ) ) ;
2020-06-19 12:11:46 -04:00
return result ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Deletes a user.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">User deleted.</response>
/// <response code="404">User not found.</response>
/// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="NotFoundResult"/> if the user was not found.</returns>
2020-06-20 20:02:07 -04:00
[HttpDelete("{userId}")]
2020-06-17 15:08:58 -04:00
[Authorize(Policy = Policies.RequiresElevation)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
2020-06-20 20:02:07 -04:00
public ActionResult DeleteUser ( [ FromRoute ] Guid userId )
2020-06-17 15:08:58 -04:00
{
2020-06-20 20:02:07 -04:00
var user = _userManager . GetUserById ( userId ) ;
2020-06-17 15:08:58 -04:00
_sessionManager . RevokeUserTokens ( user . Id , null ) ;
2020-07-20 16:43:54 -04:00
_userManager . DeleteUser ( userId ) ;
2020-06-17 15:08:58 -04:00
return NoContent ( ) ;
}
/// <summary>
/// Authenticates a user.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 12:09:58 -04:00
/// <param name="pw">The password as plain text.</param>
/// <param name="password">The password sha1-hash.</param>
/// <response code="200">User authenticated.</response>
/// <response code="403">Sha1-hashed password only is not allowed.</response>
/// <response code="404">User not found.</response>
/// <returns>A <see cref="Task"/> containing an <see cref="AuthenticationResult"/>.</returns>
2020-06-20 20:02:07 -04:00
[HttpPost("{userId}/Authenticate")]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
2020-06-17 15:08:58 -04:00
public async Task < ActionResult < AuthenticationResult > > AuthenticateUser (
2020-06-20 20:02:07 -04:00
[FromRoute, Required] Guid userId ,
2020-06-27 12:50:44 -04:00
[FromQuery, BindRequired] string? pw ,
[FromQuery, BindRequired] string? password )
2020-06-17 15:08:58 -04:00
{
2020-06-20 20:02:07 -04:00
var user = _userManager . GetUserById ( userId ) ;
2020-06-17 15:08:58 -04:00
if ( user = = null )
{
return NotFound ( "User not found" ) ;
}
if ( ! string . IsNullOrEmpty ( password ) & & string . IsNullOrEmpty ( pw ) )
{
2020-06-18 12:09:58 -04:00
return Forbid ( "Only sha1 password is not allowed." ) ;
2020-06-17 15:08:58 -04:00
}
// Password should always be null
2020-06-18 13:35:29 -04:00
AuthenticateUserByName request = new AuthenticateUserByName
{
Username = user . Username ,
Password = null ,
Pw = pw
} ;
return await AuthenticateUserByName ( request ) . ConfigureAwait ( false ) ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Authenticates a user by name.
/// </summary>
2020-06-18 12:09:58 -04:00
/// <param name="request">The <see cref="AuthenticateUserByName"/> request.</param>
/// <response code="200">User authenticated.</response>
/// <returns>A <see cref="Task"/> containing an <see cref="AuthenticationRequest"/> with information about the new session.</returns>
2020-06-17 15:08:58 -04:00
[HttpPost("AuthenticateByName")]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task < ActionResult < AuthenticationResult > > AuthenticateUserByName ( [ FromBody , BindRequired ] AuthenticateUserByName request )
2020-06-17 15:08:58 -04:00
{
var auth = _authContext . GetAuthorizationInfo ( Request ) ;
try
{
var result = await _sessionManager . AuthenticateNewSession ( new AuthenticationRequest
{
App = auth . Client ,
AppVersion = auth . Version ,
DeviceId = auth . DeviceId ,
DeviceName = auth . Device ,
2020-06-18 12:09:58 -04:00
Password = request . Pw ,
PasswordSha1 = request . Password ,
2020-06-17 15:08:58 -04:00
RemoteEndPoint = HttpContext . Connection . RemoteIpAddress . ToString ( ) ,
2020-06-18 12:09:58 -04:00
Username = request . Username
2020-06-17 15:08:58 -04:00
} ) . ConfigureAwait ( false ) ;
2020-06-19 12:11:46 -04:00
return result ;
2020-06-17 15:08:58 -04:00
}
catch ( SecurityException e )
{
// rethrow adding IP address to message
throw new SecurityException ( $"[{HttpContext.Connection.RemoteIpAddress}] {e.Message}" , e ) ;
}
}
/// <summary>
/// Updates a user's password.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 13:35:29 -04:00
/// <param name="request">The <see cref="UpdateUserPassword"/> request.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">Password successfully reset.</response>
/// <response code="403">User is not allowed to update the password.</response>
/// <response code="404">User not found.</response>
/// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="ForbidResult"/> or a <see cref="NotFoundResult"/> on failure.</returns>
2020-06-20 20:02:07 -04:00
[HttpPost("{userId}/Password")]
2020-06-22 09:44:11 -04:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
2020-06-17 15:08:58 -04:00
public async Task < ActionResult > UpdateUserPassword (
2020-06-20 20:02:07 -04:00
[FromRoute] Guid userId ,
2020-06-18 13:35:29 -04:00
[FromBody] UpdateUserPassword request )
2020-06-17 15:08:58 -04:00
{
2020-06-20 20:02:07 -04:00
if ( ! RequestHelpers . AssertCanUpdateUser ( _authContext , HttpContext . Request , userId , true ) )
2020-06-18 12:09:58 -04:00
{
return Forbid ( "User is not allowed to update the password." ) ;
}
2020-06-17 15:08:58 -04:00
2020-06-20 20:02:07 -04:00
var user = _userManager . GetUserById ( userId ) ;
2020-06-17 15:08:58 -04:00
if ( user = = null )
{
return NotFound ( "User not found" ) ;
}
2020-06-18 13:35:29 -04:00
if ( request . ResetPassword )
2020-06-17 15:08:58 -04:00
{
await _userManager . ResetPassword ( user ) . ConfigureAwait ( false ) ;
}
else
{
var success = await _userManager . AuthenticateUser (
user . Username ,
2020-06-18 13:35:29 -04:00
request . CurrentPw ,
request . CurrentPw ,
2020-06-17 15:08:58 -04:00
HttpContext . Connection . RemoteIpAddress . ToString ( ) ,
false ) . ConfigureAwait ( false ) ;
if ( success = = null )
{
2020-06-18 12:09:58 -04:00
return Forbid ( "Invalid user or password entered." ) ;
2020-06-17 15:08:58 -04:00
}
2020-06-18 13:35:29 -04:00
await _userManager . ChangePassword ( user , request . NewPw ) . ConfigureAwait ( false ) ;
2020-06-17 15:08:58 -04:00
var currentToken = _authContext . GetAuthorizationInfo ( Request ) . Token ;
_sessionManager . RevokeUserTokens ( user . Id , currentToken ) ;
}
return NoContent ( ) ;
}
/// <summary>
/// Updates a user's easy password.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 13:35:29 -04:00
/// <param name="request">The <see cref="UpdateUserEasyPassword"/> request.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">Password successfully reset.</response>
/// <response code="403">User is not allowed to update the password.</response>
/// <response code="404">User not found.</response>
/// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="ForbidResult"/> or a <see cref="NotFoundResult"/> on failure.</returns>
2020-06-20 20:02:07 -04:00
[HttpPost("{userId}/EasyPassword")]
2020-06-22 09:44:11 -04:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
2020-06-17 15:08:58 -04:00
public ActionResult UpdateUserEasyPassword (
2020-06-20 20:02:07 -04:00
[FromRoute] Guid userId ,
2020-06-18 13:35:29 -04:00
[FromBody] UpdateUserEasyPassword request )
2020-06-17 15:08:58 -04:00
{
2020-06-20 20:02:07 -04:00
if ( ! RequestHelpers . AssertCanUpdateUser ( _authContext , HttpContext . Request , userId , true ) )
2020-06-18 12:09:58 -04:00
{
return Forbid ( "User is not allowed to update the easy password." ) ;
}
2020-06-17 15:08:58 -04:00
2020-06-20 20:02:07 -04:00
var user = _userManager . GetUserById ( userId ) ;
2020-06-17 15:08:58 -04:00
if ( user = = null )
{
return NotFound ( "User not found" ) ;
}
2020-06-18 13:35:29 -04:00
if ( request . ResetPassword )
2020-06-17 15:08:58 -04:00
{
_userManager . ResetEasyPassword ( user ) ;
}
else
{
2020-06-18 13:35:29 -04:00
_userManager . ChangeEasyPassword ( user , request . NewPw , request . NewPassword ) ;
2020-06-17 15:08:58 -04:00
}
return NoContent ( ) ;
}
/// <summary>
/// Updates a user.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 12:09:58 -04:00
/// <param name="updateUser">The updated user model.</param>
/// <response code="204">User updated.</response>
/// <response code="400">User information was not supplied.</response>
/// <response code="403">User update forbidden.</response>
/// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="BadRequestResult"/> or a <see cref="ForbidResult"/> on failure.</returns>
2020-06-20 20:02:07 -04:00
[HttpPost("{userId}")]
2020-06-22 09:44:11 -04:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task < ActionResult > UpdateUser (
2020-06-20 20:02:07 -04:00
[FromRoute] Guid userId ,
2020-06-18 12:09:58 -04:00
[FromBody] UserDto updateUser )
2020-06-17 15:08:58 -04:00
{
2020-06-18 12:09:58 -04:00
if ( updateUser = = null )
{
return BadRequest ( ) ;
}
2020-06-20 20:02:07 -04:00
if ( ! RequestHelpers . AssertCanUpdateUser ( _authContext , HttpContext . Request , userId , false ) )
2020-06-18 12:09:58 -04:00
{
return Forbid ( "User update not allowed." ) ;
}
2020-06-20 20:02:07 -04:00
var user = _userManager . GetUserById ( userId ) ;
2020-06-18 12:09:58 -04:00
if ( string . Equals ( user . Username , updateUser . Name , StringComparison . Ordinal ) )
{
await _userManager . UpdateUserAsync ( user ) . ConfigureAwait ( false ) ;
_userManager . UpdateConfiguration ( user . Id , updateUser . Configuration ) ;
}
else
{
await _userManager . RenameUser ( user , updateUser . Name ) . ConfigureAwait ( false ) ;
_userManager . UpdateConfiguration ( updateUser . Id , updateUser . Configuration ) ;
}
return NoContent ( ) ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Updates a user policy.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 12:09:58 -04:00
/// <param name="newPolicy">The new user policy.</param>
/// <response code="204">User policy updated.</response>
/// <response code="400">User policy was not supplied.</response>
/// <response code="403">User policy update forbidden.</response>
/// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="BadRequestResult"/> or a <see cref="ForbidResult"/> on failure..</returns>
2020-06-20 20:02:07 -04:00
[HttpPost("{userId}/Policy")]
2020-06-22 09:44:11 -04:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public ActionResult UpdateUserPolicy (
2020-06-20 20:02:07 -04:00
[FromRoute] Guid userId ,
2020-06-18 12:09:58 -04:00
[FromBody] UserPolicy newPolicy )
2020-06-17 15:08:58 -04:00
{
2020-06-18 12:09:58 -04:00
if ( newPolicy = = null )
{
return BadRequest ( ) ;
}
2020-06-20 20:02:07 -04:00
var user = _userManager . GetUserById ( userId ) ;
2020-06-18 12:09:58 -04:00
// If removing admin access
if ( ! ( newPolicy . IsAdministrator & & user . HasPermission ( PermissionKind . IsAdministrator ) ) )
{
if ( _userManager . Users . Count ( i = > i . HasPermission ( PermissionKind . IsAdministrator ) ) = = 1 )
{
return Forbid ( "There must be at least one user in the system with administrative access." ) ;
}
}
// If disabling
if ( newPolicy . IsDisabled & & user . HasPermission ( PermissionKind . IsAdministrator ) )
{
return Forbid ( "Administrators cannot be disabled." ) ;
}
// If disabling
if ( newPolicy . IsDisabled & & ! user . HasPermission ( PermissionKind . IsDisabled ) )
{
if ( _userManager . Users . Count ( i = > ! i . HasPermission ( PermissionKind . IsDisabled ) ) = = 1 )
{
return Forbid ( "There must be at least one enabled user in the system." ) ;
}
var currentToken = _authContext . GetAuthorizationInfo ( Request ) . Token ;
_sessionManager . RevokeUserTokens ( user . Id , currentToken ) ;
}
2020-06-20 20:02:07 -04:00
_userManager . UpdatePolicy ( userId , newPolicy ) ;
2020-06-18 12:09:58 -04:00
return NoContent ( ) ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Updates a user configuration.
/// </summary>
2020-06-20 20:02:07 -04:00
/// <param name="userId">The user id.</param>
2020-06-18 12:09:58 -04:00
/// <param name="userConfig">The new user configuration.</param>
/// <response code="204">User configuration updated.</response>
/// <response code="403">User configuration update forbidden.</response>
2020-06-17 15:08:58 -04:00
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
2020-06-20 20:02:07 -04:00
[HttpPost("{userId}/Configuration")]
2020-06-22 09:44:11 -04:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public ActionResult UpdateUserConfiguration (
2020-06-20 20:02:07 -04:00
[FromRoute] Guid userId ,
2020-06-18 12:09:58 -04:00
[FromBody] UserConfiguration userConfig )
2020-06-17 15:08:58 -04:00
{
2020-06-20 20:02:07 -04:00
if ( ! RequestHelpers . AssertCanUpdateUser ( _authContext , HttpContext . Request , userId , false ) )
2020-06-18 12:09:58 -04:00
{
return Forbid ( "User configuration update not allowed" ) ;
}
2020-06-20 20:02:07 -04:00
_userManager . UpdateConfiguration ( userId , userConfig ) ;
2020-06-18 12:09:58 -04:00
return NoContent ( ) ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Creates a user.
/// </summary>
2020-06-18 13:35:29 -04:00
/// <param name="request">The create user by name request body.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">User created.</response>
/// <returns>An <see cref="UserDto"/> of the new user.</returns>
2020-08-04 14:48:53 -04:00
[HttpPost("New")]
2020-06-17 15:08:58 -04:00
[Authorize(Policy = Policies.RequiresElevation)]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
2020-06-18 13:35:29 -04:00
public async Task < ActionResult < UserDto > > CreateUserByName ( [ FromBody ] CreateUserByName request )
2020-06-17 15:08:58 -04:00
{
2020-08-03 14:01:24 -04:00
var newUser = await _userManager . CreateUserAsync ( request . Name ) . ConfigureAwait ( false ) ;
2020-06-17 15:08:58 -04:00
// no need to authenticate password for new user
2020-06-18 13:35:29 -04:00
if ( request . Password ! = null )
2020-06-17 15:08:58 -04:00
{
2020-06-18 13:35:29 -04:00
await _userManager . ChangePassword ( newUser , request . Password ) . ConfigureAwait ( false ) ;
2020-06-17 15:08:58 -04:00
}
var result = _userManager . GetUserDto ( newUser , HttpContext . Connection . RemoteIpAddress . ToString ( ) ) ;
2020-06-19 12:11:46 -04:00
return result ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Initiates the forgot password process for a local user.
/// </summary>
/// <param name="enteredUsername">The entered username.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">Password reset process started.</response>
/// <returns>A <see cref="Task"/> containing a <see cref="ForgotPasswordResult"/>.</returns>
2020-06-17 15:08:58 -04:00
[HttpPost("ForgotPassword")]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
2020-06-27 12:50:44 -04:00
public async Task < ActionResult < ForgotPasswordResult > > ForgotPassword ( [ FromBody ] string? enteredUsername )
2020-06-17 15:08:58 -04:00
{
var isLocal = HttpContext . Connection . RemoteIpAddress . Equals ( HttpContext . Connection . LocalIpAddress )
| | _networkManager . IsInLocalNetwork ( HttpContext . Connection . RemoteIpAddress . ToString ( ) ) ;
var result = await _userManager . StartForgotPasswordProcess ( enteredUsername , isLocal ) . ConfigureAwait ( false ) ;
2020-06-19 12:11:46 -04:00
return result ;
2020-06-17 15:08:58 -04:00
}
/// <summary>
/// Redeems a forgot password pin.
/// </summary>
/// <param name="pin">The pin.</param>
2020-06-18 12:09:58 -04:00
/// <response code="200">Pin reset process started.</response>
/// <returns>A <see cref="Task"/> containing a <see cref="PinRedeemResult"/>.</returns>
2020-06-17 15:08:58 -04:00
[HttpPost("ForgotPassword/Pin")]
2020-06-18 12:09:58 -04:00
[ProducesResponseType(StatusCodes.Status200OK)]
2020-06-27 12:50:44 -04:00
public async Task < ActionResult < PinRedeemResult > > ForgotPasswordPin ( [ FromBody ] string? pin )
2020-06-17 15:08:58 -04:00
{
var result = await _userManager . RedeemPasswordResetPin ( pin ) . ConfigureAwait ( false ) ;
2020-06-19 12:11:46 -04:00
return result ;
2020-06-17 15:08:58 -04:00
}
2020-06-18 12:09:58 -04:00
private IEnumerable < UserDto > Get ( bool? isHidden , bool? isDisabled , bool filterByDevice , bool filterByNetwork )
2020-06-17 15:08:58 -04:00
{
var users = _userManager . Users ;
if ( isDisabled . HasValue )
{
users = users . Where ( i = > i . HasPermission ( PermissionKind . IsDisabled ) = = isDisabled . Value ) ;
}
if ( isHidden . HasValue )
{
users = users . Where ( i = > i . HasPermission ( PermissionKind . IsHidden ) = = isHidden . Value ) ;
}
if ( filterByDevice )
{
var deviceId = _authContext . GetAuthorizationInfo ( Request ) . DeviceId ;
if ( ! string . IsNullOrWhiteSpace ( deviceId ) )
{
users = users . Where ( i = > _deviceManager . CanAccessDevice ( i , deviceId ) ) ;
}
}
if ( filterByNetwork )
{
if ( ! _networkManager . IsInLocalNetwork ( HttpContext . Connection . RemoteIpAddress . ToString ( ) ) )
{
users = users . Where ( i = > i . HasPermission ( PermissionKind . EnableRemoteAccess ) ) ;
}
}
var result = users
. OrderBy ( u = > u . Username )
2020-06-19 12:11:46 -04:00
. Select ( i = > _userManager . GetUserDto ( i , HttpContext . Connection . RemoteIpAddress . ToString ( ) ) ) ;
2020-06-17 15:08:58 -04:00
return result ;
}
}
}