From ac309245d21f16c06abe2d1d9bb260e094d0805e Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 27 Apr 2021 19:37:11 +0800 Subject: refactor: ... --- .../Timeline/Services/User/UserAvatarService.cs | 266 --------------------- 1 file changed, 266 deletions(-) delete mode 100644 BackEnd/Timeline/Services/User/UserAvatarService.cs (limited to 'BackEnd/Timeline/Services/User/UserAvatarService.cs') diff --git a/BackEnd/Timeline/Services/User/UserAvatarService.cs b/BackEnd/Timeline/Services/User/UserAvatarService.cs deleted file mode 100644 index 9f59624d..00000000 --- a/BackEnd/Timeline/Services/User/UserAvatarService.cs +++ /dev/null @@ -1,266 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using SixLabors.ImageSharp; -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Timeline.Entities; -using Timeline.Helpers.Cache; -using Timeline.Models; -using Timeline.Services.Data; -using Timeline.Services.Imaging; - -namespace Timeline.Services.User -{ - /// - /// Provider for default user avatar. - /// - /// - /// Mainly for unit tests. - /// - public interface IDefaultUserAvatarProvider - { - /// - /// Get the digest of default avatar. - /// - /// The digest. - Task GetDefaultAvatarDigest(); - - /// - /// Get the default avatar. - /// - /// The avatar. - Task GetDefaultAvatar(); - } - - public interface IUserAvatarService - { - /// - /// Get avatar digest of a user. - /// - /// User id. - /// The avatar digest. - /// Thrown when user does not exist. - Task GetAvatarDigest(long userId); - - /// - /// Get avatar of a user. If the user has no avatar set, a default one is returned. - /// - /// User id. - /// The avatar. - /// Thrown when user does not exist. - Task GetAvatar(long userId); - - /// - /// Set avatar for a user. - /// - /// User id. - /// The new avatar data. - /// The digest of the avatar. - /// Thrown if is null. - /// Thrown when user does not exist. - /// Thrown if avatar is of bad format. - Task SetAvatar(long userId, ByteData avatar); - - /// - /// Remove avatar of a user. - /// - /// User id. - /// Thrown when user does not exist. - Task DeleteAvatar(long userId); - } - - // TODO! : Make this configurable. - public class DefaultUserAvatarProvider : IDefaultUserAvatarProvider - { - private readonly IETagGenerator _eTagGenerator; - - private readonly string _avatarPath; - - private CacheableDataDigest? _cacheDigest; - private ByteData? _cacheData; - - public DefaultUserAvatarProvider(IWebHostEnvironment environment, IETagGenerator eTagGenerator) - { - _avatarPath = Path.Combine(environment.ContentRootPath, "default-avatar.png"); - _eTagGenerator = eTagGenerator; - } - - private async Task CheckAndInit() - { - var path = _avatarPath; - if (_cacheData == null || File.GetLastWriteTime(path) > _cacheDigest!.LastModified) - { - var data = await File.ReadAllBytesAsync(path); - _cacheDigest = new CacheableDataDigest(await _eTagGenerator.GenerateETagAsync(data), File.GetLastWriteTime(path)); - Image.Identify(data, out var format); - _cacheData = new ByteData(data, format.DefaultMimeType); - } - } - - public async Task GetDefaultAvatarDigest() - { - await CheckAndInit(); - return _cacheDigest!; - } - - public async Task GetDefaultAvatar() - { - await CheckAndInit(); - return _cacheData!; - } - } - - public class UserAvatarService : IUserAvatarService - { - private readonly ILogger _logger; - private readonly DatabaseContext _database; - private readonly IBasicUserService _basicUserService; - private readonly IDefaultUserAvatarProvider _defaultUserAvatarProvider; - private readonly IImageService _imageValidator; - private readonly IDataManager _dataManager; - private readonly IClock _clock; - - public UserAvatarService( - ILogger logger, - DatabaseContext database, - IBasicUserService basicUserService, - IDefaultUserAvatarProvider defaultUserAvatarProvider, - IImageService imageValidator, - IDataManager dataManager, - IClock clock) - { - _logger = logger; - _database = database; - _basicUserService = basicUserService; - _defaultUserAvatarProvider = defaultUserAvatarProvider; - _imageValidator = imageValidator; - _dataManager = dataManager; - _clock = clock; - } - - public async Task GetAvatarDigest(long userId) - { - var usernameChangeTime = await _basicUserService.GetUsernameLastModifiedTimeAsync(userId); - - var entity = await _database.UserAvatars.Where(a => a.UserId == userId).Select(a => new { a.DataTag, a.LastModified }).SingleOrDefaultAsync(); - - if (entity is null) - { - var defaultAvatarDigest = await _defaultUserAvatarProvider.GetDefaultAvatarDigest(); - return new CacheableDataDigest(defaultAvatarDigest.ETag, new DateTime[] { usernameChangeTime, defaultAvatarDigest.LastModified }.Max()); - } - else if (entity.DataTag is null) - { - var defaultAvatarDigest = await _defaultUserAvatarProvider.GetDefaultAvatarDigest(); - return new CacheableDataDigest(defaultAvatarDigest.ETag, new DateTime[] { usernameChangeTime, defaultAvatarDigest.LastModified, entity.LastModified }.Max()); - } - else - { - return new CacheableDataDigest(entity.DataTag, new DateTime[] { usernameChangeTime, entity.LastModified }.Max()); - } - } - - public async Task GetAvatar(long userId) - { - await _basicUserService.ThrowIfUserNotExist(userId); - - var entity = await _database.UserAvatars.Where(a => a.UserId == userId).SingleOrDefaultAsync(); - - if (entity is null || entity.DataTag is null) - { - return await _defaultUserAvatarProvider.GetDefaultAvatar(); - } - - var data = await _dataManager.GetEntryAndCheck(entity.DataTag, $"This is required by avatar of {userId}."); - - if (entity.Type is null) - { - Image.Identify(data, out var format); - entity.Type = format.DefaultMimeType; - await _database.SaveChangesAsync(); - } - - return new ByteData(data, entity.Type); - } - - public async Task SetAvatar(long userId, ByteData avatar) - { - if (avatar is null) - throw new ArgumentNullException(nameof(avatar)); - - await _imageValidator.ValidateAsync(avatar.Data, avatar.ContentType, true); - - await _basicUserService.ThrowIfUserNotExist(userId); - - var entity = await _database.UserAvatars.Where(a => a.UserId == userId).SingleOrDefaultAsync(); - - await using var transaction = await _database.Database.BeginTransactionAsync(); - - var tag = await _dataManager.RetainEntryAsync(avatar.Data); - - var now = _clock.GetCurrentTime(); - - if (entity is null) - { - var newEntity = new UserAvatarEntity - { - DataTag = tag, - Type = avatar.ContentType, - LastModified = now, - UserId = userId - }; - _database.Add(newEntity); - } - else - { - if (entity.DataTag is not null) - await _dataManager.FreeEntryAsync(entity.DataTag); - - entity.DataTag = tag; - entity.Type = avatar.ContentType; - entity.LastModified = now; - } - - await _database.SaveChangesAsync(); - - await transaction.CommitAsync(); - - return new CacheableDataDigest(tag, now); - } - - public async Task DeleteAvatar(long userId) - { - await _basicUserService.ThrowIfUserNotExist(userId); - - var entity = await _database.UserAvatars.Where(a => a.UserId == userId).SingleOrDefaultAsync(); - - if (entity is null || entity.DataTag is null) - return; - - await using var transaction = await _database.Database.BeginTransactionAsync(); - - await _dataManager.FreeEntryAsync(entity.DataTag); - - entity.DataTag = null; - entity.Type = null; - entity.LastModified = _clock.GetCurrentTime(); - - await _database.SaveChangesAsync(); - - await transaction.CommitAsync(); - } - } - - public static class UserAvatarServiceCollectionExtensions - { - public static void AddUserAvatarService(this IServiceCollection services) - { - services.AddScoped(); - services.AddScoped(); - } - } -} -- cgit v1.2.3