Skip to content

Commit

Permalink
Merge pull request #63 from theImmortalCoders/issue-56
Browse files Browse the repository at this point in the history
Issue 56
  • Loading branch information
marcinbator authored Nov 21, 2024
2 parents 9d1b888 + 1f44ab8 commit 14a0fc1
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 29 deletions.
55 changes: 52 additions & 3 deletions rag-2-backend/Infrastructure/Dao/GameRecordDao.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,38 @@
using Microsoft.EntityFrameworkCore;
using Npgsql;
using rag_2_backend.Infrastructure.Common.Mapper;
using rag_2_backend.Infrastructure.Common.Model;
using rag_2_backend.Infrastructure.Database;
using rag_2_backend.Infrastructure.Database.Entity;
using rag_2_backend.Infrastructure.Module.GameRecord.Dto;
using rag_2_backend.Infrastructure.Util;

#endregion

namespace rag_2_backend.Infrastructure.Dao;

public class GameRecordDao(DatabaseContext dbContext)
{
public virtual List<GameRecordResponse> GetRecordsByGameAndUser(int gameId, int userId)
public virtual List<GameRecordResponse> GetRecordsByGameAndUser(
int gameId,
int userId,
bool? isEmptyRecord,
DateTime? endDateFrom,
DateTime? endDateTo,
SortDirection sortDirection,
GameRecordSortByFields sortBy
)
{
return dbContext.GameRecords
var query = dbContext.GameRecords
.Include(r => r.Game)
.Include(r => r.User)
.Where(r => r.Game.Id == gameId && r.User.Id == userId)
.ToList()
.AsQueryable();

query = FilterGameRecords(isEmptyRecord, endDateFrom, endDateTo, query);
query = SortGameRecords(sortDirection, sortBy, query);

return query.AsEnumerable()
.Select(GameRecordMapper.Map)
.ToList();
}
Expand Down Expand Up @@ -92,4 +107,38 @@ public virtual void PerformGameRecordTransaction(Game game, GameRecord gameRecor
throw;
}
}

//

private static IQueryable<GameRecord> FilterGameRecords(
bool? isEmptyRecord,
DateTime? endDateFrom,
DateTime? endDateTo,
IQueryable<GameRecord> query
)
{
if (isEmptyRecord.HasValue)
query = query.Where(u => u.IsEmptyRecord == isEmptyRecord);
if (endDateFrom.HasValue)
query = query.Where(u => u.Ended >= endDateFrom);
if (endDateTo.HasValue)
query = query.Where(u => u.Ended <= endDateTo);

return query;
}

private static IQueryable<GameRecord> SortGameRecords(
SortDirection sortDirection,
GameRecordSortByFields sortBy,
IQueryable<GameRecord> query
)
{
return sortBy switch
{
GameRecordSortByFields.Id => DataSortingUtil.ApplySorting(query, x => x.Id, sortDirection),
GameRecordSortByFields.Ended => DataSortingUtil.ApplySorting(query, x => x.Ended, sortDirection),
GameRecordSortByFields.SizeMb => DataSortingUtil.ApplySorting(query, x => x.SizeMb, sortDirection),
_ => query
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ public LimitsResponse GetCurrentLimits()
};
}

/// <summary>Get all users list (Admin, Teacher)</summary>
/// <summary>Get all users list with optional filters and sorting (Admin, Teacher)</summary>
[HttpGet("users")]
[Authorize(Roles = "Admin, Teacher")]
public List<UserResponse> GetUsers(
[Required] Role role,
string? email,
int? studyCycleYearA,
int? studyCycleYearB,
Expand All @@ -75,6 +76,7 @@ public List<UserResponse> GetUsers(
)
{
return administrationService.GetUsers(
role,
email,
studyCycleYearA,
studyCycleYearB,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#region

using System.Linq.Expressions;
using HttpExceptions.Exceptions;
using Microsoft.EntityFrameworkCore;
using rag_2_backend.Infrastructure.Common.Mapper;
Expand All @@ -9,6 +8,7 @@
using rag_2_backend.Infrastructure.Database;
using rag_2_backend.Infrastructure.Module.Administration.Dto;
using rag_2_backend.Infrastructure.Module.User.Dto;
using rag_2_backend.Infrastructure.Util;

#endregion

Expand Down Expand Up @@ -49,6 +49,7 @@ public UserResponse GetUserDetails(string principalEmail, int userId)
}

public List<UserResponse> GetUsers(
Role role,
string? email,
int? studyCycleYearA,
int? studyCycleYearB,
Expand All @@ -58,7 +59,10 @@ public List<UserResponse> GetUsers(
UserSortByFields sortBy
)
{
var query = context.Users.Include(u => u.Course).AsQueryable();
var query = context.Users
.Include(u => u.Course)
.Where(u => u.Role == role)
.AsQueryable();

query = FilterUsers(email, studyCycleYearA, studyCycleYearB, group, courseName, query);
query = SortUsers(sortDirection, sortBy, query);
Expand Down Expand Up @@ -92,22 +96,19 @@ UserSortByFields sortBy
{
return sortBy switch
{
UserSortByFields.Id => ApplySorting(query, x => x.Id, sortDirection),
UserSortByFields.Email => ApplySorting(query, x => x.Email, sortDirection),
UserSortByFields.Name => ApplySorting(query, x => x.Name, sortDirection),
UserSortByFields.StudyYearCycleA => ApplySorting(query, x => x.StudyCycleYearA, sortDirection),
UserSortByFields.StudyYearCycleB => ApplySorting(query, x => x.StudyCycleYearB, sortDirection),
UserSortByFields.LastPlayed => ApplySorting(query, x => x.LastPlayed, sortDirection),
UserSortByFields.CourseName => ApplySorting(query, x => x.Course != null ? x.Course.Name : string.Empty,
UserSortByFields.Id => DataSortingUtil.ApplySorting(query, x => x.Id, sortDirection),
UserSortByFields.Email => DataSortingUtil.ApplySorting(query, x => x.Email, sortDirection),
UserSortByFields.Name => DataSortingUtil.ApplySorting(query, x => x.Name, sortDirection),
UserSortByFields.StudyYearCycleA => DataSortingUtil.ApplySorting(query, x => x.StudyCycleYearA,
sortDirection),
UserSortByFields.Group => ApplySorting(query, x => x.Group, sortDirection),
UserSortByFields.StudyYearCycleB => DataSortingUtil.ApplySorting(query, x => x.StudyCycleYearB,
sortDirection),
UserSortByFields.LastPlayed => DataSortingUtil.ApplySorting(query, x => x.LastPlayed, sortDirection),
UserSortByFields.CourseName => DataSortingUtil.ApplySorting(query,
x => x.Course != null ? x.Course.Name : string.Empty,
sortDirection),
UserSortByFields.Group => DataSortingUtil.ApplySorting(query, x => x.Group, sortDirection),
_ => query
};
}

private static IQueryable<T> ApplySorting<T, TKey>(IQueryable<T> query, Expression<Func<T, TKey>> keySelector,
SortDirection sortDirection)
{
return sortDirection == SortDirection.Desc ? query.OrderByDescending(keySelector) : query.OrderBy(keySelector);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace rag_2_backend.Infrastructure.Module.GameRecord.Dto;

public enum GameRecordSortByFields
{
Id,
Ended,
SizeMb
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using rag_2_backend.Infrastructure.Common.Model;
using rag_2_backend.Infrastructure.Dao;
using rag_2_backend.Infrastructure.Module.GameRecord.Dto;

Expand All @@ -18,11 +19,28 @@ public class GameRecordController(GameRecordService gameRecordService) : Control
/// <response code="404">User or game not found</response>
[HttpGet]
[Authorize]
public List<GameRecordResponse> GetRecordsByGame([Required] int gameId, [Required] int userId)
public List<GameRecordResponse> GetRecordsByGame(
[Required] int gameId,
[Required] int userId,
bool? isEmptyRecord,
DateTime? endDateFrom,
DateTime? endDateTo,
SortDirection sortDirection = SortDirection.Asc,
GameRecordSortByFields sortBy = GameRecordSortByFields.Id
)
{
var email = AuthDao.GetPrincipalEmail(User);

return gameRecordService.GetRecordsByGameAndUser(gameId, userId, email);
return gameRecordService.GetRecordsByGameAndUser(
gameId,
userId,
isEmptyRecord,
endDateFrom,
endDateTo,
sortDirection,
sortBy,
email
);
}

/// <summary>Download JSON file from specific game, admin and teacher can download everyone's data (Auth)</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,31 @@ public class GameRecordService(
GameDao gameDao
)
{
public List<GameRecordResponse> GetRecordsByGameAndUser(int gameId, int userId, string email)
public List<GameRecordResponse> GetRecordsByGameAndUser(
int gameId,
int userId,
bool? isEmptyRecord,
DateTime? endDateFrom,
DateTime? endDateTo,
SortDirection sortDirection,
GameRecordSortByFields sortBy,
string email
)
{
var principal = userDao.GetUserByEmailOrThrow(email);

if (principal.Id != userId && principal.Role.Equals(Role.Student))
throw new BadRequestException("Permission denied");

return gameRecordDao.GetRecordsByGameAndUser(gameId, userId);
return gameRecordDao.GetRecordsByGameAndUser(
gameId,
userId,
isEmptyRecord,
endDateFrom,
endDateTo,
sortDirection,
sortBy
);
}

public byte[] DownloadRecordData(int recordedGameId, string email)
Expand Down
17 changes: 17 additions & 0 deletions rag-2-backend/Infrastructure/Util/DataSortingUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#region

using System.Linq.Expressions;
using rag_2_backend.Infrastructure.Common.Model;

#endregion

namespace rag_2_backend.Infrastructure.Util;

public static class DataSortingUtil
{
public static IQueryable<T> ApplySorting<T, TKey>(IQueryable<T> query, Expression<Func<T, TKey>> keySelector,
SortDirection sortDirection)
{
return sortDirection == SortDirection.Desc ? query.OrderByDescending(keySelector) : query.OrderBy(keySelector);
}
}
11 changes: 10 additions & 1 deletion rag-2-backend/Test/Dao/GameRecordDaoTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
using HttpExceptions.Exceptions;
using Microsoft.EntityFrameworkCore;
using Moq;
using rag_2_backend.Infrastructure.Common.Model;
using rag_2_backend.Infrastructure.Dao;
using rag_2_backend.Infrastructure.Database;
using rag_2_backend.Infrastructure.Database.Entity;
using rag_2_backend.Infrastructure.Module.GameRecord.Dto;
using Xunit;

#endregion
Expand Down Expand Up @@ -64,7 +66,14 @@ public void GetRecordsByGameAndUser_ShouldReturnRecords_WhenRecordsExist()
};
SetUpGameRecordsDbSet(new List<GameRecord> { gameRecord });

var result = _gameRecordDao.GetRecordsByGameAndUser(gameId, 1);
var result = _gameRecordDao.GetRecordsByGameAndUser(
gameId,
1,
null,
null,
null, SortDirection.Asc,
GameRecordSortByFields.Id
);

Assert.Single(result);
}
Expand Down
3 changes: 2 additions & 1 deletion rag-2-backend/Test/Service/AdministrationServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ public void ShouldGetStudents()

Assert.Equal(
JsonConvert.SerializeObject(response),
JsonConvert.SerializeObject(_administrationService.GetUsers(null, null, null, null, null, SortDirection.Asc,
JsonConvert.SerializeObject(_administrationService.GetUsers(Role.Admin, null, null, null, null, null,
SortDirection.Asc,
UserSortByFields.Id)[0])
);
}
Expand Down
21 changes: 18 additions & 3 deletions rag-2-backend/Test/Service/GameRecordServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,24 @@ public void GetRecordsByGameAndUser_ShouldReturnGameRecords()
Name = null!
};
_userDaoMock.Setup(dao => dao.GetUserByEmailOrThrow(email)).Returns(user);
_gameRecordDaoMock.Setup(dao => dao.GetRecordsByGameAndUser(gameId, 1)).Returns(records);

var result = _gameRecordService.GetRecordsByGameAndUser(gameId, 1, email);
_gameRecordDaoMock.Setup(dao => dao.GetRecordsByGameAndUser(
gameId,
1,
null,
null,
null, SortDirection.Asc,
GameRecordSortByFields.Id
)).Returns(records);

var result = _gameRecordService.GetRecordsByGameAndUser(
gameId,
1,
null,
null,
null, SortDirection.Asc,
GameRecordSortByFields.Id,
email
);

Assert.Equal(records, result);
}
Expand Down

0 comments on commit 14a0fc1

Please sign in to comment.