Skip to content
Open
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 @@ -89,13 +89,13 @@ public async Task<IActionResult> GetUserData()
return Ok(aggregatedResult);
}

[HttpPost("register")]
[ProducesResponseType(typeof(Result), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Register(RegisterViewModel model)
{
var result = await AuthServiceClient.Register(model);
return Ok(result);
}
// [HttpPost("register")]
// [ProducesResponseType(typeof(Result), (int)HttpStatusCode.OK)]
// public async Task<IActionResult> Register(RegisterViewModel model)
// {
// var result = await AuthServiceClient.Register(model);
// return Ok(result);
// }

[HttpPost("login")]
[ProducesResponseType(typeof(Result<TokenCredentials>), (int)HttpStatusCode.OK)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Net;
using System.Threading.Tasks;
using HwProj.AuthService.Client;
using HwProj.CoursesService.Client;
using HwProj.Models.CoursesService.DTO;
using HwProj.Models.CoursesService.ViewModels;
using HwProj.Models.Result;
using HwProj.Models.Roles;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace HwProj.APIGateway.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class RegistrationRequestsController(
ICoursesServiceClient coursesClient,
IAuthServiceClient authServiceClient)
: AggregationController(authServiceClient)
{
[HttpPost("init")]
[ProducesResponseType(typeof(Result), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Init([FromBody] InitRegistrationRequestViewModel model)
{
var result = await coursesClient.InitRegistrationRequest(model);
return Ok(result);
}

[HttpPost("confirm")]
[ProducesResponseType(typeof(Result<long>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Confirm([FromBody] ConfirmRegistrationRequestViewModel model)
{
var result = await coursesClient.ConfirmRegistrationRequest(model);
return Ok(result);
}

[HttpGet("course/{courseId}")]
[Authorize(Roles = Roles.LecturerRole)]
[ProducesResponseType(typeof(Result<RegistrationRequestDto[]>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetCourseRequests(long courseId)
{
var result = await coursesClient.GetCourseRegistrationRequests(courseId);
return Ok(result);
}

[HttpGet("general")]
[Authorize(Roles = Roles.LecturerRole)]
[ProducesResponseType(typeof(Result<RegistrationRequestDto[]>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetGeneralRequests()
{
var result = await coursesClient.GetGeneralRegistrationRequests();
return Ok(result);
}

[HttpPost("{requestId}/approve")]
[Authorize(Roles = Roles.LecturerRole)]
[ProducesResponseType(typeof(Result<string>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Approve(long requestId)
{
var result = await coursesClient.ApproveRegistrationRequest(requestId);
return Ok(result);
}

[HttpPost("{requestId}/reject")]
[Authorize(Roles = Roles.LecturerRole)]
[ProducesResponseType(typeof(Result), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Reject(long requestId, [FromBody] ReviewRegistrationRequestViewModel model)
{
var result = await coursesClient.RejectRegistrationRequest(requestId, model);
return Ok(result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,25 @@ public async Task<IActionResult> GetUserDataByEmail(string email)
public async Task<IActionResult> Register([FromBody] RegisterViewModel model)
{
var newModel = _mapper.Map<RegisterDataDTO>(model);
var result = await _accountService.RegisterUserAsync(newModel);
var result = await _accountService.RegisterStudentAsync(newModel);
return Ok(result);
}

[HttpPost("registerStudent")]
[ProducesResponseType(typeof(Result<string>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> RegisterStudent([FromBody] RegisterViewModel model)
{
var newModel = _mapper.Map<RegisterDataDTO>(model);
var result = await _accountService.RegisterStudentAsync(newModel);
return Ok(result);
}

[HttpPost("registerLecturer")]
[ProducesResponseType(typeof(Result<string>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> RegisterLecturer([FromBody] RegisterViewModel model)
{
var newModel = _mapper.Map<RegisterDataDTO>(model);
var result = await _accountService.RegisterLecturerAsync(newModel);
return Ok(result);
}

Expand Down Expand Up @@ -113,6 +131,11 @@ public async Task<IActionResult> InviteNewLecturer(InviteLecturerViewModel model
public async Task<IActionResult> FindByEmail(string email)
{
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
return Ok(null);
}

var roles = await _userManager.GetRolesAsync(user);
return Ok(user.ToAccountDataDto(roles.First()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,24 @@ public async Task<AccountDataDto> GetAccountDataByEmailAsync(string email)
return await GetAccountDataAsync(user);
}

public async Task<Result<string>> RegisterUserAsync(RegisterDataDTO model)
public async Task<Result<string>> RegisterStudentAsync(RegisterDataDTO model)
{
model.Email = model.Email.Trim();
model.Name = model.Name.Trim();
model.Surname = model.Surname.Trim();
model.MiddleName = model.MiddleName.Trim();
NormalizeRegisterDataDTO(model);

if (await _userManager.FindByEmailAsync(model.Email) != null)
return Result<string>.Failed("Пользователь уже зарегистрирован");

return await RegisterUserAsyncInternal(model);
return await RegisterUserAsyncInternal(model, Roles.StudentRole);
}

public async Task<Result<string>> RegisterLecturerAsync(RegisterDataDTO model)
{
NormalizeRegisterDataDTO(model);

if (await _userManager.FindByEmailAsync(model.Email) != null)
return Result<string>.Failed("Пользователь уже зарегистрирован");

return await RegisterUserAsyncInternal(model, Roles.LecturerRole);
}

public async Task<Result<string>[]> GetOrRegisterStudentsBatchAsync(IEnumerable<RegisterDataDTO> models)
Expand All @@ -116,7 +123,7 @@ public async Task<Result<string>[]> GetOrRegisterStudentsBatchAsync(IEnumerable<
continue;
}

var result = await RegisterUserAsyncInternal(model);
var result = await RegisterUserAsyncInternal(model, Roles.StudentRole);
results.Add(result);
}

Expand Down Expand Up @@ -166,7 +173,7 @@ public async Task<Result<TokenCredentials>> RefreshToken(string userId)
: await GetToken(user);
}

private async Task<Result<string>> RegisterUserAsyncInternal(RegisterDataDTO model)
private async Task<Result<string>> RegisterUserAsyncInternal(RegisterDataDTO model, string role)
{
var user = _mapper.Map<User>(model);
user.UserName = user.Email;
Expand All @@ -176,13 +183,13 @@ private async Task<Result<string>> RegisterUserAsyncInternal(RegisterDataDTO mod
: _userManager.CreateAsync(user, Guid.NewGuid().ToString());

var result = await createUserTask
.Then(() => _userManager.AddToRoleAsync(user, Roles.StudentRole));
.Then(() => _userManager.AddToRoleAsync(user, role));

if (result.Succeeded)
{
var newUser = await _userManager.FindByEmailAsync(model.Email);
var changePasswordToken = await _aspUserManager.GeneratePasswordResetTokenAsync(user);
var registerEvent = new StudentRegisterEvent(newUser.Id, newUser.Email, newUser.Name,
var registerEvent = new AuthRegisterEvent(newUser.Id, newUser.Email, newUser.Name,
newUser.Surname, newUser.MiddleName)
{
ChangePasswordToken = changePasswordToken
Expand Down Expand Up @@ -377,5 +384,13 @@ private async Task<Result<TokenCredentials>> GetToken(User user)
{
return Result<TokenCredentials>.Success(await _tokenService.GetTokenAsync(user).ConfigureAwait(false));
}

private void NormalizeRegisterDataDTO(RegisterDataDTO model)
{
model.Email = model.Email.Trim();
model.Name = model.Name.Trim();
model.Surname = model.Surname.Trim();
model.MiddleName = model.MiddleName.Trim();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public interface IAccountService
Task<AccountDataDto> GetAccountDataAsync(string userId);
Task<AccountDataDto[]> GetAccountsDataAsync(string[] userIds);
Task<AccountDataDto> GetAccountDataByEmailAsync(string email);
Task<Result<string>> RegisterUserAsync(RegisterDataDTO model);
Task<Result<string>> RegisterStudentAsync(RegisterDataDTO model);
Task<Result<string>> RegisterLecturerAsync(RegisterDataDTO model);
Task<Result> EditAccountAsync(string accountId, EditDataDTO model);
Task<Result<TokenCredentials>> LoginUserAsync(LoginViewModel model);
Task<Result<TokenCredentials>> RefreshToken(string userId);
Expand Down
32 changes: 32 additions & 0 deletions HwProj.AuthService/HwProj.AuthService.Client/AuthServiceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,38 @@ public async Task<Result<string>> Register(RegisterViewModel model)
var response = await _httpClient.SendAsync(httpRequest);
return await response.DeserializeAsync<Result<string>>();
}

public async Task<Result<string>> RegisterStudent(RegisterViewModel model)
{
using var httpRequest = new HttpRequestMessage(
HttpMethod.Post,
_authServiceUri + "api/account/registerStudent")
{
Content = new StringContent(
JsonConvert.SerializeObject(model),
Encoding.UTF8,
"application/json")
};

var response = await _httpClient.SendAsync(httpRequest);
return await response.DeserializeAsync<Result<string>>();
}

public async Task<Result<string>> RegisterLecturer(RegisterViewModel model)
{
using var httpRequest = new HttpRequestMessage(
HttpMethod.Post,
_authServiceUri + "api/account/registerLecturer")
{
Content = new StringContent(
JsonConvert.SerializeObject(model),
Encoding.UTF8,
"application/json")
};

var response = await _httpClient.SendAsync(httpRequest);
return await response.DeserializeAsync<Result<string>>();
}

public async Task<Result<string>[]> GetOrRegisterStudentsBatchAsync(
IEnumerable<RegisterViewModel> registrationModels)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public interface IAuthServiceClient
Task<AccountDataDto> GetAccountDataByEmail(string email);
Task<AccountDataDto[]> GetAccountsData(string[] userId);
Task<Result<string>> Register(RegisterViewModel model);
Task<Result<string>> RegisterStudent(RegisterViewModel model);
Task<Result<string>> RegisterLecturer(RegisterViewModel model);
Task<Result<TokenCredentials>> Login(LoginViewModel model);
Task<Result<TokenCredentials>> RefreshToken(string userId);
Task<Result> Edit(EditAccountViewModel model, string userId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;

namespace HwProj.Models.CoursesService.DTO
{
public class RegistrationRequestDto
{
public long Id { get; set; }

public string? Description { get; set; }

public string? PreferredLecturerEmail { get; set; }

public long? CourseId { get; set; }

public string RequestedRole { get; set; }

public string Email { get; set; }

public string Name { get; set; }

public string Surname { get; set; }

public string MiddleName { get; set; }

public string Status { get; set; }

public DateTime CreatedAtUtc { get; set; }

public DateTime UpdatedAtUtc { get; set; }

public DateTime? ReviewedAtUtc { get; set; }

public string? ReviewedByUserId { get; set; }

public string? RejectReason { get; set; }

public string? ResolvedUserId { get; set; }
}
}
8 changes: 8 additions & 0 deletions HwProj.Common/HwProj.Models/CoursesService/RequestedRole.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace HwProj.Models.CoursesService
{
public enum RequestedRole
{
Student = 0,
Lecturer = 1,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;

namespace HwProj.Models.CoursesService.ViewModels
{
public class ConfirmRegistrationRequestViewModel
{
[Required]
public string Token { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.ComponentModel.DataAnnotations;

namespace HwProj.Models.CoursesService.ViewModels
{
public class InitRegistrationRequestViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; }

[Required]
[RegularExpression(@"^\S+.*", ErrorMessage = "Name shouldn't start with white spaces.")]
public string Name { get; set; }

[Required]
[RegularExpression(@"^\S+.*", ErrorMessage = "Surname shouldn't start with white spaces.")]
public string Surname { get; set; }

[RegularExpression(@"^\S+.*", ErrorMessage = "MiddleName shouldn't start with white spaces.")]
public string MiddleName { get; set; } = string.Empty;

public long? CourseId { get; set; }

public RequestedRole RequestedRole { get; set; } = RequestedRole.Student;

public string? Description { get; set; }

[EmailAddress]
public string? PreferredLecturerEmail { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;

namespace HwProj.Models.CoursesService.ViewModels
{
public class ReviewRegistrationRequestViewModel
{
public string? RejectReason { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ public AutomapperProfile()

CreateMap<CreateCourseFilterDTO, CreateCourseFilterModel>();
CreateMap<Filter, CourseFilterDTO>();


CreateMap<RegistrationRequest, RegistrationRequestDto>();

CreateMap<UpdateGroupViewModel, Group>().ReverseMap();
CreateMap<Group, UserGroupDescription>();

CreateMap<GroupMateViewModel, GroupMate>().ReverseMap();
}
}
Expand Down
Loading
Loading