namespace Dpz.Core.Service;
public class EmailConfigService
{
private readonly IRepository<EmailConfig> _repository;
private readonly IMapper _mapper;
public EmailConfigService(IRepository<EmailConfig> repository,IMapper mapper)
{
_repository = repository;
_mapper = mapper;
}
#region AES加解密
/// <summary>
/// AES加密
/// </summary>
/// <param name="text"></param>
/// <param name="key"></param>
/// <returns></returns>
private async Task<string> EncryptAes(string text, string key)
{
if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text));
if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key));
var encryptKey = Encoding.UTF8.GetBytes(key);
using var aesAlg = Aes.Create();
aesAlg.Padding = PaddingMode.PKCS7;
using var encryptor = aesAlg.CreateEncryptor(encryptKey, aesAlg.IV);
await using var msEncrypt = new MemoryStream();
await using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
await using (var swEncrypt = new StreamWriter(csEncrypt))
{
await swEncrypt.WriteAsync(text);
}
var iv = aesAlg.IV;
var decryptedContent = msEncrypt.ToArray();
var result = new byte[iv.Length + decryptedContent.Length];
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
Buffer.BlockCopy(decryptedContent, 0, result, iv.Length, decryptedContent.Length);
return Convert.ToBase64String(result);
}
/// <summary>
/// AES解密
/// </summary>
/// <param name="text"></param>
/// <param name="key"></param>
/// <returns></returns>
private async Task<string> DecryptAes(string text, string key)
{
if (string.IsNullOrEmpty(text)) throw new ArgumentNullException(nameof(text));
if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key));
var fullCipher = Convert.FromBase64String(text);
var iv = new byte[16];
var cipher = new byte[fullCipher.Length - iv.Length];
Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, fullCipher.Length - iv.Length);
var decryptKey = Encoding.UTF8.GetBytes(key);
using var aesAlg = Aes.Create();
aesAlg.Padding = PaddingMode.PKCS7;
using var decryptor = aesAlg.CreateDecryptor(decryptKey, iv);
await using var msDecrypt = new MemoryStream(cipher);
await using var csDecrypt = new CryptoStream(msDecrypt,
decryptor, CryptoStreamMode.Read);
using var srDecrypt = new StreamReader(csDecrypt);
var result = await srDecrypt.ReadToEndAsync();
return result;
}
#endregion
public async Task Add(VmEmailConfig viewModel)
{
var config = _repository.SearchFor(x => x.EmailName == viewModel.EmailName).FirstOrDefault();
if (config != null)
{
throw new Exception($"邮箱别名“{viewModel.EmailName}”已存在");
}
var model = _mapper.Map<EmailConfig>(viewModel);
model.Id = ObjectId.GenerateNewId();
model.Password = await EncryptAes(model.Password, model.Id.ToString());
await _repository.InsertAsync(model);
}
public async Task<string?> GetClearPassword(string id)
{
var model = await _repository.TryGetAsync(id);
if (model == null) return null;
var clearText = await DecryptAes(model.Password, id);
return clearText;
}
public async Task<List<VmEmailConfig>> GetList(string account)
{
var source = await _repository.SearchFor(x => x.AboutUser.Id == account).ToListAsync();
return _mapper.Map<List<VmEmailConfig>>(source);
}
public async Task Edit(VmEmailConfig viewModel)
{
if (string.IsNullOrEmpty(viewModel.Password))
{
var model = await _repository.TryGetAsync(viewModel.Id);
if(model == null)throw new ArgumentException("没找找到这个邮箱配置",nameof(viewModel));
var updateModel = _mapper.Map<EmailConfig>(viewModel);
updateModel.Password = model.Password;
await _repository.UpdateAsync(updateModel);
return;
}
var hasPwdUpdateModel = _mapper.Map<EmailConfig>(viewModel);
hasPwdUpdateModel.Password = await EncryptAes(hasPwdUpdateModel.Password, hasPwdUpdateModel.Id.ToString());
await _repository.UpdateAsync(hasPwdUpdateModel);
}
public async Task<VmEmailConfig?> GetConfig(string id)
{
var config = await _repository.TryGetAsync(id);
if (config == null) return null;
var viewModel = _mapper.Map<VmEmailConfig>(config);
viewModel.Password = await DecryptAes(viewModel.Password, viewModel.Id);
return viewModel;
}
public async Task<VmEmailConfig?> GetConfigByEmailName(string emailName)
{
var model = await _repository.SearchFor(x => x.EmailName == emailName).SingleOrDefaultAsync();
if (model == null) return null;
var viewModel = _mapper.Map<VmEmailConfig>(model);
viewModel.Password = await DecryptAes(viewModel.Password, viewModel.Id);
return viewModel;
}
public async Task Delete(string id)
{
if (ObjectId.TryParse(id, out var oid))
{
await _repository.DeleteAsync(x => x.Id == oid);
}
}
}