You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
326 lines
15 KiB
326 lines
15 KiB
using Dto;
|
|
using Dto.Tiny;
|
|
using Microsoft.Extensions.Logging;
|
|
using Model;
|
|
using Model.Repository;
|
|
using Shared;
|
|
using EFMappers;
|
|
using Entities;
|
|
using Entities2Dto;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Model2Entities;
|
|
|
|
public partial class DbDataManager
|
|
{
|
|
public class UserRepository : IUserRepository
|
|
{
|
|
private readonly DbDataManager _dataManager;
|
|
private readonly ILogger<DbDataManager> _logger;
|
|
|
|
public UserRepository(DbDataManager dbDataManager, ILogger<DbDataManager> logger)
|
|
{
|
|
_dataManager = dbDataManager;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<IEnumerable<User>> GetItems(int index, int count, string? orderingProperty = null,
|
|
bool descending = false)
|
|
=> await GetUsers(index, count, this.ToEnum(orderingProperty), descending);
|
|
|
|
public async Task<IEnumerable<User>> GetUsers(int index, int count,
|
|
AthleteOrderCriteria? orderingProperty = null, bool descending = false)
|
|
{
|
|
|
|
_logger.LogInformation($"GetItems with index {index} and count {count}", index, count);
|
|
_logger.LogInformation($"GetItems with orderingProperty {orderingProperty} and descending {descending}",
|
|
orderingProperty, descending);
|
|
var users = _dataManager.DbContext.AthletesSet.IncludeStandardProperties().GetItemsWithFilterAndOrdering(b => true, index, count,
|
|
orderingProperty != AthleteOrderCriteria.None ? orderingProperty : null, descending).ToModels();
|
|
_logger.LogInformation($"Retrieved {users.Count()} users");
|
|
return await Task.FromResult(users);
|
|
|
|
}
|
|
|
|
public async Task<IEnumerable<UserTinyDto>?> GetUsersTiny(int index, int count, AthleteOrderCriteria? criteria, bool descending = false)
|
|
{
|
|
|
|
var users = _dataManager.DbContext.AthletesSet.GetItemsWithFilterAndOrdering(b => true,
|
|
index, count,
|
|
criteria != AthleteOrderCriteria.None ? criteria : null, descending);
|
|
_logger.LogInformation($"Retrieved {users.Count()} users");
|
|
return await Task.FromResult(users.ToTinyDtos());
|
|
}
|
|
|
|
public async Task<User?> GetItemById(int id)
|
|
{
|
|
|
|
_logger.LogInformation($"GetItemById with id {id}", id);
|
|
var userEntity = await _dataManager.DbContext.AthletesSet.IncludeStandardProperties()
|
|
.SingleOrDefaultAsync(a => a.Id == id);
|
|
var user = userEntity != null ? userEntity.ToModel() : null;
|
|
if (user != null)
|
|
_logger.LogInformation($"Retrieved user with ID {id}");
|
|
else
|
|
_logger.LogWarning($"No user found with ID {id}");
|
|
return await Task.FromResult(user);
|
|
|
|
}
|
|
|
|
public async Task<UserTinyDto?> UpdateUser(int old, UserTinyDto user)
|
|
{
|
|
_logger.LogInformation($"UpdateUser with id {old}", old);
|
|
var originalEntity = _dataManager.DbContext.AthletesSet.Find(old);
|
|
if (originalEntity == null)
|
|
{
|
|
_logger.LogWarning($"No user found with ID {old}");
|
|
return await Task.FromResult<UserTinyDto?>(null);
|
|
}
|
|
var originalEntry = _dataManager.DbContext.Entry(originalEntity);
|
|
var values = typeof(AthleteEntity).GetProperties().Where(ppty => ppty.Name != "IdAthlete")
|
|
.ToDictionary(ppty => ppty.Name, ppty => ppty.GetValue(user.ToEntity()));
|
|
originalEntry.CurrentValues.SetValues(values);
|
|
_dataManager.DbContext.AthletesSet.Attach(originalEntity);
|
|
_dataManager.DbContext.Entry(originalEntity).State = EntityState.Modified;
|
|
_dataManager.DbContext.SaveChanges();
|
|
var updatedUser = originalEntity.ToTinyDto();
|
|
if (updatedUser != null)
|
|
_logger.LogInformation($"Updated user with ID {old}");
|
|
else
|
|
_logger.LogWarning($"No user found with ID {old}");
|
|
return await Task.FromResult(updatedUser);
|
|
}
|
|
|
|
public async Task<ResponseUserDto> GetUserById(int id)
|
|
{
|
|
_logger.LogInformation($"GetTinyItemById with id {id}", id);
|
|
var userEntity = await _dataManager.DbContext.AthletesSet.IncludeStandardProperties().Include(a => a.Followers).Include(a => a.Followings)
|
|
.SingleOrDefaultAsync(a => a.Id == id);
|
|
var user = userEntity != null ? userEntity.ToResponseDto() : null;
|
|
if (user != null)
|
|
_logger.LogInformation($"Retrieved user with ID {id}");
|
|
else
|
|
_logger.LogWarning($"No user found with ID {id}");
|
|
return user;
|
|
}
|
|
|
|
public async Task<User?> UpdateItem(int oldItem, User newItem)
|
|
{
|
|
_logger.LogInformation($"UpdateItem with id {oldItem}", oldItem);
|
|
|
|
var originalEntity = _dataManager.DbContext.AthletesSet.Find(oldItem);
|
|
if (originalEntity == null)
|
|
{
|
|
_logger.LogWarning($"No user found with ID {oldItem}");
|
|
return await Task.FromResult<User?>(null);
|
|
}
|
|
var originalEntry = _dataManager.DbContext.Entry(originalEntity);
|
|
var values = typeof(AthleteEntity).GetProperties().Where(ppty => ppty.Name != "IdAthlete")
|
|
.ToDictionary(ppty => ppty.Name, ppty => ppty.GetValue(newItem.ToEntity()));
|
|
originalEntry.CurrentValues.SetValues(values);
|
|
_dataManager.DbContext.AthletesSet.Attach(originalEntity);
|
|
_dataManager.DbContext.Entry(originalEntity).State = EntityState.Modified;
|
|
_dataManager.DbContext.SaveChanges();
|
|
var updatedUser = originalEntity.ToModel();
|
|
if (updatedUser != null)
|
|
_logger.LogInformation($"Updated user with ID {oldItem}");
|
|
else
|
|
_logger.LogWarning($"No user found with ID {oldItem}");
|
|
return await Task.FromResult(updatedUser);
|
|
}
|
|
|
|
public async Task<User?> AddItem(User item)
|
|
{
|
|
|
|
_logger.LogInformation("Adding new user");
|
|
var addedUser = (await _dataManager.DbContext.AddItem(item.ToEntity()))?.ToModel();
|
|
if (addedUser != null)
|
|
_logger.LogInformation($"Added user with ID {addedUser.Id}");
|
|
else
|
|
_logger.LogError("Failed to add user");
|
|
return await Task.FromResult(addedUser);
|
|
|
|
}
|
|
|
|
public async Task<bool> DeleteItem(int item)
|
|
{
|
|
|
|
_logger.LogInformation($"DeleteItem with id {item}", item);
|
|
var deleted = await _dataManager.DbContext.DeleteItem<AthleteEntity>(item);
|
|
if (deleted)
|
|
_logger.LogInformation($"Deleted user with ID {item}");
|
|
else
|
|
_logger.LogWarning($"No user found with ID {item}");
|
|
return await Task.FromResult(deleted);
|
|
|
|
}
|
|
|
|
public async Task<int> GetNbItems()
|
|
{
|
|
_logger.LogInformation("GetNbItems");
|
|
var nbItems = await _dataManager.DbContext.AthletesSet.CountAsync();
|
|
_logger.LogInformation($"Retrieved {nbItems} users");
|
|
return await Task.FromResult(nbItems);
|
|
}
|
|
|
|
public async Task<IEnumerable<User>> GetAllAthletes(int index, int count, AthleteOrderCriteria? criteria,
|
|
bool descending = false)
|
|
{
|
|
|
|
_logger.LogInformation($"GetAllAthletes with index {index} and count {count}", index, count);
|
|
_logger.LogInformation($"GetAllAthletes with criteria {criteria} and descending {descending}", criteria,
|
|
descending);
|
|
var athletes = _dataManager.DbContext.AthletesSet.IncludeStandardProperties()
|
|
.GetItemsWithFilterAndOrdering(a => a.IsCoach == false, index, count,
|
|
criteria != AthleteOrderCriteria.None ? criteria : null, descending).ToModels();
|
|
_logger.LogInformation($"Retrieved {athletes.Count()} athletes");
|
|
return await Task.FromResult(athletes);
|
|
}
|
|
|
|
public async Task<IEnumerable<User>> GetAllCoaches(int index, int count, AthleteOrderCriteria? criteria,
|
|
bool descending = false)
|
|
{
|
|
|
|
_logger.LogInformation($"GetAllCoaches with index {index} and count {count}", index, count);
|
|
_logger.LogInformation($"GetAllCoaches with criteria {criteria} and descending {descending}", criteria,
|
|
descending);
|
|
var coaches = _dataManager.DbContext.AthletesSet.IncludeStandardProperties()
|
|
.GetItemsWithFilterAndOrdering(a => a.IsCoach, index, count,
|
|
criteria != AthleteOrderCriteria.None ? criteria : null, descending).ToModels();
|
|
_logger.LogInformation($"Retrieved {coaches.Count()} coaches");
|
|
return await Task.FromResult(coaches);
|
|
|
|
}
|
|
|
|
|
|
public async Task<bool> AddFollowing(int fromUser, int toUser)
|
|
{
|
|
_logger.LogInformation($"Attempting to add following: User {fromUser} adding Following {toUser}");
|
|
|
|
var userEntity = _dataManager.DbContext.AthletesSet
|
|
.Include(a => a.Followings)
|
|
.FirstOrDefault(a => a.Id == fromUser);
|
|
|
|
if (userEntity == null)
|
|
{
|
|
_logger.LogWarning($"User not found: User {fromUser}");
|
|
throw new FriendShipException("User with id " + fromUser + " not found");
|
|
}
|
|
|
|
if (userEntity.Followings.Any(f => f.FollowingId == toUser))
|
|
{
|
|
_logger.LogInformation($"Following already exists: User {fromUser} and Following {toUser}");
|
|
throw new FriendShipException("Following already exists");
|
|
}
|
|
await _dataManager.DbContext.SaveChangesAsync();
|
|
|
|
userEntity.Followings.Add(new FriendshipEntity
|
|
{
|
|
FollowingId = toUser,
|
|
FollowerId = fromUser,
|
|
StartDate = DateTime.Now
|
|
});
|
|
|
|
await _dataManager.DbContext.SaveChangesAsync();
|
|
|
|
_logger.LogInformation($"Successfully following: from User {fromUser} to Following {toUser}");
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> RemoveFollowing(int fromUser, int toUser){
|
|
_logger.LogInformation($"Attempting to remove following: User {fromUser} removing Following {toUser}");
|
|
|
|
var userEntity = _dataManager.DbContext.AthletesSet
|
|
.Include(a => a.Followings)
|
|
.FirstOrDefault(a => a.Id == fromUser);
|
|
|
|
if (userEntity == null)
|
|
{
|
|
_logger.LogWarning($"User not found: User {fromUser}");
|
|
throw new FriendShipException("User with id " + fromUser + " not found");
|
|
}
|
|
|
|
var friendship = userEntity.Followings.FirstOrDefault(f => f.FollowingId == toUser);
|
|
if (friendship == null)
|
|
{
|
|
_logger.LogInformation($"Following not found: User {fromUser} and Following {toUser}");
|
|
throw new FriendShipException("Following not found");
|
|
}
|
|
await _dataManager.DbContext.SaveChangesAsync();
|
|
|
|
userEntity.Followings.Remove(friendship);
|
|
|
|
await _dataManager.DbContext.SaveChangesAsync();
|
|
|
|
_logger.LogInformation($"Successfully removed following: from User {fromUser} to Following {toUser}");
|
|
return await Task.FromResult(true);
|
|
}
|
|
public async Task<IEnumerable<UserTinyDto>?> GetFriends(int userId, int index, int count, AthleteOrderCriteria? criteria,
|
|
bool descending = false)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation($"GetFriends called with index {index}, count {count}, criteria {criteria}, and descending {descending}");
|
|
|
|
var athlete = await _dataManager.DbContext.AthletesSet
|
|
.Include(a => a.Followers).ThenInclude(f => f.Follower)
|
|
.Include(a => a.Followings).ThenInclude(f => f.Following)
|
|
.FirstOrDefaultAsync(a => a.Id == userId); // Use async version for better performance
|
|
|
|
if (athlete == null)
|
|
{
|
|
_logger.LogError("Athlete with id {id} not found", userId);
|
|
throw new ModelNotFoundException($"Athlete with id {userId} not found");
|
|
}
|
|
|
|
var friendsDtos = athlete.Followings
|
|
.Where(f => athlete.Followers.Any(ff => ff.FollowerId == f.FollowingId))
|
|
.Select(f => f.Following).GetItemsWithFilterAndOrdering(a => true, index, count,
|
|
criteria != AthleteOrderCriteria.None ? criteria : null, descending).ToTinyDtos();
|
|
|
|
var userTinyDtos = friendsDtos.ToArray();
|
|
_logger.LogInformation($"Retrieved {userTinyDtos.Count()} friends for user {userId}");
|
|
|
|
return userTinyDtos;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex.Message, ex.InnerException, ex.StackTrace);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public async Task<int> GetNbFriends(int userId)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation($"GetNbFriends called for user {userId}");
|
|
|
|
var athlete = await _dataManager.DbContext.AthletesSet
|
|
.Include(a => a.Followers).ThenInclude(f => f.Follower)
|
|
.Include(a => a.Followings).ThenInclude(f => f.Following)
|
|
.FirstOrDefaultAsync(a => a.Id == userId);
|
|
|
|
if (athlete == null)
|
|
{
|
|
_logger.LogError("Athlete with id {id} not found", userId);
|
|
throw new ModelNotFoundException($"Athlete with id {userId} not found");
|
|
}
|
|
|
|
// Count the number of mutual friendships
|
|
var nbFriends = athlete.Followings
|
|
.Count(f => athlete.Followers.Any(ff => ff.FollowerId == f.FollowingId));
|
|
|
|
_logger.LogInformation($"User {userId} has {nbFriends} friends");
|
|
|
|
return nbFriends;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "An error occurred while counting friends for user {UserId}", userId);
|
|
throw; // Consider handling the exception outside of this method or logging it accordingly.
|
|
}
|
|
}
|
|
|
|
}
|
|
} |