using AyCode.Database.DbContexts.Users; using AyCode.Interfaces.Profiles; using AyCode.Interfaces.Users; namespace AyCode.Database.DbSets.Users; public static class AcUserTokenDbSetExtensions { public static bool ChangePassword(this IAcUserChangePasswordDbSet ctx, TUser? user, string passwordHash, string verificationToken) where TUser : class, IAcUserBase where TUserToken : class, IAcUserTokenBase { if (user == null || !ctx.IsValidToken(user.Id, verificationToken)) return false; user.Password = passwordHash; ctx.Users.Update(user); ctx.DeactivateTokens(user.Id); return true; } public static TUserToken? UpdateUserTokenSent(this IAcUserTokenDbSet ctx, Guid userId, string verificationToken, DateTime tokenSentUtc) where TUserToken : class, IAcUserTokenBase { var userToken = ctx.GetUserToken(userId, verificationToken); if (userToken == null) return null; userToken.TokenSent = tokenSentUtc; userToken.TokenExpiration ??= tokenSentUtc.AddDays(1); var utcNow = DateTime.UtcNow; userToken.IsActive = tokenSentUtc <= utcNow && userToken.TokenExpiration > utcNow; ctx.UserTokens.Update(userToken); return userToken; } public static TUserToken CreateUserToken(this IAcUserTokenDbSet ctx, Guid userId, string verificationToken) where TUserToken : class, IAcUserTokenBase { var userToken = Activator.CreateInstance(); userToken.UserId = userId; userToken.Token = verificationToken; return ctx.CreateUserToken(userToken); } public static TUserToken CreateUserToken(this IAcUserTokenDbSet ctx, TUserToken userToken) where TUserToken : class, IAcUserTokenBase { ctx.DeactivateTokens(userToken.UserId); userToken.IsActive = true; ctx.UserTokens.Add(userToken); return userToken; } public static TUserToken? GetActiveUserToken(this IAcUserTokenDbSet ctx, Guid userId) where TUserToken : class, IAcUserTokenBase => ctx.UserTokens.SingleOrDefault(x => x.UserId == userId && x.IsActive && (x.TokenExpiration == null || x.TokenExpiration > DateTime.UtcNow)); public static TUserToken? GetUserToken(this IAcUserTokenDbSet ctx, Guid userId, string verificationToken) where TUserToken : class, IAcUserTokenBase => ctx.UserTokens.SingleOrDefault(x => x.UserId == userId && x.Token == verificationToken); public static bool IsValidToken(this IAcUserTokenDbSet ctx, Guid userId, string verificationToken) where TUserToken : class, IAcUserTokenBase => ctx.UserTokens.Any(x => x.UserId == userId && x.IsActive && x.Token == verificationToken && x.TokenExpiration > DateTime.UtcNow && x.TokenSent < DateTime.UtcNow); public static void DeactivateTokens(this IAcUserTokenDbSet ctx, Guid userId) where TUserToken : class, IAcUserTokenBase { var activeUserTokens = ctx.UserTokens.Where(x => x.UserId == userId && x.IsActive); foreach (var activeUserToken in activeUserTokens) activeUserToken.IsActive = false; ctx.UserTokens.UpdateRange(activeUserTokens); } }