MyBookmark/Modules.User.WebApi/Controllers/UsersController.cs

469 lines
15 KiB
C#

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Modules.User.Application;
using Modules.User.Application.Commands;
using Modules.User.Application.Queries;
using Modules.User.WebApi.Models;
using System.Net;
using Modules.User.Api.Models;
using Modules.User.Application.Commands.User;
using Modules.User.Application.Commands.User.Access;
using Modules.User.Application.Commands.User.Ban;
using Modules.User.Application.Commands.User.PersonalData;
using Modules.User.Application.Commands.User.Session;
using Modules.User.Application.Queries.User;
using Modules.User.WebApi.Models.User.Access;
namespace Modules.User.WebApi.Controllers;
[ApiController]
[Route("[controller]")]
[ProducesResponseType(400, StatusCode = 400, Type = typeof(ProblemDetails))]
[ProducesResponseType(401, StatusCode = 401, Type = typeof(UnauthorizedResult))]
[Authorize]
public class UserController : ControllerBase
{
private readonly IMediator _mediator;
private readonly ILogger<UserController> _logger;
public UserController(IMediator mediator, ILogger<UserController> logger)
{
_mediator = mediator;
_logger = logger;
}
[HttpPost("Login")]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(AuthenticationResultModel))]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginModel model)
{
var loginResult = await _mediator.Send(new LoginCommand
{
Email = model.Login,
Password = model.Password,
IsAdmin = false,
Ip = model.Ip,
Response = Response,
//CookiePath = "Account/Refresh",
CookiePath = "/",
});
return Ok(new AuthenticationResultModel
{
AccessToken = loginResult.AccessToken,
SessionExpireDate = loginResult.SessionExpireDate.ToString("O"),
});
}
[HttpPost("Refresh")]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(AuthenticationResultModel))]
[AllowAnonymous]
public async Task<IActionResult> Refresh(RefreshModel model)
{
var refreshResult = await _mediator.Send(new RefreshTokensCommand
{
Ip = model.Ip,
Response = Response,
//CookiePath = "Account/Refresh",
CookiePath = "/",
});
//if (tokens != null)
//{
// return Ok(tokens.Value.AccessToken);
//}
//else
//{
// return Unauthorized();
//}
return refreshResult == null ? Unauthorized() : Ok(new AuthenticationResultModel
{
AccessToken = refreshResult.AccessToken,
SessionExpireDate = refreshResult.SessionExpireDate.ToString("O"),
});
//return tokens == null ? Unauthorized() : Ok(new TokensModel
//{
// AccessToken = tokens.Value.AccessToken,
// RefreshToken = tokens.Value.RefreshToken,
//});
}
[HttpPost("Register")]
[AllowAnonymous]
public async Task Register(RegisterModel model)
{
var token = await _mediator.Send(new CreateUserCommand
{
Nickname = model.Nickname,
Email = model.Login,
Password = model.Password,
//IsAdmin = false,
});
}
#region Sessions
[HttpGet("sessions")]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(List<Session>))]
public async Task<IActionResult> GetSessions()
{
var sessions = await _mediator.Send(new GetAccountSessionsQuery());
return Ok(sessions.Select(q => new Session
{
Id = q.Id,
IsCurrentSession = q.IsCurrentSession,
Country = q.ClientInfo.Location.Country,
Region = q.ClientInfo.Location.Region,
OnlineStatus = q.OnlineStatus switch
{
Application.Models.UserOnlineStatus.Online => UserOnlineStatus.Online,
Application.Models.UserOnlineStatus.Away => UserOnlineStatus.Away,
Application.Models.UserOnlineStatus.Offline => UserOnlineStatus.Offline,
_ => UserOnlineStatus.Unknown,
},
LastOnline = q.LastOnline,
//Latitude = q.ClientInfo.Location.Latitude,
//Longitude = q.ClientInfo.Location.Longutude,
UserAgent = q.ClientInfo.UserAgent,
ExpiredDate = q.ExpiredDate,
}));
}
[HttpDelete("sessions/{id:guid}")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
public async Task<IActionResult> DeleteSession(Guid id)
{
try
{
await _mediator.Send(new DeleteSessionCommand
{
SessionId = id,
});
return Ok();
}
catch (UnauthorizedAccessException ex)
{
//TODO: log
return Unauthorized();
}
}
[HttpDelete("sessions/current")]
public async Task<IActionResult> DeleteCurrentSession()
{
try
{
await _mediator.Send(new DeleteCurrentSessionCommand());
return Ok();
}
catch (UnauthorizedAccessException ex)
{
//TODO: log
return Unauthorized();
}
}
[HttpDelete("sessions/all")]
public async Task<IActionResult> DeleteAllSessions()
{
try
{
await _mediator.Send(new DeleteAllSessionsCommand());
return Ok();
}
catch (UnauthorizedAccessException ex)
{
//TODO: log
return Unauthorized();
}
}
#endregion
#region Access
[HttpPost("ban")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> BanUser(AccountBanModel model, CancellationToken cancellationToken)
{
await _mediator.Send(new BanAccountCommand
{
AccountId = model.AccountId,
Reason = model.Reason,
ExpiresAtUtc = model.ExpiresAtUtc,
}, cancellationToken);
return Ok();
}
[HttpPost("unban")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> UnbanUser(AccountUnbanModel model, CancellationToken cancellationToken)
{
await _mediator.Send(new UnbanAccountCommand()
{
AccountId = model.AccountId,
Reason = model.Reason,
}, cancellationToken);
return Ok();
}
[HttpPost("{id:guid}/role/assign")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> AssignRoleToUser(Guid id, RoleAssignModel model, CancellationToken cancellationToken)
{
await _mediator.Send(new RoleAssignToUserCommand
{
AccountId = id,
RoleId = model.RoleId,
AssignReason = model.AssignReason,
}, cancellationToken);
return Ok();
}
[HttpPost("{id:guid}/role/revoke")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> RevokeRoleFromUser(Guid id, RoleRevokeModel model, CancellationToken cancellationToken)
{
await _mediator.Send(new RoleRevokeFromUserCommand()
{
AccountId = id,
RoleId = model.RoleId,
RevokeReason = model.RevokeReason,
}, cancellationToken);
return Ok();
}
[HttpPost("{id:guid}/permission/assign")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> GrantPermissionToUser(Guid id, PermissionGrantModel model, CancellationToken cancellationToken)
{
await _mediator.Send(new PermissionGrantToUserCommand()
{
AccountId = id,
PermissionId = model.PermissionId,
GrantReason = model.GrantReason,
}, cancellationToken);
return Ok();
}
[HttpPost("{id:guid}/permission/revoke")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> RevokePermissionFromUser(Guid id, PermissionRevokeModel model, CancellationToken cancellationToken)
{
await _mediator.Send(new PermissionRevokeFromUserCommand()
{
AccountId = id,
PermissionId = model.PermissionId,
RevokeReason = model.RevokeReason,
}, cancellationToken);
return Ok();
}
#endregion
[HttpGet("list")]
public async Task<PagedData<UserInfoShort>> GetUsers(bool? hasAvatar, string? nickName,
DateTimeOffset? lastOnlineFrom = null, DateTimeOffset? lastOnlineTo = null,
bool? isBanned = null, int page = 1, int itemsOnPage = 10)
{
var usersPaged = await _mediator.Send(new GetUserListQuery()
{
HasAvatar = hasAvatar,
NickName = nickName,
LastOnlineFrom = lastOnlineFrom,
LastOnlineTo = lastOnlineTo,
IsBanned = isBanned,
ItemsOnPage = itemsOnPage,
Page = page,
});
return new PagedData<UserInfoShort>
{
PagesCount = usersPaged.PagesCount,
Page = usersPaged.Page,
ItemsOnPage = usersPaged.ItemsOnPage,
ItemsCount = usersPaged.ItemsCount,
Items = usersPaged.Items.Select(q => new UserInfoShort
{
Id = q.Id,
NickName = q.NickName,
FirstName = q.FirstName,
Patronymic = q.Patronymic,
LastName = q.LastName,
Email = q.Email,
HasAvatar = q.HasAvatar,
BirthDate = q.BirthDate,
LanguageId = q.LanguageId,
OnlineStatus = q.OnlineStatus switch
{
Application.Models.UserOnlineStatus.Online => UserOnlineStatus.Online,
Application.Models.UserOnlineStatus.Away => UserOnlineStatus.Away,
Application.Models.UserOnlineStatus.Offline => UserOnlineStatus.Offline,
_ => UserOnlineStatus.Unknown,
},
LastOnline = q.LastOnline,
BanStatus = new BanStatus(q.BanStatus.IsBanned, q.BanStatus.BannedUntil),
// Roles = q.roles
})
};
}
// [HttpGet("UserAvatar")]
// [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(FileStreamResult))]
// [AllowAnonymous]
// public async Task<IActionResult> GetUserAvatar(string userId)
// {
// if (!string.IsNullOrEmpty(objectId))
// {
// var media = await _mediator.Send(new GetUserAvatarQuery
// {
// ObjectId = objectId,
// });
// if (media == null)
// {
// return NotFound();
// }
// else
// {
// return new FileStreamResult(media.Data, media.ContentType);
// }
// }
// else
// {
// return NotFound();
// }
// }
// [HttpGet]
// [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(UserInfo))]
// public async Task<IActionResult> GetUser()
// {
// var user = await _userContext.GetUserInfo();
// if (user?.Id == null) return NotFound();
// return Ok(new UserInfo
// {
// Id = user.Id,
// AccountId = user.AccountId,
// SessionId = user.SessionId,
// NickName = user.NickName,
// FirstName = user.FirstName,
// Patronymic = user.Patronymic,
// LastName = user.LastName,
// BirthDate = user.BirthDate,
// LanguageId = user.LanguageId,
// Email = user.Email,
// IsAuthenticated = user.IsAuthenticated,
// OnlineStatus = UserOnlineStatus.Online,
// });
// }
[HttpGet("Id")]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(UserInfo))]
public async Task<IActionResult> GetUserId(CancellationToken cancellationToken)
{
return Ok(await _mediator.Send(new GetUserIdQuery(), cancellationToken));
}
[AllowAnonymous]
[HttpGet("Avatar")]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(FileStreamResult))]
public async Task<IActionResult> GetAvatar([FromQuery]Guid userId)
{
var avatar = await _mediator.Send(new GetUserAvatarQuery { UserId = userId });
if (avatar == null)
{
return NotFound();
}
else
{
return new FileStreamResult(avatar.Data, avatar.ContentType);
}
}
[HttpPost("SetAvatar")]
[ProducesResponseType((int)HttpStatusCode.OK)]
public async Task<IActionResult> SetAvatar(IFormFile file)
{
if (file.Length == 0) return BadRequest("File is empty.");
await using var stream = file.OpenReadStream();
await _mediator.Send(new SetUserAvatarCommand
{
ContentType = file.ContentType,
Extension = Path.GetExtension(file.FileName),
Data = stream,
});
return Ok();
}
[HttpPost("DeleteAvatar")]
[ProducesResponseType((int)HttpStatusCode.OK)]
public async Task<IActionResult> DeleteAvatar()
{
await _mediator.Send(new DeleteUserAvatarCommand());
return Ok();
}
/*
public string? NickName { get; set; } = default!;
public string? FirstName { get; set; }
public string? Patronymic { get; set; }
public string? LastName { get; set; }
public Guid? LanguageId { get; set; }
*/
[HttpPost("SetUserInformation")]
[ProducesResponseType((int)HttpStatusCode.OK)]
public async Task<IActionResult> SetUserInformation(UserInformationEditModel model)
{
await _mediator.Send(new SetUserNameCommand
{
FirstName = model.FirstName,
Patronymic = model.Patronymic,
LastName = model.LastName,
});
return Ok();
}
[HttpPost("SetBirthDate")]
[ProducesResponseType((int)HttpStatusCode.OK)]
public async Task<IActionResult> SetBirthDate(BirthDateEditModel model)
{
await _mediator.Send(new SetUserBirthDateCommand
{
BirthDate = model.BirthDate,
});
return Ok();
}
[HttpPost("SetLanguage")]
[ProducesResponseType((int)HttpStatusCode.OK)]
public async Task<IActionResult> SetLanguage(LanguageEditModel model)
{
await _mediator.Send(new SetUserLanguageCommand
{
LanguageId = model.LanguageId,
});
return Ok();
}
}