using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
using Timeline.Helpers;
using Timeline.Models.Validation;
using Timeline.Services.Exceptions;
using static Timeline.Resources.Services.UserService;
namespace Timeline.Services
{
public interface IUserDeleteService
{
///
/// Delete a user of given username.
///
/// Username of the user to delete. Can't be null.
/// True if user is deleted, false if user not exist.
/// Thrown if is null.
/// Thrown when is of bad format.
/// Thrown when deleting root user.
Task DeleteUser(string username);
}
public class UserDeleteService : IUserDeleteService
{
private readonly ILogger _logger;
private readonly DatabaseContext _databaseContext;
private readonly ITimelinePostService _timelinePostService;
private readonly UsernameValidator _usernameValidator = new UsernameValidator();
public UserDeleteService(ILogger logger, DatabaseContext databaseContext, ITimelinePostService timelinePostService)
{
_logger = logger;
_databaseContext = databaseContext;
_timelinePostService = timelinePostService;
}
public async Task DeleteUser(string username)
{
if (username == null)
throw new ArgumentNullException(nameof(username));
if (!_usernameValidator.Validate(username, out var message))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExceptionUsernameBadFormat, message), nameof(username));
}
var user = await _databaseContext.Users.Where(u => u.Username == username).SingleOrDefaultAsync();
if (user == null)
return false;
if (user.Id == 1)
throw new InvalidOperationOnRootUserException("Can't delete root user.");
await _timelinePostService.DeleteAllPostsOfUser(user.Id);
_databaseContext.Users.Remove(user);
await _databaseContext.SaveChangesAsync();
_logger.LogInformation(Log.Format(LogDatabaseRemove, ("Id", user.Id), ("Username", user.Username)));
return true;
}
}
}