Files
Disco/Disco.Services/Plugins/Features/DetailsProvider/DetailsProviderService.cs
T
2023-04-14 16:37:42 +10:00

108 lines
3.8 KiB
C#

using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace Disco.Services.Plugins.Features.DetailsProvider
{
public class DetailsProviderService
{
private const string DetailsScope = "Details";
private readonly DiscoDataContext database;
public DetailsProviderService(DiscoDataContext database)
{
this.database = database;
}
public bool HasUserPhoto(User user)
{
var cachePath = GetUserPhotoCachePath(user);
if (File.Exists(cachePath))
return true;
// slow-path: this should only happen once,
// the first time, before we cache
var photo = GetUserPhoto(user);
return photo != null;
}
public byte[] GetUserPhoto(User user)
{
var cachePath = GetUserPhotoCachePath(user);
var cacheAge = default(DateTime?);
if (File.Exists(cachePath))
cacheAge = File.GetLastWriteTime(cachePath);
var features = Plugins.GetPluginFeatures(typeof(DetailsProviderFeature));
foreach (var feature in features)
{
var instance = feature.CreateInstance<DetailsProviderFeature>();
var result = instance.GetUserPhoto(database, user, cacheAge);
if (result != null)
{
// resize image
using (var originalStream = new MemoryStream(result))
{
using (var originalImage = Image.FromStream(originalStream))
{
using (var resizedImage = originalImage.ResizeImage(192, Brushes.White))
{
using (var savedResizedImage = (MemoryStream)resizedImage.SaveJpg(85))
{
result = savedResizedImage.ToArray();
}
}
}
}
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
File.WriteAllBytes(cachePath, result);
return result;
}
}
// serve from cache
if (cacheAge.HasValue)
return File.ReadAllBytes(cachePath);
return null;
}
private string GetUserPhotoCachePath(User user)
{
var hasher = new SHA1Managed();
var userHash = BitConverter.ToString(hasher.ComputeHash(Encoding.UTF8.GetBytes(user.UserId))).Replace("-", string.Empty);
return Path.Combine(database.DiscoConfiguration.PluginUserPhotosLocation, userHash.Substring(0, 2), $"{userHash}.jpg");
}
public Dictionary<string, string> GetDetails(User user)
{
if (!UserService.CurrentAuthorization.HasAll(Claims.User.Show, Claims.User.ShowDetails))
return new Dictionary<string, string>();
if (user.UserDetails != null)
{
return user.UserDetails
.Where(d => string.Equals(d.Scope, DetailsScope, StringComparison.Ordinal))
.ToDictionary(d => d.Key, d => d.Value, StringComparer.OrdinalIgnoreCase);
} else
{
return database.UserDetails
.Where(d => d.UserId == user.UserId &&
d.Scope == DetailsScope)
.ToDictionary(d => d.Key, d => d.Value, StringComparer.OrdinalIgnoreCase);
}
}
}
}