Skip to content

Commit

Permalink
refactor: code optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
MikhailMasny committed Sep 11, 2020
1 parent 7587361 commit 968f427
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 29 deletions.
53 changes: 51 additions & 2 deletions src/Masny.WebApi/Controllers/AccountsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ public AccountsController(IAccountService accountService)
/// </summary>
/// <param name="model">Login model.</param>
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="500">Internal server error by database.</response>
[HttpPost("authenticate")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<AuthenticateResponse>> AuthenticateAsync(AuthenticateRequest model)
{
// TODO: operation result + response
AuthenticateResponse response = await _accountService.AuthenticateAsync(model);
await SetTokenCookieAsync(response.RefreshToken);
return Ok(response);
Expand All @@ -40,8 +43,12 @@ public async Task<ActionResult<AuthenticateResponse>> AuthenticateAsync(Authenti
/// Refresh token.
/// </summary>
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="500">Internal server error by database.</response>
[HttpPost("refresh-token")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<AuthenticateResponse>> RefreshTokenAsync()
{
var refreshToken = Request.Cookies["refreshToken"];
Expand All @@ -57,11 +64,13 @@ public async Task<ActionResult<AuthenticateResponse>> RefreshTokenAsync()
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="401">Unauthorized.</response>
/// <response code="500">Internal server error by database.</response>
[Authorize]
[HttpPost("revoke-token")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> RevokeTokenAsync(RevokeTokenRequest model)
{
var token = !string.IsNullOrEmpty(model.Token)
Expand All @@ -87,8 +96,12 @@ public async Task<IActionResult> RevokeTokenAsync(RevokeTokenRequest model)
/// </summary>
/// <param name="model">Registration model.</param>
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="500">Internal server error by database.</response>
[HttpPost("register")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> RegisterAsync(RegisterRequest model)
{
await _accountService.RegisterAsync(model, Request.Headers["origin"]);
Expand All @@ -100,8 +113,12 @@ public async Task<IActionResult> RegisterAsync(RegisterRequest model)
/// </summary>
/// <param name="model">Verify email model.</param>
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="500">Internal server error by database.</response>
[HttpPost("verify-email")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> VerifyEmailAsync(VerifyEmailRequest model)
{
await _accountService.VerifyEmailAsync(model.Token);
Expand All @@ -113,8 +130,12 @@ public async Task<IActionResult> VerifyEmailAsync(VerifyEmailRequest model)
/// </summary>
/// <param name="model">Forgot password model.</param>
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="500">Internal server error by database.</response>
[HttpPost("forgot-password")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> ForgotPasswordAsync(ForgotPasswordRequest model)
{
await _accountService.ForgotPasswordAsync(model, Request.Headers["origin"]);
Expand All @@ -126,8 +147,12 @@ public async Task<IActionResult> ForgotPasswordAsync(ForgotPasswordRequest model
/// </summary>
/// <param name="model">Validate reset token model.</param>
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="500">Internal server error by database.</response>
[HttpPost("validate-reset-token")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> ValidateResetTokenAsync(ValidateResetTokenRequest model)
{
await _accountService.ValidateResetTokenAsync(model);
Expand All @@ -139,8 +164,12 @@ public async Task<IActionResult> ValidateResetTokenAsync(ValidateResetTokenReque
/// </summary>
/// <param name="model">Reset password model.</param>
/// <response code="200">The operation was successful.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="500">Internal server error by database.</response>
[HttpPost("reset-password")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> ResetPasswordAsync(ResetPasswordRequest model)
{
await _accountService.ResetPasswordAsync(model);
Expand All @@ -152,10 +181,12 @@ public async Task<IActionResult> ResetPasswordAsync(ResetPasswordRequest model)
/// </summary>
/// <response code="200">Accounts.</response>
/// <response code="401">Unauthorized.</response>
/// <response code="500">Internal server error by database.</response>
[Authorize(AppRoles.Admin)]
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<IEnumerable<AccountResponse>>> GetAllAsync()
{
IEnumerable<AccountResponse> accounts = await _accountService.GetAllAsync();
Expand All @@ -168,10 +199,14 @@ public async Task<ActionResult<IEnumerable<AccountResponse>>> GetAllAsync()
/// <param name="id">Account id.</param>
/// <response code="200">Account.</response>
/// <response code="401">Unauthorized.</response>
/// <response code="404">If account not found by Id.</response>
/// <response code="500">Internal server error by database.</response>
[Authorize]
[HttpGet("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<AccountResponse>> GetByIdAsync(int id)
{
if (id != Account.Id && Account.Role != AppRoles.Admin)
Expand All @@ -188,11 +223,15 @@ public async Task<ActionResult<AccountResponse>> GetByIdAsync(int id)
/// </summary>
/// <param name="model">Account.</param>
/// <response code="200">Account created.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="401">Unauthorized.</response>
/// <response code="500">Internal server error by database.</response>
[Authorize(AppRoles.Admin)]
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<AccountResponse>> CreateAsync(CreateRequest model)
{
AccountResponse account = await _accountService.CreateAsync(model);
Expand All @@ -205,11 +244,17 @@ public async Task<ActionResult<AccountResponse>> CreateAsync(CreateRequest model
/// <param name="id">Account id.</param>
/// <param name="model">Model to update account.</param>
/// <response code="200">Account updated.</response>
/// <response code="400">If the request has wrong data.</response>
/// <response code="401">Unauthorized.</response>
/// <response code="404">If account not found by Id.</response>
/// <response code="500">Internal server error by database.</response>
[Authorize]
[HttpPut("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<AccountResponse>> UpdateAsync(int id, UpdateRequest model)
{
if (id != Account.Id && Account.Role != AppRoles.Admin)
Expand All @@ -232,10 +277,14 @@ public async Task<ActionResult<AccountResponse>> UpdateAsync(int id, UpdateReque
/// <param name="id">Accound id.</param>
/// <response code="200">Account deleted.</response>
/// <response code="401">Unauthorized.</response>
/// <response code="404">If account not found by Id.</response>
/// <response code="500">Internal server error by database.</response>
[Authorize]
[HttpDelete("{id:int}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DeleteAsync(int id)
{
if (id != Account.Id && Account.Role != AppRoles.Admin)
Expand All @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion src/Masny.WebApi/Controllers/CalendarController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ public async Task<ActionResult<CalendarResponse>> GetCalendarLink(CalendarReques
{
CalendarDto calendarDto = _mapper.Map<CalendarDto>(calendarRequest);
string link = await _calendarService.GetGoogleCalendarLinkAsync(calendarDto);
var response = new CalendarResponse { Link = link };
var response = new CalendarResponse
{
Link = link
};

return Ok(response);
}
Expand Down
1 change: 1 addition & 0 deletions src/Masny.WebApi/Entities/RefreshToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
9 changes: 0 additions & 9 deletions src/Masny.WebApi/Extensions/WebServiceCollectionExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,8 @@

namespace Masny.WebApi.Extensions
{
/// <summary>
/// Service collection for Web project.
/// </summary>
public static class WebServiceCollectionExtension
{
/// <summary>
/// Dependency injection.
/// </summary>
/// <param name="services">Service collection.</param>
/// <param name="configuration">Configuration.</param>
/// <returns>Service collection.</returns>
public static IServiceCollection AddWeb(this IServiceCollection services, IConfiguration configuration)
{
services = services ?? throw new ArgumentNullException(nameof(services));
Expand Down
8 changes: 6 additions & 2 deletions src/Masny.WebApi/Helpers/AppException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions src/Masny.WebApi/Helpers/AppRoles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
public enum AppRoles
{
Admin,
User
Admin = 0,
User = 1,
}
}
4 changes: 2 additions & 2 deletions src/Masny.WebApi/Helpers/AuthorizeAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
}
}
Expand Down
1 change: 0 additions & 1 deletion src/Masny.WebApi/Helpers/AutoMapperProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace Masny.WebApi.Helpers
{
public class AutoMapperProfile : Profile
{
// TODO: Use Dto
public AutoMapperProfile()
{
CreateMap<CalendarRequest, CalendarDto>();
Expand Down
2 changes: 2 additions & 0 deletions src/Masny.WebApi/Helpers/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
6 changes: 3 additions & 3 deletions src/Masny.WebApi/Interfaces/IAccountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ public interface IAccountService
Task ValidateResetTokenAsync(ValidateResetTokenRequest model);

Task ResetPasswordAsync(ResetPasswordRequest model);

Task<IEnumerable<AccountResponse>> GetAllAsync();

Task<AccountResponse> GetByIdAsync(int id);

Task<AccountResponse> CreateAsync(CreateRequest model);

Task<AccountResponse> UpdateAsync(int id, UpdateRequest model);

Task DeleteAsync(int id);
}
}
3 changes: 1 addition & 2 deletions src/Masny.WebApi/Interfaces/ICalendarService.cs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/Masny.WebApi/Services/AccountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -160,7 +160,6 @@ public async Task ValidateResetTokenAsync(ValidateResetTokenRequest model)

if (account == null)
{
// TODO: To constants or resources
throw new AppException("Invalid token");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Masny.WebApi/Services/EmailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public EmailService(IOptions<AppSettings> 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 };
Expand Down
2 changes: 0 additions & 2 deletions src/Masny.WebApi/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ public void ConfigureServices(IServiceCollection services)

public void Configure(IApplicationBuilder app)
{
//context.Database.Migrate();

app.UseHttpsRedirection();

app.UseSwagger();
Expand Down

0 comments on commit 968f427

Please sign in to comment.