using Dpz.Core.Public.Entity.Option;
using Dpz.Core.Public.ViewModel.Option;
namespace Dpz.Core.Service.RepositoryServiceImpl;
public class AppOptionService : IAppOptionService
{
private readonly IRepository<AppOption> _repository;
private readonly IHybridCachingProvider _cachingProvider;
private readonly IMapper _mapper;
/// <summary>
/// 友情链接 Option name
/// </summary>
private const string FriendOptionName = "friends";
/// <summary>
/// 页脚内容 Option name
/// </summary>
private const string FooterContentOptionName = "footer";
/// <summary>
/// 账号锁定 Option name
/// </summary>
private const string AccountLockOptionName = "AccountLoginFailLock";
public AppOptionService(
IRepository<AppOption> repository,
IHybridCachingProvider cachingProvider,
IMapper mapper)
{
_repository = repository;
_cachingProvider = cachingProvider;
_mapper = mapper;
}
public async Task<IList<VmFriends>> GetFriendsAsync()
{
var friends = await _repository.SearchFor(x => x.OptionName == FriendOptionName).ToListAsync();
if (friends == null || !friends.Any())
return new List<VmFriends>();
var list = friends.Cast<Friends>().ToList();
return _mapper.Map<List<VmFriends>>(list);
}
public async Task AddFriendAsync(VmFriends friend)
{
//var entity = new AppOption {Option = friend, Name = "friends"};
var entity = _mapper.Map<Friends>(friend);
entity.CreateTime = DateTime.Now;
entity.LastUpdateTime = DateTime.Now;
entity.OptionName = FriendOptionName;
await _repository.InsertAsync(entity);
}
public async Task EditFriendAsync(VmFriends? friend)
{
if (string.IsNullOrEmpty(friend?.Id) || !ObjectId.TryParse(friend.Id, out var oid)) return;
var entity = await _repository.FindAsync(oid);
if (entity == null || entity is not Friends entityFriend) return;
entityFriend.Avatar = friend.Avatar;
entityFriend.Description = friend.Description;
entityFriend.Link = friend.Link;
entityFriend.Name = friend.Name;
entityFriend.LastUpdateTime = DateTime.Now;
await _repository.UpdateAsync(entityFriend);
}
public async Task<VmAppOption?> FindAsync(string id)
{
var entity = await _repository.TryGetAsync(id);
if (entity == null) return null;
return _mapper.Map<VmAppOption>(entity);
}
public async Task<VmSaltOption> GetSaltAsync(string account)
{
var entity = await _repository.Collection.Aggregate()
.Match(new BsonDocument {{"OptionName", "AccountSalt"}})
.Match(new BsonDocument {{"Account", account}})
.Match(new BsonDocument
{
{
"Expire", new BsonDocument
{
{"$gt", BsonDateTime.Create(DateTime.Now)}
}
}
}).FirstOrDefaultAsync();
if (entity is SaltOption saltOption)
{
return _mapper.Map<VmSaltOption>(saltOption);
}
var salt = Guid.NewGuid().ToString("N");
var saltEntity = new SaltOption
{
Account = account,
CreateTime = DateTime.Now,
Expire = DateTime.Now.AddDays(7),
LastUpdateTime = DateTime.Now,
OptionName = "AccountSalt",
Salt = salt
};
await _repository.InsertAsync(saltEntity);
return _mapper.Map<VmSaltOption>(saltEntity);
}
public async Task SaveFooterContentAsync(string content)
{
await _cachingProvider.SetAsync(CacheKey.FooterKey, content, TimeSpan.FromDays(30));
var footer = await _repository.SearchFor(x => x.OptionName == FooterContentOptionName).FirstOrDefaultAsync();
if (footer != null)
{
var set = new BsonDocument
{
{
"$set", new BsonDocument
{
{"Content", new BsonString(content)},
{"LastUpdateTime", new BsonDateTime(DateTime.Now)}
}
}
};
UpdateDefinition<AppOption> update = new BsonDocumentUpdateDefinition<AppOption>(set);
await _repository.UpdateAsync(x => x.Id == footer.Id, update);
return;
}
var entity = new FooterContent
{
Content = content,
CreateTime = DateTime.Now,
LastUpdateTime = DateTime.Now,
OptionName = FooterContentOptionName
};
await _repository.InsertAsync(entity);
}
public async Task<string> GetFooterContentAsync()
{
var footer = await _repository.SearchFor(x => x.OptionName == FooterContentOptionName).FirstOrDefaultAsync();
return footer is FooterContent entity ? entity.Content : "";
}
public async Task LoginFailAsync(string account)
{
if (await _repository.Collection.Aggregate()
.Match(new BsonDocument {{"OptionName", AccountLockOptionName}})
.Match(new BsonDocument {{"Account", account}})
.FirstOrDefaultAsync() is AccountLock accountLock)
{
// 如果锁定时间过期,那么重置
if (accountLock.Expired.HasValue && DateTime.Now > accountLock.Expired.Value.ToLocalTime())
{
accountLock.Expired = null;
accountLock.AttemptNumber = 1;
accountLock.LastUpdateTime = DateTime.Now;
await _repository.UpdateAsync(accountLock);
return;
}
// 上次操作超过间隔时间,那么重置尝试次数
if (DateTime.Now > accountLock.LastUpdateTime.ToLocalTime().AddHours(1))
{
accountLock.AttemptNumber = 1;
}
// 没有超过间隔时间,尝试次数累加
else
{
accountLock.AttemptNumber++;
}
accountLock.LastUpdateTime = DateTime.Now;
// 超过尝试次数,则锁定,设定锁定时间
if (accountLock.AttemptNumber > 3)
{
accountLock.Expired = DateTime.Now.AddDays(1);
}
await _repository.UpdateAsync(accountLock);
return;
}
var entity = new AccountLock
{
Account = account,
AttemptNumber = 1,
CreateTime = DateTime.Now,
LastUpdateTime = DateTime.Now,
OptionName = AccountLockOptionName
};
await _repository.InsertAsync(entity);
}
public async Task LoginSuccessfulAsync(string account)
{
if (await _repository.Collection.Aggregate()
.Match(new BsonDocument {{"OptionName", AccountLockOptionName}})
.Match(new BsonDocument {{"Account", account}})
.FirstOrDefaultAsync() is AccountLock accountLock)
{
accountLock.AttemptNumber = 0;
accountLock.Expired = null;
accountLock.LastUpdateTime = DateTime.Now;
await _repository.UpdateAsync(accountLock);
}
}
public async Task<bool> IsAccountLockAsync(string account)
{
var entity = await _repository.Collection.Aggregate()
.Match(new BsonDocument {{"OptionName", AccountLockOptionName}})
.Match(new BsonDocument {{"Account", account}})
.FirstOrDefaultAsync();
return entity is AccountLock {Expired: { }} accountLock &&
accountLock.Expired.Value.ToLocalTime() > DateTime.Now;
}
private const string SettingOptionName = "Application.Setting";
public async Task<VmSetting?> GetSettingAsync()
{
var option = await _repository.SearchFor(x => x.OptionName == SettingOptionName).SingleOrDefaultAsync();
if (option is Setting setting)
{
return _mapper.Map<VmSetting>(setting);
}
return null;
}
public async Task SaveSettingAsync(VmSetting setting)
{
await _cachingProvider.SetAsync(CacheKey.AppSettingKey, setting, TimeSpan.FromDays(7));
var option = await _repository.SearchFor(x => x.OptionName == SettingOptionName).SingleOrDefaultAsync();
if (option is Setting entitySetting)
{
entitySetting.Api = setting.Api;
entitySetting.Cdn = setting.Cdn;
entitySetting.Core = setting.Core;
entitySetting.Image = setting.Image;
entitySetting.Job = setting.Job;
entitySetting.Main = setting.Main;
entitySetting.Message = setting.Message;
entitySetting.Script = setting.Script;
entitySetting.Static = setting.Static;
entitySetting.LastUpdateTime = DateTime.Now;
await _repository.UpdateAsync(entitySetting);
return;
}
var entity = _mapper.Map<Setting>(setting);
entity.OptionName = SettingOptionName;
entity.CreateTime = DateTime.Now;
entity.LastUpdateTime = DateTime.Now;
await _repository.InsertAsync(entity);
}
public async Task DeleteAsync(string id)
{
if (ObjectId.TryParse(id, out var oid))
{
await _repository.DeleteAsync(oid);
}
}
}