using BuddyFinance.Common.Concepts; using BuddyFinance.Common.Encryption; using BuddyFinance.Common.Helpers; using BuddyFinance.Integration.Logging; using BuddyFinance.Integration.Models; using BuddyFinance.Integration.Models.Account; using BuddyFinance.Integration.Models.Enums; using BuddyFinance.Integration.Utils; using BuddyFinance.Model; using System; using System.Collections.Generic; using System.Configuration; using System.Data.Entity; using System.Linq; namespace BuddyFinance.Integration { public class SecurityIntegrator : BaseIntegrator { public LoginResult Login(string username, string password) { username = username.ToLower(); //username = username.Decrypt(); //password = password.Decrypt(); int errorCode = 0; string errorMessage = ""; bool? result = false; string profIleid = null; string profIleNumber = null; string userId = null; string roleId = null; string usertype = null; string contact = null; string oauthToken = null; string name = null, surname = null; Status status = null; bool mustChangesPassword = false; try { using (var db = new BuddyFinanceDBEntities()) { #region Default Admin Acc //if (!db.Profiles.Any(m => m.ProfileTypeId == (int)ProfileTypeEnum.BuddyFinance)) //{ // var pr = new Profile // { // ProfileNumber = "BuddyFinance", // Title = "Mr", // Name = "Buddy Finance", // Surname = "Profile", // EmailAddress = "info@justclient.co.za", // ContactNumber = "", // DateOfBirth = DateTime.Now, // GenderId = (int)GenderEnum.Male, // IdentificationNumber = "2017070754085", // IdentificationTypeId = (int)IdentificationTypeEnum.IdentityDocument, // ProfileTypeId = (int)ProfileTypeEnum.BuddyFinance, // EthnicityId = (int)EthnicityEnum.African, // SourceOfIncomeId = (int)SourceOfIncomeEnum.Other, // EmploymentStatusId = (int)EmploymentStatusEnum.SelfEmployed, // //EmploymentDetailId = employementDetails.Id, // // EmploymentDetail = employementDetails, // // BankingDetailsId = bankingDetails.Id, // // BankingDetail = bankingDetails, // OtherSourceOfIncome = "Money laundering", // CountryOfBirthId = (int)CountryEnum.SouthAfrica, // //TaxInformationId =taxInformation.Id // // TaxInformation = taxInformation, // StatusId = (int)ProfileStatusEnum.Approved, // AvailableFunds = 1000, // BillingDate = DateTime.Now, // LastBillDate = DateTime.Now // }; // db.Profiles.Add(pr); // db.SaveChanges(); //} if (!db.Users.Any(m => m.UserName.Equals("admin@buddyfinance.co.za", StringComparison.OrdinalIgnoreCase))) { var buddyFinanceProfile = db.Profiles.Find(Constants.BuddyFinanceProfileId); //db.Profiles.FirstOrDefault(m => m.EmailAddress.Equals("info@zartner.co.za", StringComparison.OrdinalIgnoreCase)); if (buddyFinanceProfile != null) { var hash = buddyFinanceProfile.Id.ToEncryptedString(); var adminUser = new User { UserName = buddyFinanceProfile.EmailAddress, ProfileId = buddyFinanceProfile.Id, MustChangePassword = false, Password = "Pass123".Encrypt(hash), PasswordHash = hash, RoleId = (int)UserRoleEnum.SuperAdmin, IsActive = true, AccountVerified = true, Name = buddyFinanceProfile.Name, Surname = buddyFinanceProfile.Surname, SignUpDate = DateTime.Now, }; db.Users.Add(adminUser); db.SaveChanges(); db.Entry(adminUser).Reload(); } } #endregion var user = db.Users .Include(m=> m.Profile) .Include(m => m.UserRole) .FirstOrDefault(m => m.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)); if (user != null) { result = user.Password.Equals(password.Encrypt(user.PasswordHash)); if (result.HasValue && result.Value) { if (user.AccountVerified) { if (!user.IsActive) { errorCode = (int)ResponseCodes.Failure; errorMessage = "Your account is currenly deactivated. Please contact Buddy Finance for more info."; } else if (user.Profile.StatusId == (int)ProfileStatusEnum.Suspended) { errorCode = (int)ResponseCodes.Failure; errorMessage = "Your account is currenly suspended. Please contact Buddy Finance for more info."; } else { user.LastLoginDate = DateTime.Now; profIleid = user.Profile.Id.ToString(); profIleNumber = user.Profile.ProfileNumber; contact = user.Profile.EmailAddress; usertype = user.UserRole.Name; oauthToken = TokenManager.Generate(user.UserName, true);//$"{user.Profile.Id}|{DateTime.Now}|{TOKEN_LIFESPAN}|{user.Id}"; userId = user.Id.ToString(); roleId = user.RoleId.ToString(); status = new Status { Id = user.Profile.ProfileStatus.Id, Description = user.Profile.ProfileStatus.Description }; name = user.Name ?? user.Profile.Name; surname = user.Surname ?? user.Profile.Surname; db.SaveChanges(); errorCode = (int)ResponseCodes.Success; errorMessage = "Success"; if (user.UserRole.Id == (int)UserRoleEnum.Admin || user.UserRole.Id == (int)UserRoleEnum.SuperAdmin) { contact = user.UserName; mustChangesPassword = user.MustChangePassword; } } } else { errorCode = (int)ResponseCodes.InactiveAccount; errorMessage = "You account is not verified. Please verify your email address in order to login, by clicking the verify link attached in your email"; } } else { errorCode = (int)ResponseCodes.ValidationError; errorMessage = "Invalid username and password combination"; } } else { errorCode = (int)ResponseCodes.ValidationError; errorMessage = "Invalid login"; } } } catch (Exception ex) { errorCode = (int)ResponseCodes.Exception; errorMessage = ex.Message; } return new LoginResult { ErrorCode = errorCode, ErrorMessage = errorMessage, Result = result, ProfileId = profIleid.Encrypt(), UserType = usertype.Encrypt(), Contact = contact.Encrypt(), OauthToken = oauthToken.Encrypt(), UserId = userId.Encrypt(), RoleId = roleId.Encrypt(), Status = status, Name = name.Encrypt(), Surname = surname.Encrypt(), MustChangePassword = mustChangesPassword, ProfileNumber = profIleNumber.Encrypt() }; } public BaseResult Exists(string email) { var result = new BaseResult(); try { using (var db = new BuddyFinanceDBEntities()) { result.Result = db.Profiles.Any(m => m.EmailAddress.Equals(email, StringComparison.OrdinalIgnoreCase)); } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult GenerateToken(string username, bool send = false, string sendUrl = null, NotificationTempate notificationType = NotificationTempate.PasswordReset, string subject = "Password Reset | Buddy Finance") { var result = new BaseResult(); try { using (var db = new BuddyFinanceDBEntities()) { username = username.ToLower(); var user = db.Users.FirstOrDefault(m => m.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)); if (user != null) { var token = TokenManager.Generate(user.UserName); // ($"{user.Profile.Id}|{DateTime.Now}|{TimeSpan.FromDays(5)}|{user.Id}").Encrypt(); if (send) { var profile = user.Profile; //Task.Factory.StartNew(() => //{ try { var emailVars = new Dictionary { {"[url]", sendUrl.Replace("_token", token )}, { "[names]", $"{user.Name ?? profile.Name} {user.Surname ?? profile.Surname}" }, { "[username]",user.UserName }, { "[profileNumber]", profile.ProfileNumber } }; var templateText = System.IO.File.ReadAllText(ConfigurationManager.AppSettings["TemplatesPath"] + notificationType.ToString() + ".txt"); var emailBody = emailVars.Aggregate(templateText, (item, m) => item.Replace(m.Key, m.Value)); var _notifications = new NotificationsIntegrator(); _notifications.SendEmail(user.UserName, emailBody, subject, null); result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; result.Result = token; } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = "token could not be sent." + ex.Message; } //}); } else { result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; result.Result = token; } } } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult ResetPassword(string username, string newPassword, string oldPassword = "", string token = "") { var result = new BaseResult(); //newPassword = newPassword.Decrypt(); //if (!string.IsNullOrWhiteSpace(oldPassword)) // oldPassword = oldPassword.Decrypt(); try { var tokenIsvalid = TokenManager.ValidateToken(token); if (tokenIsvalid) { var split = token.Decrypt().Split('|'); int.TryParse(split[3], out int userId); using (var db = new BuddyFinanceDBEntities()) { var user = db.Users.Find(userId); //?.UserName; var username_ = user?.UserName; //split[0]; if (username_.Equals(username, StringComparison.OrdinalIgnoreCase)) { if (user != null) { var hash = user.PasswordHash ?? user.ProfileId.ToEncryptedString(); if (string.IsNullOrWhiteSpace(oldPassword)) { user.Password = newPassword.Encrypt(hash); db.SaveChanges(); } else { if (user.Password.Equals(oldPassword.Encrypt(hash))) { user.Password = newPassword.Encrypt(hash); db.SaveChanges(); } } result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; result.Result = true; } else { result.ErrorCode = (int)ResponseCodes.NotFound; result.ErrorMessage = "User account not found"; result.Result = false; } } else { result.ErrorCode = (int)ResponseCodes.ValidationError; result.ErrorMessage = "Username missmatch"; } } } else { result.ErrorCode = (int)ResponseCodes.ValidationError; result.ErrorMessage = "Invalid token"; } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult ChangePassword(string username, string oldPassword, string newPassword, string accessToken) { var result = new BaseResult(); if (string.IsNullOrWhiteSpace(accessToken)) { return new BaseResult((int)ResponseCodes.Unauthorized, "Unauthorized"); } try { // token = $"access_token|{DateTime.Now}|{ts}|{user.Id}"; var split = accessToken.Decrypt().Split('|'); int.TryParse(split[3], out int userId); using (var db = new BuddyFinanceDBEntities()) { var user = db.Users.Find(userId); if (user != null && user.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)) { //var hash = user.ProfileId.ToEncryptedString(); if (user.Password.Equals(oldPassword.Encrypt(user.PasswordHash))) { user.Password = newPassword.Encrypt(user.PasswordHash); user.MustChangePassword = false; user.IsActive = true; user.AccountVerified = true; db.SaveChanges(); result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; result.Result = true; } else { result.ErrorCode = (int)ResponseCodes.ValidationError; result.ErrorMessage = "current password is invalid"; } } else { result.ErrorCode = (int)ResponseCodes.ValidationError; result.ErrorMessage = "Username does not match current user"; } } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult> UserAccounts() { var result = new BaseResult>(); try { using (var db = new BuddyFinanceDBEntities()) { var userAccounts = db.Users.ToList(); result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; result.Result = !userAccounts.Any() ? new List() : userAccounts.ConvertAll(m => new UserAccountModel { Id = m.Id, SignUpDate = m.SignUpDate, LastLoginDate = m.LastLoginDate, ProfileId = m.ProfileId, UserName = m.UserName, IsActive = m.IsActive, MobileNumber = m.MobileNumber, MustChangePassword = m.MustChangePassword, Name = m.Name ?? m.Profile.Name, Surname = m.Surname ?? m.Profile.Surname, UserRole = new Models.Account.UserRole { Id = m.UserRole.Id, Name = m.UserRole.Name }, ProfileNumber = m.UserRole.Id == (int)UserRoleEnum.Buddy || m.UserRole.Id == (int)UserRoleEnum.Buddy ? m.Profile.ProfileNumber : "" }); } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; //} // Id = m.Id, // LastLoginDate = m.LastLoginDate, // ProfileId = m.ProfileId, // UserName = m.UserName // }); // } // } // catch (Exception ex) // { // result.ErrorCode = (int)ResponseCodes.Exception; // result.ErrorMessage = ex.Message; // } // return result; //} } public BaseResult Activate(string username) { var result = new BaseResult(); try { using (var db = new BuddyFinanceDBEntities()) { var user = db.Users.FirstOrDefault(m => m.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)); if (user != null) { try { user.IsActive = true; db.SaveChanges(); var mailDetails = new Dictionary { { "[names]", $"{user.Name} {user.Surname}" }, }; //var mailSend = _notifications.SendEmail(user.UserName, emailBody, "Account Created | Buddy Finance", null); var templateText = System.IO.File.ReadAllText(ConfigurationManager.AppSettings["TemplatesPath"] + NotificationTempate.AccountActivated.ToString() + ".txt"); var _notifications = new NotificationsIntegrator(); var emailBody = mailDetails.Aggregate(templateText, (item, m) => item.Replace(m.Key, m.Value)); _notifications.SendEmail(user.UserName, templateText, "Account Actviated! | Buddy Finance", null); result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; result.Result = true; } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = "account could not be activated." + ex.Message; } } } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult Deactivate(string username) { var result = new BaseResult(); try { using (var db = new BuddyFinanceDBEntities()) { var user = db.Users.FirstOrDefault(m => m.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)); if (user != null) { try { user.IsActive = false; db.SaveChanges(); var mailDetails = new Dictionary { { "[names]", $"{user.Name} {user.Surname}" }, }; var templateText = System.IO.File.ReadAllText(ConfigurationManager.AppSettings["TemplatesPath"] + NotificationTempate.AccountDeactivated.ToString() + ".txt"); var _notifications = new NotificationsIntegrator(); var emailBody = mailDetails.Aggregate(templateText, (item, m) => item.Replace(m.Key, m.Value)); _notifications.SendEmail(user.UserName, templateText, "Account Deactviated | Buddy Finance", null); result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; result.Result = true; } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = "token could not be sent." + ex.Message; } } } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult Get(int userId) { var result = new BaseResult(); try { using (var db = new BuddyFinanceDBEntities()) { var user = db.Users.Find(userId); if (user == null) { result.ErrorCode = (int)ResponseCodes.NotFound; result.ErrorMessage = $"User with ID '{userId}' could not be found"; } else { result.Result = new UserAccountModel { Id = user.Id, UserName = user.UserName, Name = user.Name, Surname = user.Surname, MobileNumber = user.MobileNumber, ProfileId = user.ProfileId, IsActive = user.IsActive, MustChangePassword = true, RoleId = user.RoleId, UserRole = new Models.Account.UserRole { Id = user.RoleId, Name = user.UserRole.Name }, SignUpDate = user.SignUpDate, }; result.ErrorCode = (int)ResponseCodes.Success; result.ErrorMessage = "Success"; } } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult Save(UserAccountModel userAccount) { var result = new BaseResult(); try { using (var db = new BuddyFinanceDBEntities()) { userAccount.UserName = userAccount.UserName.ToLower(); var user = db.Users.FirstOrDefault(m => m.UserName.Equals(userAccount.UserName, StringComparison.OrdinalIgnoreCase)); if (user != null) { result.ErrorCode = (int)ResponseCodes.ValidationError; result.ErrorMessage = "email address (username) already in use"; } else { var profileId = userAccount.ProfileId; if (userAccount.RoleId == (int)UserRoleEnum.Admin || userAccount.RoleId == (int)UserRoleEnum.SuperAdmin) { //var buddyFinanceDefault = db.Profiles.FirstOrDefault(m => m.ProfileTypeId == (int)ProfileTypeEnum.BuddyFinance); //if (buddyFinanceDefault != null) // profileId = buddyFinanceDefault.Id; profileId = Constants.BuddyFinanceProfileId; } string pssHash = profileId.ToEncryptedString().Encrypt(); var password = PasswordHelper.GeneratePassword(pssHash, out string plainTextPassword); user = new User { UserName = userAccount.UserName, Name = userAccount.Name, Surname = userAccount.Surname, MobileNumber = userAccount.MobileNumber, ProfileId = profileId, IsActive = false, MustChangePassword = true, RoleId = userAccount.RoleId, SignUpDate = DateTime.Now, Password = password, PasswordHash = pssHash, }; db.Users.Add(user); db.SaveChanges(); var token = TokenManager.Generate(user.UserName, isAccessToken: true); var url = ConfigurationManager.AppSettings["AdminVerifyUrl"] .Replace("_email", user.UserName) .Replace("_token", token.Encrypt()); var mailDetails = new Dictionary { { "[names]", $"{user.Name} {user.Surname}" }, { "[email]", $"{user.UserName}"}, { "[defaultpassword]", $"{plainTextPassword}" }, { "[url]", url } }; var templateText = System.IO.File.ReadAllText(ConfigurationManager.AppSettings["TemplatesPath"] + NotificationTempate.AdminAccountCreated.ToString() + ".txt"); var emailBody = mailDetails.Aggregate(templateText, (item, m) => item.Replace(m.Key, m.Value)); var mailSend = _notifications.SendEmail(user.UserName, emailBody, "Account Created | Buddy Finance", null); result.ErrorCode = (int)ResponseCodes.Success; result.Result = true; result.ErrorMessage = "Success"; } } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } public BaseResult Update(UserAccountModel userAccount) { var result = new BaseResult(); try { using (var db = new BuddyFinanceDBEntities()) { userAccount.UserName = userAccount.UserName.ToLower(); var user = db.Users.Find(userAccount.Id); if (user == null) { result.ErrorCode = (int)ResponseCodes.ValidationError; result.ErrorMessage = $"user with username '{userAccount.UserName}' does not exist"; } else if (db.Users.Any(m => m.UserName.Equals(userAccount.UserName, StringComparison.OrdinalIgnoreCase) && m.Id != userAccount.Id)) { result.ErrorCode = (int)ResponseCodes.ValidationError; result.ErrorMessage = "email address (username) already in use"; } else { user.UserName = userAccount.UserName; user.Name = userAccount.Name; user.Surname = userAccount.Surname; user.MobileNumber = userAccount.MobileNumber; user.RoleId = userAccount.RoleId; db.Entry(user).State = EntityState.Modified; db.SaveChanges(); result.ErrorCode = (int)ResponseCodes.Success; result.Result = true; result.ErrorMessage = "Success"; } } } catch (Exception ex) { result.ErrorCode = (int)ResponseCodes.Exception; result.ErrorMessage = ex.Message; } return result; } } }