From 968f427531cc0d5e70e863ace0caac08756cbff3 Mon Sep 17 00:00:00 2001 From: Mikhail M <47109585+MikhailMasny@users.noreply.github.com> Date: Sat, 12 Sep 2020 02:33:26 +0300 Subject: [PATCH] refactor: code optimization --- .../Controllers/AccountsController.cs | 53 ++++++++++++++++++- .../Controllers/CalendarController.cs | 5 +- src/Masny.WebApi/Entities/RefreshToken.cs | 1 + .../WebServiceCollectionExtension.cs | 9 ---- src/Masny.WebApi/Helpers/AppException.cs | 8 ++- src/Masny.WebApi/Helpers/AppRoles.cs | 4 +- .../Helpers/AuthorizeAttribute.cs | 4 +- src/Masny.WebApi/Helpers/AutoMapperProfile.cs | 1 - src/Masny.WebApi/Helpers/Constants.cs | 2 + .../Interfaces/IAccountService.cs | 6 +-- .../Interfaces/ICalendarService.cs | 3 +- src/Masny.WebApi/Services/AccountService.cs | 3 +- src/Masny.WebApi/Services/EmailService.cs | 2 +- src/Masny.WebApi/Startup.cs | 2 - 14 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/Masny.WebApi/Controllers/AccountsController.cs b/src/Masny.WebApi/Controllers/AccountsController.cs index 6accd36..b8ee8a6 100644 --- a/src/Masny.WebApi/Controllers/AccountsController.cs +++ b/src/Masny.WebApi/Controllers/AccountsController.cs @@ -26,11 +26,14 @@ public AccountsController(IAccountService accountService) /// /// Login model. /// The operation was successful. + /// If the request has wrong data. + /// Internal server error by database. [HttpPost("authenticate")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> AuthenticateAsync(AuthenticateRequest model) { - // TODO: operation result + response AuthenticateResponse response = await _accountService.AuthenticateAsync(model); await SetTokenCookieAsync(response.RefreshToken); return Ok(response); @@ -40,8 +43,12 @@ public async Task> AuthenticateAsync(Authenti /// Refresh token. /// /// The operation was successful. + /// If the request has wrong data. + /// Internal server error by database. [HttpPost("refresh-token")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> RefreshTokenAsync() { var refreshToken = Request.Cookies["refreshToken"]; @@ -57,11 +64,13 @@ public async Task> RefreshTokenAsync() /// The operation was successful. /// If the request has wrong data. /// Unauthorized. + /// Internal server error by database. [Authorize] [HttpPost("revoke-token")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task RevokeTokenAsync(RevokeTokenRequest model) { var token = !string.IsNullOrEmpty(model.Token) @@ -87,8 +96,12 @@ public async Task RevokeTokenAsync(RevokeTokenRequest model) /// /// Registration model. /// The operation was successful. + /// If the request has wrong data. + /// Internal server error by database. [HttpPost("register")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task RegisterAsync(RegisterRequest model) { await _accountService.RegisterAsync(model, Request.Headers["origin"]); @@ -100,8 +113,12 @@ public async Task RegisterAsync(RegisterRequest model) /// /// Verify email model. /// The operation was successful. + /// If the request has wrong data. + /// Internal server error by database. [HttpPost("verify-email")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task VerifyEmailAsync(VerifyEmailRequest model) { await _accountService.VerifyEmailAsync(model.Token); @@ -113,8 +130,12 @@ public async Task VerifyEmailAsync(VerifyEmailRequest model) /// /// Forgot password model. /// The operation was successful. + /// If the request has wrong data. + /// Internal server error by database. [HttpPost("forgot-password")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task ForgotPasswordAsync(ForgotPasswordRequest model) { await _accountService.ForgotPasswordAsync(model, Request.Headers["origin"]); @@ -126,8 +147,12 @@ public async Task ForgotPasswordAsync(ForgotPasswordRequest model /// /// Validate reset token model. /// The operation was successful. + /// If the request has wrong data. + /// Internal server error by database. [HttpPost("validate-reset-token")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task ValidateResetTokenAsync(ValidateResetTokenRequest model) { await _accountService.ValidateResetTokenAsync(model); @@ -139,8 +164,12 @@ public async Task ValidateResetTokenAsync(ValidateResetTokenReque /// /// Reset password model. /// The operation was successful. + /// If the request has wrong data. + /// Internal server error by database. [HttpPost("reset-password")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task ResetPasswordAsync(ResetPasswordRequest model) { await _accountService.ResetPasswordAsync(model); @@ -152,10 +181,12 @@ public async Task ResetPasswordAsync(ResetPasswordRequest model) /// /// Accounts. /// Unauthorized. + /// Internal server error by database. [Authorize(AppRoles.Admin)] [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task>> GetAllAsync() { IEnumerable accounts = await _accountService.GetAllAsync(); @@ -168,10 +199,14 @@ public async Task>> GetAllAsync() /// Account id. /// Account. /// Unauthorized. + /// If account not found by Id. + /// Internal server error by database. [Authorize] [HttpGet("{id:int}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> GetByIdAsync(int id) { if (id != Account.Id && Account.Role != AppRoles.Admin) @@ -188,11 +223,15 @@ public async Task> GetByIdAsync(int id) /// /// Account. /// Account created. + /// If the request has wrong data. /// Unauthorized. + /// Internal server error by database. [Authorize(AppRoles.Admin)] [HttpPost] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> CreateAsync(CreateRequest model) { AccountResponse account = await _accountService.CreateAsync(model); @@ -205,11 +244,17 @@ public async Task> CreateAsync(CreateRequest model /// Account id. /// Model to update account. /// Account updated. + /// If the request has wrong data. /// Unauthorized. + /// If account not found by Id. + /// Internal server error by database. [Authorize] [HttpPut("{id:int}")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task> UpdateAsync(int id, UpdateRequest model) { if (id != Account.Id && Account.Role != AppRoles.Admin) @@ -232,10 +277,14 @@ public async Task> UpdateAsync(int id, UpdateReque /// Accound id. /// Account deleted. /// Unauthorized. + /// If account not found by Id. + /// Internal server error by database. [Authorize] [HttpDelete("{id:int}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async Task DeleteAsync(int id) { if (id != Account.Id && Account.Role != AppRoles.Admin) @@ -252,7 +301,7 @@ private Task SetTokenCookieAsync(string token) var cookieOptions = new CookieOptions { //HttpOnly = true, - Expires = DateTime.UtcNow.AddDays(7) + Expires = DateTime.UtcNow.AddDays(Constants.TokenExpiresDays) }; Response.Cookies.Append("refreshToken", token, cookieOptions); diff --git a/src/Masny.WebApi/Controllers/CalendarController.cs b/src/Masny.WebApi/Controllers/CalendarController.cs index d385c0f..043201e 100644 --- a/src/Masny.WebApi/Controllers/CalendarController.cs +++ b/src/Masny.WebApi/Controllers/CalendarController.cs @@ -41,7 +41,10 @@ public async Task> GetCalendarLink(CalendarReques { CalendarDto calendarDto = _mapper.Map(calendarRequest); string link = await _calendarService.GetGoogleCalendarLinkAsync(calendarDto); - var response = new CalendarResponse { Link = link }; + var response = new CalendarResponse + { + Link = link + }; return Ok(response); } diff --git a/src/Masny.WebApi/Entities/RefreshToken.cs b/src/Masny.WebApi/Entities/RefreshToken.cs index d70c87a..eb15bf3 100644 --- a/src/Masny.WebApi/Entities/RefreshToken.cs +++ b/src/Masny.WebApi/Entities/RefreshToken.cs @@ -9,6 +9,7 @@ public class RefreshToken { [Key] public int Id { get; set; } + public Account Account { get; set; } public string Token { get; set; } public DateTime Expires { get; set; } diff --git a/src/Masny.WebApi/Extensions/WebServiceCollectionExtension.cs b/src/Masny.WebApi/Extensions/WebServiceCollectionExtension.cs index 009daba..bdffc91 100644 --- a/src/Masny.WebApi/Extensions/WebServiceCollectionExtension.cs +++ b/src/Masny.WebApi/Extensions/WebServiceCollectionExtension.cs @@ -12,17 +12,8 @@ namespace Masny.WebApi.Extensions { - /// - /// Service collection for Web project. - /// public static class WebServiceCollectionExtension { - /// - /// Dependency injection. - /// - /// Service collection. - /// Configuration. - /// Service collection. public static IServiceCollection AddWeb(this IServiceCollection services, IConfiguration configuration) { services = services ?? throw new ArgumentNullException(nameof(services)); diff --git a/src/Masny.WebApi/Helpers/AppException.cs b/src/Masny.WebApi/Helpers/AppException.cs index cc1a588..4acaf7f 100644 --- a/src/Masny.WebApi/Helpers/AppException.cs +++ b/src/Masny.WebApi/Helpers/AppException.cs @@ -5,9 +5,13 @@ namespace Masny.WebApi.Helpers { public class AppException : Exception { - public AppException() : base() { } + public AppException() : base() + { + } - public AppException(string message) : base(message) { } + public AppException(string message) : base(message) + { + } public AppException(string message, params object[] args) : base(string.Format(CultureInfo.CurrentCulture, message, args)) diff --git a/src/Masny.WebApi/Helpers/AppRoles.cs b/src/Masny.WebApi/Helpers/AppRoles.cs index 102b603..ae8e0e6 100644 --- a/src/Masny.WebApi/Helpers/AppRoles.cs +++ b/src/Masny.WebApi/Helpers/AppRoles.cs @@ -2,7 +2,7 @@ { public enum AppRoles { - Admin, - User + Admin = 0, + User = 1, } } diff --git a/src/Masny.WebApi/Helpers/AuthorizeAttribute.cs b/src/Masny.WebApi/Helpers/AuthorizeAttribute.cs index b11fa5f..390a589 100644 --- a/src/Masny.WebApi/Helpers/AuthorizeAttribute.cs +++ b/src/Masny.WebApi/Helpers/AuthorizeAttribute.cs @@ -24,8 +24,8 @@ public void OnAuthorization(AuthorizationFilterContext context) if (account == null || (_roles.Any() && !_roles.Contains(account.Role))) { context.Result = new JsonResult(new { message = "Unauthorized" }) - { - StatusCode = StatusCodes.Status401Unauthorized + { + StatusCode = StatusCodes.Status401Unauthorized }; } } diff --git a/src/Masny.WebApi/Helpers/AutoMapperProfile.cs b/src/Masny.WebApi/Helpers/AutoMapperProfile.cs index e107048..012bd4b 100644 --- a/src/Masny.WebApi/Helpers/AutoMapperProfile.cs +++ b/src/Masny.WebApi/Helpers/AutoMapperProfile.cs @@ -8,7 +8,6 @@ namespace Masny.WebApi.Helpers { public class AutoMapperProfile : Profile { - // TODO: Use Dto public AutoMapperProfile() { CreateMap(); diff --git a/src/Masny.WebApi/Helpers/Constants.cs b/src/Masny.WebApi/Helpers/Constants.cs index a615341..f68fa58 100644 --- a/src/Masny.WebApi/Helpers/Constants.cs +++ b/src/Masny.WebApi/Helpers/Constants.cs @@ -2,6 +2,8 @@ { public static class Constants { + public const int TokenExpiresDays = 7; + public const int ResetTokenExpiresDays = 24; public const string GoogleUrl = "https://www.google.com/calendar/render"; public const string DateTimeFormat = "yyyyMMddTHHmmssZ"; } diff --git a/src/Masny.WebApi/Interfaces/IAccountService.cs b/src/Masny.WebApi/Interfaces/IAccountService.cs index 1114d0a..d19535a 100644 --- a/src/Masny.WebApi/Interfaces/IAccountService.cs +++ b/src/Masny.WebApi/Interfaces/IAccountService.cs @@ -22,15 +22,15 @@ public interface IAccountService Task ValidateResetTokenAsync(ValidateResetTokenRequest model); Task ResetPasswordAsync(ResetPasswordRequest model); - + Task> GetAllAsync(); Task GetByIdAsync(int id); Task CreateAsync(CreateRequest model); - + Task UpdateAsync(int id, UpdateRequest model); - + Task DeleteAsync(int id); } } diff --git a/src/Masny.WebApi/Interfaces/ICalendarService.cs b/src/Masny.WebApi/Interfaces/ICalendarService.cs index 2e98cff..7d71e4f 100644 --- a/src/Masny.WebApi/Interfaces/ICalendarService.cs +++ b/src/Masny.WebApi/Interfaces/ICalendarService.cs @@ -1,5 +1,4 @@ -using Masny.WebApi.Contracts.Requests; -using Masny.WebApi.Models; +using Masny.WebApi.Models; using System.Threading.Tasks; namespace Masny.WebApi.Interfaces diff --git a/src/Masny.WebApi/Services/AccountService.cs b/src/Masny.WebApi/Services/AccountService.cs index ee8b30e..fcfa111 100644 --- a/src/Masny.WebApi/Services/AccountService.cs +++ b/src/Masny.WebApi/Services/AccountService.cs @@ -145,7 +145,7 @@ public async Task ForgotPasswordAsync(ForgotPasswordRequest model, string origin } account.ResetToken = await RandomTokenStringAsync(); - account.ResetTokenExpires = DateTime.UtcNow.AddDays(24); // TODO: To constants + account.ResetTokenExpires = DateTime.UtcNow.AddDays(Constants.ResetTokenExpiresDays); _context.Accounts.Update(account); await _context.SaveChangesAsync(); @@ -160,7 +160,6 @@ public async Task ValidateResetTokenAsync(ValidateResetTokenRequest model) if (account == null) { - // TODO: To constants or resources throw new AppException("Invalid token"); } } diff --git a/src/Masny.WebApi/Services/EmailService.cs b/src/Masny.WebApi/Services/EmailService.cs index 07fe277..b2adb49 100644 --- a/src/Masny.WebApi/Services/EmailService.cs +++ b/src/Masny.WebApi/Services/EmailService.cs @@ -27,7 +27,7 @@ public EmailService(IOptions appSettings) public async Task SendAsync(string to, string subject, string html, string from = null) { var email = new MimeMessage(); - + email.To.Add(MailboxAddress.Parse(to)); email.Subject = subject; email.Body = new TextPart(TextFormat.Html) { Text = html }; diff --git a/src/Masny.WebApi/Startup.cs b/src/Masny.WebApi/Startup.cs index 5791cda..1235eeb 100644 --- a/src/Masny.WebApi/Startup.cs +++ b/src/Masny.WebApi/Startup.cs @@ -22,8 +22,6 @@ public void ConfigureServices(IServiceCollection services) public void Configure(IApplicationBuilder app) { - //context.Database.Migrate(); - app.UseHttpsRedirection(); app.UseSwagger();