using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.Concurrent; using Disco.Models.Repository; using Disco.Data.Repository; using System.Web; using Quartz; using Quartz.Impl; using Disco.Services.Tasks; namespace Disco.BI.UserBI { public class UserCache { private static ConcurrentDictionary> _Cache = new ConcurrentDictionary>(); private const long CacheTimeoutTicks = 6000000000; // 10 Minutes private const string CacheHttpRequestKey = "Disco_CurrentUser"; public static User CurrentUser { get { string username = null; User user; // Check for ASP.NET if (HttpContext.Current != null) { if (HttpContext.Current.Request.IsAuthenticated) { user = (User)HttpContext.Current.Items[CacheHttpRequestKey]; if (user != null) return user; username = HttpContext.Current.User.Identity.Name; } else { return null; //throw new PlatformNotSupportedException("ASP.NET Authentication is not correctly configured"); } } // User default User if (username == null) { username = System.Security.Principal.WindowsIdentity.GetCurrent().Name; } user = GetUser(username); if (HttpContext.Current != null && HttpContext.Current.Request.IsAuthenticated) { // Cache in current request HttpContext.Current.Items[CacheHttpRequestKey] = user; } return user; } } public static User GetUser(string Username) { // Check Cache User u = TryUserCache(Username); if (u == null) { // Load from Repository using (DiscoDataContext dbContext = new DiscoDataContext()) { u = GetUser(Username, dbContext, true); } } return u; } public static User GetUser(string Username, DiscoDataContext dbContext, bool ForceRefresh = false) { User u = null; // Check Cache if (!ForceRefresh) u = TryUserCache(Username); if (u == null) { string username = Username.ToLower(); u = UserBI.Utilities.LoadUser(dbContext, username); SetValue(username, u); } return u; } private static User TryUserCache(string Username) { string username = Username.ToLower(); Tuple userRecord; if (_Cache.TryGetValue(username, out userRecord)) { if (userRecord.Item2 > DateTime.Now) return userRecord.Item1; else _Cache.TryRemove(username, out userRecord); } return null; } public static bool InvalidateValue(string Key) { Tuple userRecord; return _Cache.TryRemove(Key.ToLower(), out userRecord); } private static bool SetValue(string Key, User User) { string key = Key.ToLower(); Tuple userRecord = new Tuple(User, DateTime.Now.AddTicks(CacheTimeoutTicks)); if (_Cache.ContainsKey(key)) { Tuple oldUser; if (_Cache.TryGetValue(key, out oldUser)) { return _Cache.TryUpdate(key, userRecord, oldUser); } } return _Cache.TryAdd(key, userRecord); } internal static void CleanStaleCache() { var usernames = _Cache.Keys.ToArray(); foreach (string username in usernames) { Tuple userRecord; if (_Cache.TryGetValue(username, out userRecord)) { if (userRecord.Item2 <= DateTime.Now) _Cache.TryRemove(username, out userRecord); } } } } }