Authentication Alpha
parent
294c9736b4
commit
0be67ce4a1
|
@ -11,16 +11,17 @@ using ln.http.resources;
|
||||||
using ln.types.btree;
|
using ln.types.btree;
|
||||||
using ln.types.rpc;
|
using ln.types.rpc;
|
||||||
using ln.application.slots;
|
using ln.application.slots;
|
||||||
|
using ln.identities;
|
||||||
|
using ln.http.session;
|
||||||
|
|
||||||
namespace ln.application
|
namespace ln.application
|
||||||
{
|
{
|
||||||
public class Application : IApplicationInterface
|
public class Application : ResourceApplication
|
||||||
{
|
{
|
||||||
public ArgumentContainer Arguments { get; protected set; }
|
public ArgumentContainer Arguments { get; protected set; }
|
||||||
public HTTPServer HttpServer { get; private set; }
|
public HTTPServer HttpServer { get; private set; }
|
||||||
|
|
||||||
public ServiceContainer ServiceContainer { get; }
|
public ServiceContainer ServiceContainer { get; }
|
||||||
public ResourceApplication HTTPApplication { get; private set; }
|
|
||||||
|
|
||||||
public MemoryLogger MemoryLogger { get; }
|
public MemoryLogger MemoryLogger { get; }
|
||||||
|
|
||||||
|
@ -29,22 +30,30 @@ namespace ln.application
|
||||||
public RPCContainer RPCContainer { get; } = new RPCContainer();
|
public RPCContainer RPCContainer { get; } = new RPCContainer();
|
||||||
public BinarySlotContainer BinarySlots { get; } = new BinarySlotContainer();
|
public BinarySlotContainer BinarySlots { get; } = new BinarySlotContainer();
|
||||||
|
|
||||||
|
public IIdentityProvider IdentityProvider { get; protected set; }
|
||||||
|
|
||||||
MappingBTree<Guid, ApplicationContext> applicationContexts = new MappingBTree<Guid, ApplicationContext>((x)=>x.ContextID);
|
MappingBTree<Guid, ApplicationSession> applicationSessions = new MappingBTree<Guid, ApplicationSession>((x)=>x.SessionID);
|
||||||
|
|
||||||
public Application()
|
public Application(IIdentityProvider identityProvider,RPCContainer rpcContainer)
|
||||||
{
|
{
|
||||||
|
IdentityProvider = identityProvider;
|
||||||
|
RPCContainer = rpcContainer;
|
||||||
|
|
||||||
MemoryLogger = new MemoryLogger(8192);
|
MemoryLogger = new MemoryLogger(8192);
|
||||||
Logger.Default.Backends.Add(MemoryLogger);
|
Logger.Default.Backends.Add(MemoryLogger);
|
||||||
|
|
||||||
Arguments = new ArgumentContainer()
|
Arguments = new ArgumentContainer()
|
||||||
.Add((char)0, "log-level", "INFO")
|
.Add((char)0, "log-level", "INFO")
|
||||||
.Add('l', "http-listen","0.0.0.0")
|
.Add('l', "http-listen", "0.0.0.0")
|
||||||
.Add('p', "http-port", "8080");
|
.Add('p', "http-port", "8080");
|
||||||
|
|
||||||
ServiceContainer = new ServiceContainer(this);
|
ServiceContainer = new ServiceContainer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Application() :this(null,new RPCContainer()) { }
|
||||||
|
public Application(IIdentityProvider identityProvider) : this(identityProvider,new RPCContainer()) { }
|
||||||
|
|
||||||
public virtual void PrepareStart()
|
public virtual void PrepareStart()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -68,8 +77,9 @@ namespace ln.application
|
||||||
));
|
));
|
||||||
|
|
||||||
HttpServer.Start();
|
HttpServer.Start();
|
||||||
HTTPApplication = new ResourceApplication();
|
HttpServer.DefaultApplication = this;
|
||||||
HttpServer.DefaultApplication = HTTPApplication;
|
|
||||||
|
RootResource = new BaseResource("");
|
||||||
|
|
||||||
|
|
||||||
/* Application Services */
|
/* Application Services */
|
||||||
|
@ -100,45 +110,64 @@ namespace ln.application
|
||||||
HttpServer.Stop();
|
HttpServer.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ApplicationContext CreateApplicationContext() => new ApplicationContext(this);
|
public virtual ApplicationSession CreateApplicationSession() => new ApplicationSession(this);
|
||||||
|
public ApplicationSession GetApplicationSession(Session session)
|
||||||
|
{
|
||||||
|
ApplicationSession applicationSession = session.Get<ApplicationSession>("LNApplicationSession");
|
||||||
|
if (applicationSession == null)
|
||||||
|
{
|
||||||
|
applicationSession = CreateApplicationSession();
|
||||||
|
applicationSessions.Add(applicationSession);
|
||||||
|
session["LNApplicationSession"] = applicationSession;
|
||||||
|
}
|
||||||
|
|
||||||
public ApplicationContext GetApplicationContext() => GetApplicationContext(Guid.Empty);
|
return applicationSession;
|
||||||
public ApplicationContext GetApplicationContext(Guid contextID)
|
}
|
||||||
|
|
||||||
|
public ApplicationSession GetApplicationSession() => GetApplicationSession(Guid.Empty);
|
||||||
|
public ApplicationSession GetApplicationSession(Guid contextID)
|
||||||
{
|
{
|
||||||
ApplicationContext applicationContext;
|
ApplicationSession applicationSession;
|
||||||
if (Guid.Empty.Equals(contextID))
|
if (Guid.Empty.Equals(contextID))
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
applicationContext = CreateApplicationContext();
|
applicationSession = CreateApplicationSession();
|
||||||
if (!applicationContexts.ContainsKey(applicationContext.ContextID))
|
if (!applicationSessions.ContainsKey(applicationSession.SessionID))
|
||||||
{
|
{
|
||||||
applicationContexts.Add(applicationContext);
|
applicationSessions.Add(applicationSession);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!applicationContexts.ContainsKey(contextID))
|
if (!applicationSessions.ContainsKey(contextID))
|
||||||
throw new KeyNotFoundException();
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
applicationContext = applicationContexts[contextID];
|
applicationSession = applicationSessions[contextID];
|
||||||
}
|
}
|
||||||
return applicationContext;
|
return applicationSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual AuthenticatedUser AuthenticateUser(string username,object prove)
|
public virtual object ProcessMessage(object message)
|
||||||
|
{
|
||||||
|
//Application.BinarySlots.RequestSlot(message as SlotRequest);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual Identity Authenticate(string username,object prove)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CleanupApplicationContexts()
|
public void CleanupApplicationContexts()
|
||||||
{
|
{
|
||||||
foreach (ApplicationContext applicationContext in applicationContexts.ToArray())
|
foreach (ApplicationSession applicationContext in applicationSessions.ToArray())
|
||||||
{
|
{
|
||||||
if (applicationContext.Untouched > TimeSpan.FromSeconds(ApplicationContextTimeout))
|
if (applicationContext.Untouched > TimeSpan.FromSeconds(ApplicationContextTimeout))
|
||||||
applicationContexts.RemoveKey(applicationContext.ContextID);
|
applicationSessions.RemoveKey(applicationContext.SessionID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
namespace ln.application
|
|
||||||
{
|
|
||||||
public class ApplicationContext
|
|
||||||
{
|
|
||||||
static ThreadLocal<ApplicationContext> currentApplicationContext = new ThreadLocal<ApplicationContext>();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using ln.identities;
|
||||||
|
using ln.types.rpc;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ln.logging;
|
||||||
|
using ln.json;
|
||||||
|
using ln.json.mapping;
|
||||||
|
namespace ln.application
|
||||||
|
{
|
||||||
|
public class ApplicationSession : IDisposable
|
||||||
|
{
|
||||||
|
static ThreadLocal<ApplicationSession> currentApplicationSession = new ThreadLocal<ApplicationSession>();
|
||||||
|
public static void SetCurrentSession(ApplicationSession applicationSession) => currentApplicationSession.Value = applicationSession;
|
||||||
|
public static void ClearCurrentSession() => currentApplicationSession.Value = null;
|
||||||
|
public static ApplicationSession CurrentSession => currentApplicationSession.Value;
|
||||||
|
|
||||||
|
public Guid SessionID { 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 Identity SessionIdentity { get; protected set; }
|
||||||
|
|
||||||
|
public ApplicationSession(Application application)
|
||||||
|
{
|
||||||
|
SessionID = Guid.NewGuid();
|
||||||
|
Created = DateTime.Now;
|
||||||
|
LastAccess = Created;
|
||||||
|
|
||||||
|
Application = application;
|
||||||
|
SessionIdentity = null;
|
||||||
|
|
||||||
|
Logging.Log(LogLevel.DEBUG, "ApplicationSession created: {0}",SessionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateLastAccess()
|
||||||
|
{
|
||||||
|
LastAccess = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual object ProcessMessage(object message)
|
||||||
|
{
|
||||||
|
if (message is RPCCall rpcCall)
|
||||||
|
{
|
||||||
|
return Application.RPCContainer.Invoke(rpcCall);
|
||||||
|
} else if (message is AuthenticationRequest authenticationRequest)
|
||||||
|
{
|
||||||
|
Identity identity = Application.IdentityProvider.GetIdentity(authenticationRequest.IdentityName);
|
||||||
|
SecureAttribute[] secureAttributes = identity.GetSecureAttributes(authenticationRequest.SecureAttributeTypeName);
|
||||||
|
AuthenticationChallenges authenticationChallenges = new AuthenticationChallenges(secureAttributes);
|
||||||
|
return authenticationChallenges;
|
||||||
|
} else if (message is AuthenticationProve authenticationProve)
|
||||||
|
{
|
||||||
|
Identity identity = Application.IdentityProvider.GetIdentity(authenticationProve.IdentityName);
|
||||||
|
SecureAttribute secureAttribute = identity.GetSecureAttribute(authenticationProve.SecureAttributeUniqueID);
|
||||||
|
if (secureAttribute.Authenticate(authenticationProve.Challenge, authenticationProve.Prove))
|
||||||
|
{
|
||||||
|
SessionIdentity = identity;
|
||||||
|
JSONObject r = new JSONObject();
|
||||||
|
r.Add("UniqueID", JSONMapper.DefaultMapper.ToJson(identity.UniqueID));
|
||||||
|
r.Add("IdentityName", JSONMapper.DefaultMapper.ToJson(identity.IdentityName));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void DeauthenticateUser()
|
||||||
|
{
|
||||||
|
SessionIdentity = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
Logging.Log(LogLevel.DEBUG, "ApplicationSession disposing: {0}", SessionID);
|
||||||
|
DeauthenticateUser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,28 +6,33 @@ using ln.types.rpc;
|
||||||
using ln.http;
|
using ln.http;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using ln.application.slots;
|
using ln.application.slots;
|
||||||
|
using ln.json.mapping;
|
||||||
|
using ln.identities;
|
||||||
namespace ln.application
|
namespace ln.application
|
||||||
{
|
{
|
||||||
public class ApplicationWebSocket : WebSocket
|
public class ApplicationWebSocket : WebSocket
|
||||||
{
|
{
|
||||||
public IApplicationInterface ApplicationInterface { get; }
|
static Dictionary<string, Func<JSONValue, object>> messageConverters = new Dictionary<string, Func<JSONValue, object>>();
|
||||||
|
static public void RegisterMessageConverter(string messageType, Func<JSONValue, object> converter) => messageConverters[messageType] = converter;
|
||||||
|
static public Func<JSONValue, object> FindConverter(string messageType) => messageConverters[messageType];
|
||||||
|
|
||||||
Dictionary<string, Func<JSONValue, object>> messageConverters = new Dictionary<string, Func<JSONValue, object>>();
|
public Application Application { get; }
|
||||||
|
public ApplicationSession ApplicationSession => Application.GetApplicationSession();
|
||||||
|
|
||||||
public ApplicationWebSocket(IApplicationInterface applicationInterface,HttpRequest httpRequest)
|
|
||||||
:base(httpRequest)
|
|
||||||
{
|
|
||||||
ApplicationInterface = applicationInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddMessageConverter(string messageType, Func<JSONValue, object> converter)
|
static ApplicationWebSocket()
|
||||||
{
|
{
|
||||||
messageConverters[messageType] = converter;
|
RegisterMessageConverter("RPCCall", (JSONValue json) => JSONMapper.DefaultMapper.FromJson(json, typeof(RPCCall)));
|
||||||
|
RegisterMessageConverter("SlotRequest", (JSONValue json) => JSONMapper.DefaultMapper.FromJson(json, typeof(SlotRequest)));
|
||||||
|
RegisterMessageConverter("AuthenticationProve", (JSONValue json) => JSONMapper.DefaultMapper.FromJson(json, typeof(AuthenticationProve)));
|
||||||
|
RegisterMessageConverter("AuthenticationRequest", (JSONValue json) => JSONMapper.DefaultMapper.FromJson(json, typeof(AuthenticationRequest)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<JSONValue, object> FindConverter(string messageType)
|
|
||||||
|
public ApplicationWebSocket(Application application, HttpRequest httpRequest)
|
||||||
|
: base(httpRequest)
|
||||||
{
|
{
|
||||||
return messageConverters[messageType];
|
Application = application;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Received(string textMessage)
|
public override bool Received(string textMessage)
|
||||||
|
@ -59,27 +64,41 @@ namespace ln.application
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
object convertedMessage = FindConverter(messageType)(message);
|
object convertedMessage = FindConverter(messageType)(message);
|
||||||
return ReceivedMessage(messageId, messageType, convertedMessage);
|
ReceivedMessage(messageId, messageType, convertedMessage);
|
||||||
|
|
||||||
|
return true;
|
||||||
} catch (Exception e)
|
} catch (Exception e)
|
||||||
{
|
{
|
||||||
Logging.Log(e);
|
Logging.Log(e);
|
||||||
SendError(messageId, e.ToString(), e.InnerException.ToString());
|
SendError(messageId, e.ToString(), e.InnerException?.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool ReceivedMessage(long messageId, string messageType, object message)
|
public virtual void ReceivedMessage(long messageId, string messageType, object message)
|
||||||
{
|
{
|
||||||
switch (messageType)
|
ApplicationSession.SetCurrentSession(ApplicationSession);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
case "RPCCall":
|
object result = ApplicationSession?.ProcessMessage(message);
|
||||||
SendMessage(messageId, ApplicationInterface.RPCContainer.Invoke(message as RPCCall));
|
if (result is null)
|
||||||
return true;
|
{
|
||||||
case "SlotRequest":
|
result = Application.ProcessMessage(message);
|
||||||
SlotAllocation slotAllocation = ApplicationInterface.BinarySlots.RequestSlot(message as SlotRequest);
|
}
|
||||||
return true;
|
if (result is null)
|
||||||
default:
|
{
|
||||||
return false;
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
SendMessage(messageId, result);
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
SendError(messageId, e.ToString(), e.InnerException?.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ApplicationSession.ClearCurrentSession();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +110,7 @@ namespace ln.application
|
||||||
public void SendMessage(long messageID, object message)
|
public void SendMessage(long messageID, object message)
|
||||||
{
|
{
|
||||||
string messageType = message.GetType().Name;
|
string messageType = message.GetType().Name;
|
||||||
JSONObject jsonMessage = JSONObject.From(message);
|
JSONObject jsonMessage = message is JSONObject ? message as JSONObject : JSONObject.From(message);
|
||||||
|
|
||||||
SendMessage(messageID, messageType, jsonMessage);
|
SendMessage(messageID, messageType, jsonMessage);
|
||||||
}
|
}
|
||||||
|
@ -117,35 +136,6 @@ namespace ln.application
|
||||||
SendMessage(messageId, "error", failed);
|
SendMessage(messageId, "error", failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void a()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Logging.Log(LogLevel.DEBUGDETAIL, "ApplicationWebSocket: Received: {0}",textMessage);
|
|
||||||
JSONObject json = (JSONObject)JSONParser.Parse(textMessage);
|
|
||||||
RPCCall rpcCall = json.ToObject<RPCCall>();
|
|
||||||
|
|
||||||
requestContext.HttpRequest.HTTPServer.ThreadPool.Enqueue(() =>
|
|
||||||
{
|
|
||||||
RPCResult rpcResult = Invoke(rpcCall);
|
|
||||||
string resultText = JSONObject.From(rpcResult).ToString();
|
|
||||||
|
|
||||||
Logging.Log(LogLevel.DEBUGDETAIL, "ApplicationWebSocket: Sending: {0}", resultText);
|
|
||||||
requestContext.WebSocket.Send(resultText);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logging.Log(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual RPCResult Invoke(RPCCall call)
|
|
||||||
{
|
|
||||||
RPCResult result = null;
|
|
||||||
result = ApplicationInterface.RPCContainer.Invoke(call);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
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<string> roles = new HashSet<string>();
|
|
||||||
|
|
||||||
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<string> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -37,8 +37,7 @@
|
||||||
<Compile Include="service\ServiceContainer.cs" />
|
<Compile Include="service\ServiceContainer.cs" />
|
||||||
<Compile Include="service\ApplicationServiceBase.cs" />
|
<Compile Include="service\ApplicationServiceBase.cs" />
|
||||||
<Compile Include="ApplicationWebSocket.cs" />
|
<Compile Include="ApplicationWebSocket.cs" />
|
||||||
<Compile Include="ApplicationContext.cs" />
|
<Compile Include="ApplicationSession.cs" />
|
||||||
<Compile Include="AuthenticatedUser.cs" />
|
|
||||||
<Compile Include="slots\BinarySlot.cs" />
|
<Compile Include="slots\BinarySlot.cs" />
|
||||||
<Compile Include="slots\SlotRequest.cs" />
|
<Compile Include="slots\SlotRequest.cs" />
|
||||||
<Compile Include="slots\BinarySlotContainer.cs" />
|
<Compile Include="slots\BinarySlotContainer.cs" />
|
||||||
|
@ -65,6 +64,10 @@
|
||||||
<Project>{D9342117-3249-4D8B-87C9-51A50676B158}</Project>
|
<Project>{D9342117-3249-4D8B-87C9-51A50676B158}</Project>
|
||||||
<Name>ln.json</Name>
|
<Name>ln.json</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\ln.identities\ln.identities.csproj">
|
||||||
|
<Project>{AA1F75AF-0AEC-4CC0-AC3B-209AE90781AC}</Project>
|
||||||
|
<Name>ln.identities</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="service\" />
|
<Folder Include="service\" />
|
||||||
|
|
|
@ -12,10 +12,17 @@ using ln.http.resources;
|
||||||
using ln.application.service;
|
using ln.application.service;
|
||||||
using ln.http;
|
using ln.http;
|
||||||
using ln.http.listener;
|
using ln.http.listener;
|
||||||
|
using ln.http.resources.websocket;
|
||||||
namespace ln.application.demo
|
namespace ln.application.demo
|
||||||
{
|
{
|
||||||
public class ApplicationDemo : Application
|
public class ApplicationDemo : Application
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public ApplicationDemo()
|
||||||
|
:base(new DemoIdentityProvider())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public override void PrepareStart()
|
public override void PrepareStart()
|
||||||
{
|
{
|
||||||
base.PrepareStart();
|
base.PrepareStart();
|
||||||
|
@ -29,17 +36,20 @@ namespace ln.application.demo
|
||||||
public ApplicationService() : base("core") { }
|
public ApplicationService() : base("core") { }
|
||||||
|
|
||||||
|
|
||||||
public override void ServiceMain(IApplicationInterface applicationInterface)
|
public override void ServiceMain(Application application)
|
||||||
{
|
{
|
||||||
DirectoryResource directoryResource = new DirectoryResource(new string[] { "../../www", "www" });
|
DirectoryResource directoryResource = new DirectoryResource(new string[] { "../../../www", "www" });
|
||||||
directoryResource.DefaultResource = directoryResource.GetResource("demo.html");
|
directoryResource.DefaultResource = directoryResource.GetResource("demo.html");
|
||||||
directoryResource.FallBackResource = directoryResource.DefaultResource;
|
directoryResource.FallBackResource = directoryResource.DefaultResource;
|
||||||
|
|
||||||
CurrentApplicationInterface.HTTPApplication.RootResource = directoryResource;
|
CurrentApplication.RootResource = directoryResource;
|
||||||
|
|
||||||
|
WebsocketResource websocketResource = new WebsocketResource(null, "socket", (HttpRequest arg) => new ApplicationWebSocket((Application)this.CurrentApplication, arg));
|
||||||
|
directoryResource.InjectResource(websocketResource);
|
||||||
|
|
||||||
//applicationInterface.HttpServer.AddListener(new HttpsListener(8443));
|
//applicationInterface.HttpServer.AddListener(new HttpsListener(8443));
|
||||||
|
|
||||||
base.ServiceMain(applicationInterface);
|
base.ServiceMain(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ln.identities;
|
||||||
|
using System.Linq;
|
||||||
|
namespace ln.application.demo
|
||||||
|
{
|
||||||
|
public class DemoIdentityProvider : BaseIdentityProvider
|
||||||
|
{
|
||||||
|
Dictionary<Guid, Identity> identities = new Dictionary<Guid, Identity>();
|
||||||
|
|
||||||
|
public DemoIdentityProvider()
|
||||||
|
{
|
||||||
|
Identity demoIdentity = new Identity("demo");
|
||||||
|
demoIdentity.AddSecureAttribute(new SeededPassword("demopass"));
|
||||||
|
|
||||||
|
identities.Add(demoIdentity.UniqueID,demoIdentity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Identity CreateIdentity(string identityName)
|
||||||
|
{
|
||||||
|
Identity identity = new Identity(identityName);
|
||||||
|
identities.Add(identity.UniqueID, identity);
|
||||||
|
return identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<KeyValuePair<Guid, string>> GetIdentities() => identities.Select((arg) => new KeyValuePair<Guid, string>(arg.Key,arg.Value.IdentityName));
|
||||||
|
public override Identity GetIdentity(Guid uniqueID) => identities[uniqueID];
|
||||||
|
|
||||||
|
public override bool Save(Identity identity) => true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ApplicationDemo.cs" />
|
<Compile Include="ApplicationDemo.cs" />
|
||||||
|
<Compile Include="DemoIdentityProvider.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ln.application.csproj">
|
<ProjectReference Include="..\ln.application.csproj">
|
||||||
|
@ -63,6 +64,10 @@
|
||||||
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
|
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
|
||||||
<Name>ln.types</Name>
|
<Name>ln.types</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\ln.identities\ln.identities.csproj">
|
||||||
|
<Project>{AA1F75AF-0AEC-4CC0-AC3B-209AE90781AC}</Project>
|
||||||
|
<Name>ln.identities</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="www\" />
|
<Folder Include="www\" />
|
||||||
|
|
|
@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.types", "..\ln.types\ln.
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.application.demo", "ln.application.demo\ln.application.demo.csproj", "{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.application.demo", "ln.application.demo\ln.application.demo.csproj", "{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.identities", "..\ln.identities\ln.identities.csproj", "{AA1F75AF-0AEC-4CC0-AC3B-209AE90781AC}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -55,5 +57,9 @@ Global
|
||||||
{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2CBEE2D5-C4D4-4DBD-8AA4-B54E99812808}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AA1F75AF-0AEC-4CC0-AC3B-209AE90781AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AA1F75AF-0AEC-4CC0-AC3B-209AE90781AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AA1F75AF-0AEC-4CC0-AC3B-209AE90781AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AA1F75AF-0AEC-4CC0-AC3B-209AE90781AC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace ln.application.service
|
||||||
|
|
||||||
public string ServiceStateText { get; protected set; }
|
public string ServiceStateText { get; protected set; }
|
||||||
|
|
||||||
public IApplicationInterface CurrentApplicationInterface { get; protected set; }
|
public Application CurrentApplication { get; protected set; }
|
||||||
|
|
||||||
public Type[] DependingServiceTypes => dependingServiceTypes.ToArray();
|
public Type[] DependingServiceTypes => dependingServiceTypes.ToArray();
|
||||||
HashSet<Type> dependingServiceTypes = new HashSet<Type>();
|
HashSet<Type> dependingServiceTypes = new HashSet<Type>();
|
||||||
|
@ -42,14 +42,14 @@ namespace ln.application.service
|
||||||
|
|
||||||
public T Dependency<T>() where T : ApplicationServiceBase
|
public T Dependency<T>() where T : ApplicationServiceBase
|
||||||
{
|
{
|
||||||
T serviceBase = (T)CurrentApplicationInterface.ServiceContainer[typeof(T)].ServiceBase;
|
T serviceBase = (T)CurrentApplication.ServiceContainer[typeof(T)].ServiceBase;
|
||||||
if (serviceBase == null)
|
if (serviceBase == null)
|
||||||
throw new EntryPointNotFoundException(String.Format("depending service not found: {0}",typeof(T).ToString()));
|
throw new EntryPointNotFoundException(String.Format("depending service not found: {0}",typeof(T).ToString()));
|
||||||
|
|
||||||
return serviceBase;
|
return serviceBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ServiceMain(IApplicationInterface applicationInterface)
|
public virtual void ServiceMain(Application application)
|
||||||
{
|
{
|
||||||
Ready();
|
Ready();
|
||||||
while (!StopRequested)
|
while (!StopRequested)
|
||||||
|
@ -61,19 +61,19 @@ namespace ln.application.service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool Start(IApplicationInterface applicationInterface, String[] arguments)
|
public virtual bool Start(Application application, String[] arguments)
|
||||||
{
|
{
|
||||||
if (IsAlive)
|
if (IsAlive)
|
||||||
throw new NotSupportedException("Service is already alive");
|
throw new NotSupportedException("Service is already alive");
|
||||||
|
|
||||||
CurrentApplicationInterface = applicationInterface;
|
CurrentApplication = application;
|
||||||
|
|
||||||
foreach (Type dep in dependingServiceTypes)
|
foreach (Type dep in dependingServiceTypes)
|
||||||
{
|
{
|
||||||
ServiceDefinition depService = CurrentApplicationInterface.ServiceContainer[dep];
|
ServiceDefinition depService = CurrentApplication.ServiceContainer[dep];
|
||||||
if (!depService.IsAlive)
|
if (!depService.IsAlive)
|
||||||
{
|
{
|
||||||
CurrentApplicationInterface.ServiceContainer.Start(depService);
|
CurrentApplication.ServiceContainer.Start(depService);
|
||||||
if (!depService.IsAlive)
|
if (!depService.IsAlive)
|
||||||
{
|
{
|
||||||
Logging.Log(LogLevel.ERROR, "service {0} could not start depending service {1}", ServiceName, depService.ServiceClassName);
|
Logging.Log(LogLevel.ERROR, "service {0} could not start depending service {1}", ServiceName, depService.ServiceClassName);
|
||||||
|
@ -97,7 +97,7 @@ namespace ln.application.service
|
||||||
|
|
||||||
ready = false;
|
ready = false;
|
||||||
StopRequested = false;
|
StopRequested = false;
|
||||||
ServiceThread = new Thread(() => ServiceMain(applicationInterface));
|
ServiceThread = new Thread(() => ServiceMain(application));
|
||||||
ServiceThread.Start();
|
ServiceThread.Start();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -131,7 +131,7 @@ namespace ln.application.service
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ServiceThread.IsAlive)
|
if (!ServiceThread.IsAlive)
|
||||||
CurrentApplicationInterface = null;
|
CurrentApplication = null;
|
||||||
|
|
||||||
ready = false;
|
ready = false;
|
||||||
return !ServiceThread.IsAlive;
|
return !ServiceThread.IsAlive;
|
||||||
|
|
|
@ -75,14 +75,14 @@ namespace ln.application.service
|
||||||
serviceType = null;
|
serviceType = null;
|
||||||
serviceAssembly = null;
|
serviceAssembly = null;
|
||||||
}
|
}
|
||||||
public void Start(IApplicationInterface applicationInterface)
|
public void Start(Application application)
|
||||||
{
|
{
|
||||||
if (!IsLoaded)
|
if (!IsLoaded)
|
||||||
Load();
|
Load();
|
||||||
|
|
||||||
Logging.Log(LogLevel.INFO, "service: starting {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
|
Logging.Log(LogLevel.INFO, "service: starting {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
|
||||||
|
|
||||||
if (ServiceBase.Start(applicationInterface,new string[0]))
|
if (ServiceBase.Start(application,new string[0]))
|
||||||
Logging.Log(LogLevel.INFO, "service: started {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
|
Logging.Log(LogLevel.INFO, "service: started {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
|
||||||
else
|
else
|
||||||
Logging.Log(LogLevel.ERROR, "service: failed {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
|
Logging.Log(LogLevel.ERROR, "service: failed {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
|
||||||
|
|
2
www
2
www
|
@ -1 +1 @@
|
||||||
Subproject commit d1663cbbbe0d91631c4bd6b7b0f7228621329705
|
Subproject commit 6815c42b253152f120fd74a1f0cdc0bebf071547
|
Loading…
Reference in New Issue