Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RSN-40] Add user authentication #43

Merged
merged 5 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public async Task HandleException_WhenVerificationException_ShouldReturnProblemD
var exception = new VerificationException("Verification error");

ProblemDetailsContext? problemDetailsContext = null;

_mockProblemDetailsService.Setup(x =>
x.TryWriteAsync(It.IsAny<ProblemDetailsContext>()))
.Callback<ProblemDetailsContext>(context => problemDetailsContext = context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ public void Setup()
_mockContext = new Mock<ReasnContext>();
_hasher = new PasswordHasher<User>();
_service = new AuthService(_mockContext.Object);

var user = new User
{
Email = "[email protected]",
Username = "jsnow",
Password = _hasher.HashPassword(null!, "password")
Password = _hasher.HashPassword(null!, "password"),
Phone = "+123 456789"
};

_mockContext.Setup(c => c.Users)
.ReturnsDbSet(new List<User> { user });
}
Expand Down Expand Up @@ -96,6 +95,19 @@ public void Register_WhenUserWithUsernameAlreadyExists_ShouldThrowBadRequestExce
Assert.ThrowsException<BadRequestException>(() => _service.Register(request));
}

[TestMethod]
public void Register_WhenUserWithPhoneAlreadyExists_ShouldThrowBadRequestException()
{
var request = new RegisterRequest
{
Email = "[email protected]",
Username = "jstark",
Phone = "+123 456789"
};

Assert.ThrowsException<BadRequestException>(() => _service.Register(request));
}

[TestMethod]
public void Register_WhenUserDoesNotExist_ShouldReturnRegisteredUser()
{
Expand All @@ -106,7 +118,7 @@ public void Register_WhenUserDoesNotExist_ShouldReturnRegisteredUser()
Email = "[email protected]",
Username = "jstark",
Password = "S3cureP@ssword!",
Phone = "+123 456789",
Phone = "+123 456781",
Address = new AddressDto
{
Street = "The Wall",
Expand Down
5 changes: 4 additions & 1 deletion Server/ReasnAPI/ReasnAPI/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
using Microsoft.AspNetCore.Mvc;
using ReasnAPI.Mappers;
using ReasnAPI.Models.Authentication;
using ReasnAPI.Models.DTOs;
using ReasnAPI.Services.Authentication;

namespace ReasnAPI.Controllers;

[ApiController]
[Route("api/[controller]")]
[Route("[controller]")]
public class AuthController : ControllerBase
{
private readonly AuthService _authService;
Expand All @@ -20,6 +21,7 @@ public AuthController(AuthService authService, TokenService tokenService)
}

[HttpPost("login")]
[ProducesResponseType<TokenPayload>(StatusCodes.Status200OK)]
public IActionResult Login(
[FromBody] LoginRequest request,
[FromServices] IValidator<LoginRequest> validator)
Expand All @@ -32,6 +34,7 @@ public IActionResult Login(
}

[HttpPost("register")]
[ProducesResponseType<UserDto>(StatusCodes.Status201Created)]
public IActionResult Register(
[FromBody] RegisterRequest request,
[FromServices] IValidator<RegisterRequest> validator)
Expand Down
2 changes: 1 addition & 1 deletion Server/ReasnAPI/ReasnAPI/Controllers/UsersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace ReasnAPI.Controllers;

[ApiController]
[Route("api/[controller]")]
[Route("[controller]")]
public class UsersController : ControllerBase
{
[HttpGet]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace ReasnAPI.Middlewares;

public class GlobalRoutePrefixMiddleware
{
private readonly RequestDelegate _next;
private readonly string _routePrefix;

public GlobalRoutePrefixMiddleware(RequestDelegate next, string routePrefix)
{
_next = next;
_routePrefix = routePrefix;
}

public async Task InvokeAsync(HttpContext context)
{
context.Request.PathBase = new PathString(_routePrefix);
await _next(context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace ReasnAPI.Models.Authentication;

public class TokenPayload
{
public string TokenType { get; set; }
public string AccessToken { get; set; }
public string TokenType { get; set; } = null!;
public string AccessToken { get; set; } = null!;
public int ExpiresIn { get; set; }
}
3 changes: 1 addition & 2 deletions Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@
.HasPostgresEnum("common", "event_status", new[] { "Completed", "In progress", "Approved", "Waiting for approval" })
.HasPostgresEnum("common", "object_type", new[] { "Event", "User" })
.HasPostgresEnum("common", "participant_status", new[] { "Interested", "Participating" })
.HasPostgresEnum("users", "role", new[] { "User", "Organizer", "Admin" });

.HasPostgresEnum("users", "role", new[] { "User", "Organizer", "Admin" });
modelBuilder.Entity<Address>(entity =>
{
entity.HasKey(e => e.Id).HasName("address_pkey");
Expand Down Expand Up @@ -285,5 +284,5 @@
OnModelCreatingPartial(modelBuilder);
}

partial void OnModelCreatingPartial(ModelBuilder modelBuilder);

Check warning on line 287 in Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs

View workflow job for this annotation

GitHub Actions / dotnet-tests (ubuntu-latest)

Supply an implementation for this partial method. (https://rules.sonarsource.com/csharp/RSPEC-3251)

Check warning on line 287 in Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs

View workflow job for this annotation

GitHub Actions / dotnet-tests (macos-latest)

Supply an implementation for this partial method. (https://rules.sonarsource.com/csharp/RSPEC-3251)

Check warning on line 287 in Server/ReasnAPI/ReasnAPI/Models/Database/ReasnContext.cs

View workflow job for this annotation

GitHub Actions / dotnet-tests (windows-latest)

Supply an implementation for this partial method. (https://rules.sonarsource.com/csharp/RSPEC-3251)
}
8 changes: 4 additions & 4 deletions Server/ReasnAPI/ReasnAPI/Models/Enums/UserRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ namespace ReasnAPI.Models.Enums;
public enum UserRole
{
[PgName("User")]
User,

User,
[PgName("Organizer")]
Organizer,

Organizer,
[PgName("Admin")]
Admin
}
4 changes: 4 additions & 0 deletions Server/ReasnAPI/ReasnAPI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using ReasnAPI.Exceptions;
using ReasnAPI.Middlewares;
using ReasnAPI.Models.Database;
using ReasnAPI.Services.Authentication;
using ReasnAPI.Validators;
Expand Down Expand Up @@ -103,6 +104,9 @@

var app = builder.Build();

app.UseMiddleware<GlobalRoutePrefixMiddleware>("/api/v1");
app.UsePathBase(new PathString("/api/v1"));

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
Expand All @@ -128,3 +132,3 @@

app.MapGet("/", () => "Hello, World!");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ public User Register(RegisterRequest request)
{
var userAlreadyExists = _context.Users.Any(u =>
u.Email.ToUpper() == request.Email.ToUpper() ||
u.Username.ToUpper() == request.Username.ToUpper());
u.Username.ToUpper() == request.Username.ToUpper() ||
u.Phone == request.Phone);

if (userAlreadyExists)
{
throw new BadRequestException(
"User with provided email or username already exists");
"User with provided email, username or phone already exists");
}

var user = new User
Expand Down
4 changes: 2 additions & 2 deletions Server/ReasnAPI/ReasnAPI/Validators/AddressValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class AddressValidator : AbstractValidator<AddressDto>
private const string CityRegex = @"^\p{Lu}[\p{Ll}'.]+(?:[\s-][\p{L}'.]+)*$";
private const string StreetRegex = @"^[\p{L}\d\s\-/.,#']+(?<![-\s#,])$";
private const string StateRegex = @"^\p{Lu}\p{Ll}+(?:(\s|-)\p{L}+)*$";
private const string ZipCodeRegex = @"^[\p{L}\d\s-]{3,}$";

private const string ZipCodeRegex = @"^[\p{L}\d\s-]{3,}$";
public AddressValidator()
{
RuleFor(a => a.Country)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public RegisterRequestValidator()

RuleFor(r => r.Email)
.NotEmpty()
.MaximumLength(MaxEmailLength)
.EmailAddress();
.EmailAddress()
.MaximumLength(MaxEmailLength);

RuleFor(r => r.Password)
.NotEmpty()
Expand Down
Loading