Skip to content

Commit

Permalink
Merge pull request #66 from theImmortalCoders/dev
Browse files Browse the repository at this point in the history
Release 1.9
  • Loading branch information
pablitoo1 authored Nov 28, 2024
2 parents 88b31b8 + 3c3dd65 commit 8864a39
Show file tree
Hide file tree
Showing 46 changed files with 684 additions and 470 deletions.
7 changes: 7 additions & 0 deletions rag-2-backend/Infrastructure/Common/Model/SortDirection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace rag_2_backend.Infrastructure.Common.Model;

public enum SortDirection
{
Asc,
Desc
}
10 changes: 3 additions & 7 deletions rag-2-backend/Infrastructure/Dao/CourseDao.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#region

using HttpExceptions.Exceptions;
using Microsoft.EntityFrameworkCore;
using rag_2_backend.Infrastructure.Database;
using rag_2_backend.Infrastructure.Database.Entity;

Expand All @@ -10,14 +11,9 @@ namespace rag_2_backend.Infrastructure.Dao;

public class CourseDao(DatabaseContext dbContext)
{
public virtual Course GetCourseByIdOrThrow(int id)
public virtual async Task<Course> GetCourseByIdOrThrow(int id)
{
return dbContext.Courses.SingleOrDefault(u => u.Id == id) ??
return await dbContext.Courses.SingleOrDefaultAsync(u => u.Id == id) ??
throw new NotFoundException("Course not found");
}

public virtual List<Course> GetAllCourses()
{
return dbContext.Courses.ToList();
}
}
14 changes: 8 additions & 6 deletions rag-2-backend/Infrastructure/Dao/GameDao.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#region

using HttpExceptions.Exceptions;
using Microsoft.EntityFrameworkCore;
using rag_2_backend.Infrastructure.Database;
using rag_2_backend.Infrastructure.Database.Entity;

Expand All @@ -10,19 +11,20 @@ namespace rag_2_backend.Infrastructure.Dao;

public class GameDao(DatabaseContext dbContext)
{
public virtual Game GetGameByIdOrThrow(int id)
public virtual async Task<Game> GetGameByIdOrThrow(int id)
{
return dbContext.Games.SingleOrDefault(g => g.Id == id) ?? throw new NotFoundException("Game not found");
return await dbContext.Games.SingleOrDefaultAsync(g => g.Id == id) ??
throw new NotFoundException("Game not found");
}

public virtual Game GetGameByNameOrThrow(string gameName)
public virtual async Task<Game> GetGameByNameOrThrow(string gameName)
{
return dbContext.Games.SingleOrDefault(g => Equals(g.Name.ToLower(), gameName.ToLower()))
return await dbContext.Games.SingleOrDefaultAsync(g => Equals(g.Name.ToLower(), gameName.ToLower()))
?? throw new NotFoundException("Game not found");
}

public virtual List<Game> GetAllGames()
public virtual async Task<List<Game>> GetAllGames()
{
return dbContext.Games.ToList();
return await dbContext.Games.ToListAsync();
}
}
87 changes: 68 additions & 19 deletions rag-2-backend/Infrastructure/Dao/GameRecordDao.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,79 @@
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 async Task<List<GameRecordResponse>> GetRecordsByGameAndUser(
int gameId,
int userId,
bool? includeEmptyRecords,
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(includeEmptyRecords, endDateFrom, endDateTo, query);
query = SortGameRecords(sortDirection, sortBy, query);

return await Task.Run(() => query.AsEnumerable()
.Select(GameRecordMapper.Map)
.ToList();
.ToList());
}

public virtual List<GameRecord> GetGameRecordsByUserWithGame(int userId)
public virtual async Task<List<GameRecord>> GetGameRecordsByUserWithGame(int userId)
{
return dbContext.GameRecords
return await dbContext.GameRecords
.OrderBy(r => r.Started)
.Where(r => r.User.Id == userId)
.Include(recordedGame => recordedGame.Game)
.ToList();
.ToListAsync();
}

public virtual List<GameRecord> GetGameRecordsByGameWithUser(int gameId)
public virtual async Task<List<GameRecord>> GetGameRecordsByGameWithUser(int gameId)
{
return dbContext.GameRecords
return await dbContext.GameRecords
.OrderBy(r => r.Started)
.Where(r => r.Game.Id == gameId)
.Include(recordedGame => recordedGame.User)
.ToList();
.ToListAsync();
}

public virtual GameRecord GetRecordedGameById(int recordedGameId)
public virtual async Task<GameRecord> GetRecordedGameById(int recordedGameId)
{
return dbContext.GameRecords.Include(recordedGame => recordedGame.User)
return await dbContext.GameRecords.Include(recordedGame => recordedGame.User)
.Include(r => r.Game)
.SingleOrDefault(g => g.Id == recordedGameId)
.SingleOrDefaultAsync(g => g.Id == recordedGameId)
?? throw new NotFoundException("Game record not found");
}

public virtual double CountTotalStorageMb()
public virtual async Task<double> CountTotalStorageMb()
{
return dbContext.GameRecords
.Select(r => r.SizeMb)
.ToList()
return (await dbContext.GameRecords
.Select(r => r.SizeMb)
.ToListAsync())
.Sum();
}

public virtual int CountAllGameRecords()
public virtual async Task<int> CountAllGameRecords()
{
return dbContext.GameRecords.Count();
return await dbContext.GameRecords.CountAsync();
}

public virtual void PerformGameRecordTransaction(Game game, GameRecord gameRecord,
Expand Down Expand Up @@ -92,4 +107,38 @@ public virtual void PerformGameRecordTransaction(Game game, GameRecord gameRecor
throw;
}
}

//

private static IQueryable<GameRecord> FilterGameRecords(
bool? includeEmptyRecords,
DateTime? endDateFrom,
DateTime? endDateTo,
IQueryable<GameRecord> query
)
{
if (includeEmptyRecords is null or false)
query = query.Where(u => u.IsEmptyRecord == false);
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
};
}
}
13 changes: 7 additions & 6 deletions rag-2-backend/Infrastructure/Dao/RefreshTokenDao.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#region

using Microsoft.EntityFrameworkCore;
using rag_2_backend.Infrastructure.Database;
using rag_2_backend.Infrastructure.Database.Entity;

Expand All @@ -9,17 +10,17 @@ namespace rag_2_backend.Infrastructure.Dao;

public class RefreshTokenDao(DatabaseContext context)
{
public virtual void RemoveTokensForUser(User user)
public virtual async Task RemoveTokensForUser(User user)
{
var unusedTokens = context.RefreshTokens.Where(r => r.User.Id == user.Id).ToList();
var unusedTokens = await context.RefreshTokens.Where(r => r.User.Id == user.Id).ToListAsync();
context.RefreshTokens.RemoveRange(unusedTokens);
context.SaveChanges();
await context.SaveChangesAsync();
}

public virtual void RemoveTokenByToken(string token)
public virtual async Task RemoveTokenByToken(string token)
{
var unusedTokens = context.RefreshTokens.Where(r => r.Token == token).ToList();
var unusedTokens = await context.RefreshTokens.Where(r => r.Token == token).ToListAsync();
context.RefreshTokens.RemoveRange(unusedTokens);
context.SaveChanges();
await context.SaveChangesAsync();
}
}
14 changes: 7 additions & 7 deletions rag-2-backend/Infrastructure/Dao/UserDao.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ namespace rag_2_backend.Infrastructure.Dao;

public class UserDao(DatabaseContext context)
{
public virtual User GetUserByIdOrThrow(int id)
public virtual async Task<User> GetUserByIdOrThrow(int id)
{
return context.Users.SingleOrDefault(u => u.Id == id) ??
return await context.Users.SingleOrDefaultAsync(u => u.Id == id) ??
throw new NotFoundException("User not found");
}

public virtual User GetUserByEmailOrThrow(string email)
public virtual async Task<User> GetUserByEmailOrThrow(string email)
{
return context.Users
return await context.Users
.Include(u => u.Course)
.SingleOrDefault(u => u.Email == email) ??
.SingleOrDefaultAsync(u => u.Email == email) ??
throw new NotFoundException("User not found");
}

public virtual int CountUsers()
public virtual async Task<int> CountUsers()
{
return context.Users.Count();
return await context.Users.CountAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public class AccountConfirmationToken
{
[Key] [MaxLength(100)] public required string Token { get; init; }
public required DateTime Expiration { get; set; }
public required User User { get; init; }

[ForeignKey("UserId")] public required User User { get; init; }
}
7 changes: 5 additions & 2 deletions rag-2-backend/Infrastructure/Database/Entity/GameRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ namespace rag_2_backend.Infrastructure.Database.Entity;
public class GameRecord
{
[Key] public int Id { get; init; }
public required Game Game { get; init; }
public required User User { get; init; }

[ForeignKey("GameId")] public required Game Game { get; init; }

[ForeignKey("UserId")] public required User User { get; init; }

public required List<GameRecordValue> Values { get; init; }
public List<Player>? Players { get; init; }
public DateTime Started { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public class PasswordResetToken
{
[Key] [MaxLength(100)] public required string Token { get; init; }
public required DateTime Expiration { get; set; }
public required User User { get; init; }

[ForeignKey("UserId")] public required User User { get; init; }
}
3 changes: 2 additions & 1 deletion rag-2-backend/Infrastructure/Database/Entity/RefreshToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public class RefreshToken
{
[Key] [MaxLength(100)] public required string Token { get; init; }
public required DateTime Expiration { get; init; }
public required User User { get; init; }

[ForeignKey("UserId")] public required User User { get; init; }
}
4 changes: 3 additions & 1 deletion rag-2-backend/Infrastructure/Database/Entity/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public User(string email)
public int StudyCycleYearB { get; set; }
public bool Banned { get; set; }
public DateTime LastPlayed { get; set; }
public Course? Course { get; set; }

[ForeignKey("CourseId")] public Course? Course { get; set; }

[MaxLength(100)] public string? Group { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,28 @@ public class AdministrationController(
/// <response code="400">Cannot ban administrator</response>
[HttpPost("{userId:int}/ban-status")]
[Authorize(Roles = "Admin")]
public void ChangeBanStatus([Required] int userId, [Required] bool isBanned)
public async Task ChangeBanStatus([Required] int userId, [Required] bool isBanned)
{
administrationService.ChangeBanStatus(userId, isBanned);
await administrationService.ChangeBanStatus(userId, isBanned);
}

/// <summary>Change role for any user by user ID despite admins (Admin)</summary>
/// <response code="404">User not found</response>
/// <response code="400">Cannot change administrator's role</response>
[HttpPost("{userId:int}/role")]
[Authorize(Roles = "Admin")]
public void ChangeRole([Required] int userId, [Required] Role role)
public async Task ChangeRole([Required] int userId, [Required] Role role)
{
administrationService.ChangeRole(userId, role);
await administrationService.ChangeRole(userId, role);
}

/// <summary>Get details of any user by user ID (Admin, Teacher)</summary>
/// <response code="403">Cannot view details</response>
[HttpGet("{userId:int}/details")]
[Authorize(Roles = "Admin,Teacher")]
public UserResponse GetUserDetails([Required] int userId)
public async Task<UserResponse> GetUserDetails([Required] int userId)
{
return administrationService.GetUserDetails(AuthDao.GetPrincipalEmail(User), userId);
return await administrationService.GetUserDetails(AuthDao.GetPrincipalEmail(User), userId);
}

/// <summary>Get current limits for roles (Auth)</summary>
Expand All @@ -61,11 +61,29 @@ 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> GetStudents()
public async Task<List<UserResponse>> GetUsers(
[Required] Role role,
string? email,
int? studyCycleYearA,
int? studyCycleYearB,
string? group,
string? courseName,
SortDirection sortDirection = SortDirection.Asc,
UserSortByFields sortBy = UserSortByFields.Id
)
{
return administrationService.GetStudents();
return await administrationService.GetUsers(
role,
email,
studyCycleYearA,
studyCycleYearB,
group,
courseName,
sortDirection,
sortBy
);
}
}
Loading

0 comments on commit 8864a39

Please sign in to comment.