diff --git a/Application.cs b/Application.cs index 7110c09..494fafe 100644 --- a/Application.cs +++ b/Application.cs @@ -8,6 +8,7 @@ using ln.types; using System.Net; using ln.application.service; using ln.http.resources; +using ln.types.btree; namespace ln.application { @@ -21,6 +22,11 @@ namespace ln.application public MemoryLogger MemoryLogger { get; } + public int ApplicationContextTimeout { get; set; } = 1200; + + + MappingBTree applicationContexts = new MappingBTree((x)=>x.ContextID); + public Application() { MemoryLogger = new MemoryLogger(8192); @@ -89,12 +95,53 @@ namespace ln.application HttpServer.Stop(); } + public virtual ApplicationContext CreateApplicationContext() => new ApplicationContext(this); + + public ApplicationContext GetApplicationContext() => GetApplicationContext(Guid.Empty); + public ApplicationContext GetApplicationContext(Guid contextID) + { + ApplicationContext applicationContext; + if (Guid.Empty.Equals(contextID)) + { + while (true) + { + applicationContext = CreateApplicationContext(); + if (!applicationContexts.ContainsKey(applicationContext.ContextID)) + { + applicationContexts.Add(applicationContext); + break; + } + } + } + else + { + if (!applicationContexts.ContainsKey(contextID)) + throw new KeyNotFoundException(); + + applicationContext = applicationContexts[contextID]; + } + return applicationContext; + } + + public virtual AuthenticatedUser AuthenticateUser(string username,object prove) + { + return null; + } + + public void CleanupApplicationContexts() + { + foreach (ApplicationContext applicationContext in applicationContexts.ToArray()) + { + if (applicationContext.Untouched > TimeSpan.FromSeconds(ApplicationContextTimeout)) + applicationContexts.RemoveKey(applicationContext.ContextID); + } + } - /* + /* * Plugin Classes */ - Dictionary> pluginInstances = new Dictionary>(); + Dictionary> pluginInstances = new Dictionary>(); public void RegisterPluginInstance(PC pluginInstance) => RegisterPluginInstance(typeof(PC),pluginInstance); public void RegisterPluginInstance(Type type,object pluginInstance) diff --git a/ApplicationContext.cs b/ApplicationContext.cs new file mode 100644 index 0000000..2fd08c1 --- /dev/null +++ b/ApplicationContext.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading; +namespace ln.application +{ + public class ApplicationContext + { + static ThreadLocal currentApplicationContext = new ThreadLocal(); + public static void SetCurrentContext(ApplicationContext applicationContext) => currentApplicationContext.Value = applicationContext; + public static void ClearCurrentContext() => currentApplicationContext.Value = null; + + public Guid ContextID { get; } + public DateTime Created { get; } + public DateTime LastAccess { get; protected set; } + + public TimeSpan Age => LastAccess - Created; + public TimeSpan Untouched => DateTime.Now - LastAccess; + + public Application Application { get; } + public AuthenticatedUser CurrentUser { get; protected set; } + + + public ApplicationContext(Application application) + { + ContextID = Guid.NewGuid(); + Created = DateTime.Now; + LastAccess = Created; + + Application = application; + CurrentUser = AuthenticatedUser.Anonymous; + } + + protected void UpdateLastAccess() + { + LastAccess = DateTime.Now; + } + + public virtual bool AuthenticateUser(string username,object prove) + { + AuthenticatedUser authenticatedUser = Application.AuthenticateUser(username, prove); + if (authenticatedUser != null) + { + CurrentUser = authenticatedUser; + return true; + } + else + { + CurrentUser = AuthenticatedUser.Anonymous; + return false; + } + } + public virtual void DeauthenticateUser() + { + CurrentUser = AuthenticatedUser.Anonymous; + } + } +} diff --git a/AuthenticatedUser.cs b/AuthenticatedUser.cs new file mode 100644 index 0000000..7cbbaf3 --- /dev/null +++ b/AuthenticatedUser.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Security.Cryptography; +namespace ln.application +{ + public class AuthenticatedUser + { + public static AuthenticatedUser Anonymous { get; } = new AuthenticatedUser(); + + public Guid ID { get; } + public string Name { get; } + + public byte[] SecretHash { get; set; } + + public int Token { get; set; } + + public string[] Roles => Roles.ToArray(); + + + HashSet roles = new HashSet(); + + public AuthenticatedUser() + { + ID = Guid.Empty; + Name = "Anonymous"; + } + + public AuthenticatedUser(Guid userID, string name) : this(userID, name, new string[0]) { } + public AuthenticatedUser(Guid userID, string name, IEnumerable userRoles) + { + ID = userID; + Name = name; + foreach (string role in userRoles) + roles.Add(role); + } + + public bool HasRole(string role) => roles.Contains(role); + + public void SetSecret(string secret) + { + byte[] secretBytes = Encoding.UTF8.GetBytes(secret); + SHA256 sha256 = SHA256.Create(); + sha256.ComputeHash(secretBytes); + + SecretHash = sha256.Hash; + } + + public override int GetHashCode() + { + return ID.GetHashCode(); + } + public override bool Equals(object obj) + { + if (obj is AuthenticatedUser) + { + AuthenticatedUser other = obj as AuthenticatedUser; + return ID.Equals(other.ID); + } + return false; + } + } +} diff --git a/ln.application.csproj b/ln.application.csproj index d564cca..d6ad701 100644 --- a/ln.application.csproj +++ b/ln.application.csproj @@ -37,6 +37,8 @@ + +