using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using System.Transactions; using AutoMapper; using System.Linq.Expressions; using TTSW.Common; using TodoAPI2.Models; using Microsoft.AspNetCore.Http; using IdentityModel; namespace TTSW.EF { public class BaseRepository2 : IBaseRepository2 where T : class, IBaseEntity2 { #region Private Variables private DataContext _context; public DataContext Context { get { return _context; } } private IHttpContextAccessor _contextAccessor; private LoginProfile _loginProfile; #endregion #region Properties private DbSet _entities; public DbSet Entities { get { return _entities ?? (_entities = _context.Set()); } } #endregion public BaseRepository2(DataContext context, IHttpContextAccessor contextAccessor ) { _context = context; _contextAccessor = contextAccessor; } #region Private Functions private bool SaveToDB() { return (_context.SaveChanges() >= 0); } private T SetCreatorProperties(T entity) { //entity.CreatorId = _userRepository.LoginProfile.Id; entity.created = DateTime.Now; return entity; } private T SetUpdatorProperties(T entity) { //entity.UpdatorId = _userRepository.LoginProfile.Id; entity.updated = DateTime.Now; return entity; } private T SetActiveProperty(T entity) { entity.isActive = true; return entity; } private T SetInActiveProperty(T entity) { entity.isActive = false; return entity; } #endregion #region Public Functions public LoginProfile GetLoginProfile() { // Set login profile in the 1st accessing time only // The user has to login to the system too. if (_loginProfile == null && _contextAccessor.HttpContext.User.Identity.IsAuthenticated) { var dict = new Dictionary(); // A list to keep list of all keys for getting user user claims var userProfileClaimsKey = new List(); userProfileClaimsKey.Add(JwtClaimTypes.GivenName); userProfileClaimsKey.Add(JwtClaimTypes.FamilyName); userProfileClaimsKey.Add(JwtClaimTypes.Email); userProfileClaimsKey.Add("customer_guid"); userProfileClaimsKey.Add("user_guid"); userProfileClaimsKey.Add("permission_level"); userProfileClaimsKey.Add("base_system"); userProfileClaimsKey.Add(JwtClaimTypes.Name); userProfileClaimsKey.Add(JwtClaimTypes.PreferredUserName); userProfileClaimsKey.Add(JwtClaimTypes.PhoneNumber); // Fetch only claims related to user profile _contextAccessor.HttpContext.User.Claims .Where(c=> userProfileClaimsKey.Contains(c.Type)).ToList() .ForEach(item => dict.Add(item.Type, item.Value)); // Map claims to model _loginProfile = new LoginProfile(); //if (dict.ContainsKey(JwtClaimTypes.Subject)) // _loginProfile.Id = dict[JwtClaimTypes.Subject]; if (dict.ContainsKey(JwtClaimTypes.GivenName) && !string.IsNullOrEmpty(dict[JwtClaimTypes.GivenName])) _loginProfile.FirstName = dict[JwtClaimTypes.GivenName]; if (dict.ContainsKey(JwtClaimTypes.FamilyName) && !string.IsNullOrEmpty(dict[JwtClaimTypes.FamilyName])) _loginProfile.LastName = dict[JwtClaimTypes.FamilyName]; if (dict.ContainsKey(JwtClaimTypes.Email) && !string.IsNullOrEmpty(dict[JwtClaimTypes.Email])) _loginProfile.Email = dict[JwtClaimTypes.Email]; if (dict.ContainsKey("customer_guid") && !string.IsNullOrEmpty(dict["customer_guid"])) _loginProfile.CustomerGUID = new Guid(dict["customer_guid"]); if (dict.ContainsKey("user_guid") && !string.IsNullOrEmpty(dict["user_guid"])) _loginProfile.UserGUID = new Guid(dict["user_guid"]); if (dict.ContainsKey("permission_level") && !string.IsNullOrEmpty(dict["permission_level"])) _loginProfile.permission_level = dict["permission_level"]; if (dict.ContainsKey("base_system") && !string.IsNullOrEmpty(dict["base_system"])) _loginProfile.base_system = dict["base_system"]; if (string.IsNullOrEmpty(_loginProfile.base_system)) { _loginProfile.base_system = ""; } if (dict.ContainsKey(JwtClaimTypes.Name) && !string.IsNullOrEmpty(dict[JwtClaimTypes.Name])) _loginProfile.UserName = dict[JwtClaimTypes.Name]; else if (dict.ContainsKey(JwtClaimTypes.PreferredUserName) && !string.IsNullOrEmpty(dict[JwtClaimTypes.PreferredUserName])) _loginProfile.UserName = dict[JwtClaimTypes.PreferredUserName]; if (dict.ContainsKey(JwtClaimTypes.PhoneNumber) && !string.IsNullOrEmpty(dict[JwtClaimTypes.PhoneNumber])) _loginProfile.PhoneNumber = dict[JwtClaimTypes.PhoneNumber]; } return _loginProfile; } #region Query Functions public T Get(Key id) { return Entities //.Include(c => c.Creator) //.Include(c => c.Updator) .FirstOrDefault(c=>c.id.Equals(id)); } public T Get(Key id, params Expression>[] includes) { var query = Entities.AsQueryable(); //Dynamic include columns foreach (var include in includes) query = query.Include(include); return query //.Include(c => c.Creator) //.Include(c => c.Updator) .FirstOrDefault(c => c.id.Equals(id)); } public IQueryable GetQuery() { return Entities.AsNoTracking(); } public List GetList(Expression> predicate) { var query = Entities .AsNoTracking() //.Include(c => c.Creator) //.Include(c => c.Updator) .Where(predicate); return query.ToList(); } public List GetList(Expression> predicate, params Expression>[] includes) { var query = Entities.AsQueryable(); //Dynamic include columns foreach (var include in includes) query = query.Include(include); query = query .AsNoTracking() //.Include(c => c.Creator) //.Include(c => c.Updator) .Where(predicate); return query.ToList(); } #endregion #region Manipulation Functions public T Insert(T entity) { var userLogin = GetLoginProfile(); entity = SetCreatorProperties(entity); entity = SetUpdatorProperties(entity); entity = SetActiveProperty(entity); var result = Entities.Add(entity); if(!SaveToDB()) throw new NotificationException($"Unable to add new item to database."); return Get(result.Entity.id); } public void Insert(IEnumerable list) { var userLogin = GetLoginProfile(); var insertedList = new List(); foreach(var entity in list) { var newItem = entity; newItem = SetCreatorProperties(newItem); newItem = SetUpdatorProperties(newItem); newItem = SetActiveProperty(newItem); insertedList.Add(newItem); } Entities.AddRange(insertedList); if (!SaveToDB()) throw new NotificationException($"Unable to insert item to database."); } public T Update(Key id, object model) { var userLogin = GetLoginProfile(); var existingItem = Get(id); if(existingItem == null) throw new NotificationException($"No item in database."); Mapper.Map(model, existingItem); existingItem = SetUpdatorProperties(existingItem); if (!SaveToDB()) throw new NotificationException($"Unable to save item to database."); return existingItem; } public T SetAsInActive(Key id) { var userLogin = GetLoginProfile(); var existingItem = Get(id); if (existingItem == null) throw new NotificationException($"No item in database."); existingItem = SetUpdatorProperties(existingItem); existingItem = SetInActiveProperty(existingItem); if (!SaveToDB()) throw new NotificationException($"Unable to set item as inactive to database."); return existingItem; } public T SetAsActive(Key id) { var userLogin = GetLoginProfile(); var existingItem = Get(id); if (existingItem == null) throw new NotificationException($"No item in database."); existingItem = SetUpdatorProperties(existingItem); existingItem = SetActiveProperty(existingItem); if (!SaveToDB()) throw new NotificationException($"Unable to set item as active to database."); return existingItem; } public void Delete(Key id) { var userLogin = GetLoginProfile(); var existingItem = Get(id); if (existingItem == null) throw new NotificationException($"No item in database."); Entities.Remove(existingItem); if (!SaveToDB()) throw new NotificationException($"Unable to delete item from database."); return; } public void Delete(Expression> predicate) { var userLogin = GetLoginProfile(); Entities.RemoveRange(Entities.Where(predicate)); if (!SaveToDB()) throw new NotificationException($"Unable to delete items from database."); } public void InsertWithoutCommit(T entity) { var userLogin = GetLoginProfile(); entity = SetCreatorProperties(entity); entity = SetUpdatorProperties(entity); entity = SetActiveProperty(entity); var result = Entities.Add(entity); } public void UpdateWithoutCommit(Key id, object model) { var userLogin = GetLoginProfile(); var existingItem = Get(id); if (existingItem == null) throw new NotificationException($"No item in database."); Mapper.Map(model, existingItem); existingItem = SetUpdatorProperties(existingItem); } public void DeleteWithoutCommit(Key id) { var userLogin = GetLoginProfile(); var existingItem = Get(id); if (existingItem == null) throw new NotificationException($"No item in database."); Entities.Remove(existingItem); } #endregion #endregion } }