Skip to content
Draft
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 28 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Build (.NET 8)

on:
push:
branches: [ master ]
pull_request:

jobs:
build:
runs-on: windows-latest
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET 8
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
cache: true
cache-dependency-path: |
**/*.csproj
**/*.sln

- name: Build
run: dotnet build HwProj.sln -c Release
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ jobs:
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
command_timeout: 30m
script: |
cd /home/${{ secrets.SSH_USER }}/docker/HwProj-2.0.1
echo "${{ secrets.SUDO_PASSWORD }}" | sudo -S ./update.sh
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,4 @@ StyleCop.Cache
.env
swagger-codegen
hwproj.front/static_dist/
hwproj.front/dist/
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
<PropertyGroup>
<NullableReferenceTypes>enable</NullableReferenceTypes>
</PropertyGroup>
</Project>
</Project>
18 changes: 7 additions & 11 deletions HwProj.APIGateway/HwProj.APIGateway.API/ApplicationProfile.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
using AutoMapper;
using HwProj.Models.AuthService.DTO;
using HwProj.Models.AuthService.ViewModels;
using HwProj.Models.CoursesService;
using HwProj.Models.CoursesService.DTO;
using HwProj.Models.CoursesService.ViewModels;

namespace HwProj.APIGateway.API
namespace HwProj.APIGateway.API;

public class ApplicationProfile : Profile
{
public class ApplicationProfile : Profile
public ApplicationProfile()
{
public ApplicationProfile()
{
CreateMap<InviteExpertViewModel, CreateCourseFilterDTO>();
CreateMap<EditMentorWorkspaceDTO, CreateCourseFilterDTO>();
}
CreateMap<InviteExpertViewModel, CreateCourseFilterDTO>();
CreateMap<EditMentorWorkspaceDTO, CreateCourseFilterDTO>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,12 @@ namespace HwProj.APIGateway.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AccountController : AggregationController
public class AccountController(
IAuthServiceClient authClient,
ICoursesServiceClient coursesClient,
ISolutionsServiceClient solutionsServiceClient)
: AggregationController(authClient)
{
private readonly ICoursesServiceClient _coursesClient;
private readonly ISolutionsServiceClient _solutionsServiceClient;

public AccountController(
IAuthServiceClient authClient,
ICoursesServiceClient coursesClient,
ISolutionsServiceClient solutionsServiceClient) : base(authClient)
{
_coursesClient = coursesClient;
_solutionsServiceClient = solutionsServiceClient;
}

[HttpGet("getUserData/{userId}")]
[ProducesResponseType(typeof(AccountDataDto), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetUserDataById(string userId)
Expand All @@ -52,7 +44,7 @@ public async Task<IActionResult> GetUserData()

if (User.IsInRole(Roles.LecturerRole))
{
var courses = await _coursesClient.GetAllUserCourses();
var courses = await coursesClient.GetAllUserCourses();
var courseEvents = courses
.Select(t => new CourseEvents
{
Expand All @@ -74,9 +66,9 @@ public async Task<IActionResult> GetUserData()
}

var currentTime = DateTime.UtcNow;
var taskDeadlines = await _coursesClient.GetTaskDeadlines();
var taskDeadlines = await coursesClient.GetTaskDeadlines();
var taskIds = taskDeadlines.Select(t => t.TaskId).ToArray();
var solutions = await _solutionsServiceClient.GetLastTaskSolutions(taskIds, UserId);
var solutions = await solutionsServiceClient.GetLastTaskSolutions(taskIds, UserId);
var taskDeadlinesInfo = taskDeadlines
.Zip(solutions, (deadline, solution) => (deadline, solution))
.Where(t => currentTime <= t.deadline.DeadlineDate || t.solution == null)
Expand Down Expand Up @@ -160,7 +152,7 @@ public async Task<Result> ResetPassword(ResetPasswordViewModel model)
{
return await AuthServiceClient.ResetPassword(model);
}

[Authorize]
[HttpPost("github/url")]
[ProducesResponseType(typeof(UrlDto), (int)HttpStatusCode.OK)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,38 @@
using HwProj.Models.CoursesService.ViewModels;
using Microsoft.AspNetCore.Mvc;

namespace HwProj.APIGateway.API.Controllers
namespace HwProj.APIGateway.API.Controllers;

public class AggregationController : ControllerBase
{
public class AggregationController : ControllerBase
{
protected readonly IAuthServiceClient AuthServiceClient;
protected readonly IAuthServiceClient AuthServiceClient;

protected AggregationController(IAuthServiceClient authServiceClient)
{
AuthServiceClient = authServiceClient;
}
protected AggregationController(IAuthServiceClient authServiceClient)
{
AuthServiceClient = authServiceClient;
}

protected string? UserId =>
Request.HttpContext.User.Claims
.FirstOrDefault(claim => claim.Type.ToString() == "_id")
?.Value;
protected string? UserId =>
Request.HttpContext.User.Claims
.FirstOrDefault(claim => claim.Type.ToString() == "_id")
?.Value;

protected async Task<CoursePreviewView[]> GetCoursePreviews(CoursePreview[] courses)
protected async Task<CoursePreviewView[]> GetCoursePreviews(CoursePreview[] courses)
{
var mentorIds = courses.SelectMany(t => t.MentorIds).Distinct().ToArray();
var mentors = await AuthServiceClient.GetAccountsData(mentorIds);
var mentorsDict = mentors.Where(x => x != null).ToDictionary(x => x.UserId);
return courses.Select(course => new CoursePreviewView
{
var mentorIds = courses.SelectMany(t => t.MentorIds).Distinct().ToArray();
var mentors = await AuthServiceClient.GetAccountsData(mentorIds);
var mentorsDict = mentors.Where(x => x != null).ToDictionary(x => x.UserId);
return courses.Select(course => new CoursePreviewView
{
Id = course.Id,
Name = course.Name,
GroupName = course.GroupName,
IsCompleted = course.IsCompleted,
Mentors = course.MentorIds
.Select(x => mentorsDict.TryGetValue(x, out var mentor) ? mentor : null)
.Where(x => x != null)
.ToArray()!,
TaskId = course.TaskId
}).ToArray();
}
Id = course.Id,
Name = course.Name,
GroupName = course.GroupName,
IsCompleted = course.IsCompleted,
Mentors = course.MentorIds
.Select(x => mentorsDict.TryGetValue(x, out var mentor) ? mentor : null)
.Where(x => x != null)
.ToArray()!,
TaskId = course.TaskId
}).ToArray();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,97 +7,96 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace HwProj.APIGateway.API.Controllers
namespace HwProj.APIGateway.API.Controllers;

[Route("api/[controller]")]
[ApiController]
public class CourseGroupsController : AggregationController
{
[Route("api/[controller]")]
[ApiController]
public class CourseGroupsController : AggregationController
{
private readonly ICoursesServiceClient _coursesClient;
private readonly ICoursesServiceClient _coursesClient;

public CourseGroupsController(ICoursesServiceClient coursesClient) : base(null)
{
_coursesClient = coursesClient;
}
public CourseGroupsController(ICoursesServiceClient coursesClient) : base(null)
{
_coursesClient = coursesClient;
}

[HttpGet("{courseId}/getAll")]
[ProducesResponseType(typeof(GroupViewModel[]), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetAllCourseGroups(long courseId)
{
var result = await _coursesClient.GetAllCourseGroups(courseId);
return result == null
? NotFound() as IActionResult
: Ok(result);
}
[HttpGet("{courseId}/getAll")]
[ProducesResponseType(typeof(GroupViewModel[]), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetAllCourseGroups(long courseId)
{
var result = await _coursesClient.GetAllCourseGroups(courseId);
return result == null
? NotFound()
: Ok(result);
}

[HttpPost("{courseId}/create")]
[Authorize(Roles = Roles.LecturerRole)]
[ProducesResponseType(typeof(long), (int)HttpStatusCode.OK)]
public async Task<IActionResult> CreateCourseGroup(CreateGroupViewModel model, long courseId)
{
var result = await _coursesClient.CreateCourseGroup(model, courseId);
return Ok(result);
}
[HttpPost("{courseId}/create")]
[Authorize(Roles = Roles.LecturerRole)]
[ProducesResponseType(typeof(long), (int)HttpStatusCode.OK)]
public async Task<IActionResult> CreateCourseGroup(CreateGroupViewModel model, long courseId)
{
var result = await _coursesClient.CreateCourseGroup(model, courseId);
return Ok(result);
}

[HttpDelete("{courseId}/delete/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> DeleteCourseGroup(long courseId, long groupId)
{
await _coursesClient.DeleteCourseGroup(courseId, groupId);
return Ok();
}
[HttpDelete("{courseId}/delete/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> DeleteCourseGroup(long courseId, long groupId)
{
await _coursesClient.DeleteCourseGroup(courseId, groupId);
return Ok();
}

[HttpPost("{courseId}/update/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> UpdateCourseGroup(UpdateGroupViewModel model, long courseId, long groupId)
{
await _coursesClient.UpdateCourseGroup(model, courseId, groupId);
return Ok();
}
[HttpPost("{courseId}/update/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> UpdateCourseGroup(UpdateGroupViewModel model, long courseId, long groupId)
{
await _coursesClient.UpdateCourseGroup(model, courseId, groupId);
return Ok();
}

[HttpGet("{courseId}/get")]
[Authorize]
[ProducesResponseType(typeof(GroupViewModel), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetCourseGroupsById(long courseId)
{
var result = await _coursesClient.GetCourseGroupsById(courseId, UserId);
return result == null
? NotFound() as IActionResult
: Ok(result);
}
[HttpGet("{courseId}/get")]
[Authorize]
[ProducesResponseType(typeof(GroupViewModel), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetCourseGroupsById(long courseId)
{
var result = await _coursesClient.GetCourseGroupsById(courseId, UserId);
return result == null
? NotFound()
: Ok(result);
}

[HttpPost("{courseId}/addStudentInGroup/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> AddStudentInGroup(long courseId, long groupId, [FromQuery] string userId)
{
await _coursesClient.AddStudentInGroup(courseId, groupId, userId);
return Ok();
}
[HttpPost("{courseId}/addStudentInGroup/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> AddStudentInGroup(long courseId, long groupId, [FromQuery] string userId)
{
await _coursesClient.AddStudentInGroup(courseId, groupId, userId);
return Ok();
}

[HttpPost("{courseId}/removeStudentFromGroup/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> RemoveStudentFromGroup(long courseId, long groupId, [FromQuery] string userId)
{
await _coursesClient.RemoveStudentFromGroup(courseId, groupId, userId);
return Ok();
}
[HttpPost("{courseId}/removeStudentFromGroup/{groupId}")]
[Authorize(Roles = Roles.LecturerRole)]
public async Task<IActionResult> RemoveStudentFromGroup(long courseId, long groupId, [FromQuery] string userId)
{
await _coursesClient.RemoveStudentFromGroup(courseId, groupId, userId);
return Ok();
}

[HttpGet("get/{groupId}")]
[ProducesResponseType(typeof(GroupViewModel), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetGroup(long groupId)
{
var result = (await _coursesClient.GetGroupsById(groupId)).FirstOrDefault();
return result == null
? NotFound() as IActionResult
: Ok(result);
}
[HttpGet("get/{groupId}")]
[ProducesResponseType(typeof(GroupViewModel), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetGroup(long groupId)
{
var result = (await _coursesClient.GetGroupsById(groupId)).FirstOrDefault();
return result == null
? NotFound()
: Ok(result);
}

[HttpGet("getTasks/{groupId}")]
[ProducesResponseType(typeof(long[]), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetGroupTasks(long groupId)
{
var result = await _coursesClient.GetGroupTasks(groupId);
return Ok(result);
}
[HttpGet("getTasks/{groupId}")]
[ProducesResponseType(typeof(long[]), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetGroupTasks(long groupId)
{
var result = await _coursesClient.GetGroupTasks(groupId);
return Ok(result);
}
}
Loading