From 331b357a64cec36af09d7283a3f48c7852d076b3 Mon Sep 17 00:00:00 2001 From: icedream Date: Wed, 14 May 2014 18:18:34 +0200 Subject: [PATCH] Brightstar DB time. Now I "only" need proper numeric ID generation with freshly created users. --- src/npmotd/Program.cs | 9 +- src/npserv/App.config | 7 +- ...BrightstarDatabaseAuthenticationHandler.cs | 69 ++ .../BrightstarDatabaseFileServingHandler.cs | 84 ++ .../Database/BrightstarDatabaseContext.cs | 501 ++++++++++ .../Database/BrightstarDatabaseContext.tt | 918 ++++++++++++++++++ src/npserv/Database/IBan.cs | 17 + src/npserv/Database/ICheatDetection.cs | 19 + src/npserv/Database/IFriend.cs | 21 + src/npserv/Database/IPublisherFile.cs | 14 + src/npserv/Database/ISession.cs | 15 + src/npserv/Database/IUser.cs | 36 + src/npserv/Database/IUserFile.cs | 16 + src/npserv/Database/User.cs | 79 -- src/npserv/Program.cs | 341 +++---- src/npserv/Properties/AssemblyInfo.cs | 6 +- .../RavenDatabaseAuthenticationHandler.cs | 65 -- src/npserv/RavenDatabaseFileServingHandler.cs | 98 -- src/npserv/UInt32Converter.cs | 24 - src/npserv/npserv.csproj | 71 +- src/npserv/packages.config | 13 +- 21 files changed, 1943 insertions(+), 480 deletions(-) create mode 100644 src/npserv/BrightstarDatabaseAuthenticationHandler.cs create mode 100644 src/npserv/BrightstarDatabaseFileServingHandler.cs create mode 100644 src/npserv/Database/BrightstarDatabaseContext.cs create mode 100644 src/npserv/Database/BrightstarDatabaseContext.tt create mode 100644 src/npserv/Database/IBan.cs create mode 100644 src/npserv/Database/ICheatDetection.cs create mode 100644 src/npserv/Database/IFriend.cs create mode 100644 src/npserv/Database/IPublisherFile.cs create mode 100644 src/npserv/Database/ISession.cs create mode 100644 src/npserv/Database/IUser.cs create mode 100644 src/npserv/Database/IUserFile.cs delete mode 100644 src/npserv/Database/User.cs delete mode 100644 src/npserv/RavenDatabaseAuthenticationHandler.cs delete mode 100644 src/npserv/RavenDatabaseFileServingHandler.cs delete mode 100644 src/npserv/UInt32Converter.cs diff --git a/src/npmotd/Program.cs b/src/npmotd/Program.cs index 329e1ef..f8f8588 100644 --- a/src/npmotd/Program.cs +++ b/src/npmotd/Program.cs @@ -79,10 +79,10 @@ namespace NPSharp.CommandLine.MOTD return; } - string hostname = args[0]; - ushort port = ushort.Parse(args[1]); - string username = args[2]; - string password = args[3]; + var hostname = args[0]; + var port = ushort.Parse(args[1]); + var username = args[2]; + var password = args[3]; // NP connection setup log.DebugFormat("Connecting to {0}:{1}...", hostname, port); @@ -129,6 +129,7 @@ namespace NPSharp.CommandLine.MOTD { log.InfoFormat("Server says: {0}", Encoding.UTF8.GetString(np.GetPublisherFile("motd-english.txt").Result)); + np.Disconnect(); } catch { diff --git a/src/npserv/App.config b/src/npserv/App.config index a2dd99c..728a6f5 100644 --- a/src/npserv/App.config +++ b/src/npserv/App.config @@ -1,8 +1,9 @@  + - - - + + + diff --git a/src/npserv/BrightstarDatabaseAuthenticationHandler.cs b/src/npserv/BrightstarDatabaseAuthenticationHandler.cs new file mode 100644 index 0000000..fd623e0 --- /dev/null +++ b/src/npserv/BrightstarDatabaseAuthenticationHandler.cs @@ -0,0 +1,69 @@ +using System; +using System.Globalization; +using System.Linq; +using log4net; +using NPSharp.CommandLine.Server.Database; +using NPSharp.Steam; + +namespace NPSharp.CommandLine.Server +{ + internal class BrightstarDatabaseAuthenticationHandler : IAuthenticationHandler + { + private readonly BrightstarDatabaseContext _db; + private readonly ILog _log; + + public BrightstarDatabaseAuthenticationHandler(BrightstarDatabaseContext database) + { + _log = LogManager.GetLogger("AuthHandler"); + _db = database; + } + + public AuthenticationResult AuthenticateUser(NPServerClient client, string username, string password) + { + // Nah, authenticating this way is deprecated as fuck. + return new AuthenticationResult(); + } + + public AuthenticationResult AuthenticateUser(NPServerClient client, string token) + { + // Check if token is valid + var resultEnum = _db.Sessions.Where(s => s.Id == token && s.ExpiryTime > DateTime.Now); + if (!resultEnum.Any()) + return new AuthenticationResult(); // authentication failed because token is invalid + + var session = resultEnum.Single(); + + var ar = + new AuthenticationResult(new CSteamID + { + AccountID = uint.Parse(session.User.Id, NumberStyles.Integer), + AccountInstance = 1, + AccountType = EAccountType.Individual, + AccountUniverse = EUniverse.Public + }); + + _db.DeleteObject(session); + _db.SaveChanges(); + _log.DebugFormat("Deleted now used session {0}", session.Id); + + return ar; + } + + public AuthenticationResult AuthenticateServer(NPServerClient client, string licenseKey) + { + // TODO: AuthenticateServer + throw new NotImplementedException(); + } + + public TicketValidationResult ValidateTicket(NPServerClient client, NPServerClient server) + { + // TODO: ValidateTicket + throw new NotImplementedException(); + } + + ~BrightstarDatabaseAuthenticationHandler() + { + _db.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/npserv/BrightstarDatabaseFileServingHandler.cs b/src/npserv/BrightstarDatabaseFileServingHandler.cs new file mode 100644 index 0000000..7010325 --- /dev/null +++ b/src/npserv/BrightstarDatabaseFileServingHandler.cs @@ -0,0 +1,84 @@ +using System.Globalization; +using System.Linq; +using System.Text; +using NPSharp.CommandLine.Server.Database; + +namespace NPSharp.CommandLine.Server +{ + internal class BrightstarDatabaseFileServingHandler : IFileServingHandler + { + private readonly BrightstarDatabaseContext _db; + + public BrightstarDatabaseFileServingHandler(BrightstarDatabaseContext database) + { + //_database = database; + _db = database; + } + + ~BrightstarDatabaseFileServingHandler() + { + _db.Dispose(); + } + + public byte[] ReadUserFile(NPServerClient client, string file) + { + var resultEnum = + _db.UserFiles.Where(uf => uf.User.Id == client.UserID.AccountID.ToString(CultureInfo.InvariantCulture) && uf.FileName == file); + + return resultEnum.Any() ? resultEnum.Single().FileData : null; + } + + public byte[] ReadPublisherFile(NPServerClient client, string file) + { + var resultEnum = + _db.PublisherFiles.Where(pf => pf.FileName == file); + + return resultEnum.Any() ? resultEnum.Single().FileData : null; + } + + public void WriteUserFile(NPServerClient client, string file, byte[] data) + { + var resultEnum = + _db.UserFiles.Where(uf => uf.User.Id == client.UserID.AccountID.ToString(CultureInfo.InvariantCulture) && uf.FileName == file); + + var userFile = resultEnum.Any() ? resultEnum.Single() : _db.UserFiles.Create(); + userFile.FileName = file; + userFile.FileData = data; + userFile.User = _db.Users.Single(u => u.Id == client.UserID.AccountID.ToString(CultureInfo.InvariantCulture)); + + _db.SaveChanges(); + } + + protected byte[] GetDefaultUserFile(string file) + { + switch (file) + { + case "iw4.stat": + return new byte[8*1024]; + default: + return null; + } + } + + protected byte[] GetDefaultPublisherFile(string file) + { + switch (file) + { + case "hello_world.txt": + case "motd-english.txt": + case "motd-german.txt": + case "motd-french.txt": + case "motd-russian.txt": + case "motd-spanish.txt": + return Encoding.UTF8.GetBytes("hello"); + case "playerlog.csv": + case "social_tu1.cfg": + case "heatmap.raw": + case "online_mp.img": + return new byte[0]; + default: + return null; + } + } + } +} \ No newline at end of file diff --git a/src/npserv/Database/BrightstarDatabaseContext.cs b/src/npserv/Database/BrightstarDatabaseContext.cs new file mode 100644 index 0000000..8a39b69 --- /dev/null +++ b/src/npserv/Database/BrightstarDatabaseContext.cs @@ -0,0 +1,501 @@ +// ----------------------------------------------------------------------- +// +// This code was generated from a template. +// +// Changes to this file may cause incorrect behaviour and will be lost +// if the code is regenerated. +// +//------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using BrightstarDB.Client; +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + public class BrightstarDatabaseContext : BrightstarEntityContext + { + private static readonly EntityMappingStore TypeMappings; + + static BrightstarDatabaseContext() + { + TypeMappings = new EntityMappingStore(); + var provider = new ReflectionMappingProvider(); + provider.AddMappingsForType(TypeMappings, typeof (IBan)); + TypeMappings.SetImplMapping(); + provider.AddMappingsForType(TypeMappings, typeof (ICheatDetection)); + TypeMappings.SetImplMapping(); + provider.AddMappingsForType(TypeMappings, typeof (IFriend)); + TypeMappings.SetImplMapping(); + provider.AddMappingsForType(TypeMappings, typeof (IPublisherFile)); + TypeMappings.SetImplMapping(); + provider.AddMappingsForType(TypeMappings, typeof (ISession)); + TypeMappings.SetImplMapping(); + provider.AddMappingsForType(TypeMappings, typeof (IUser)); + TypeMappings.SetImplMapping(); + provider.AddMappingsForType(TypeMappings, typeof (IUserFile)); + TypeMappings.SetImplMapping(); + } + + /// + /// Initialize a new entity context using the specified BrightstarDB + /// Data Object Store connection + /// + /// The connection to the BrightstarDB Data Object Store that will provide the entity objects + /// + /// OPTIONAL: A that overrides the default mappings generated + /// by reflection. + /// + public BrightstarDatabaseContext(IDataObjectStore dataObjectStore, EntityMappingStore typeMappings = null) + : base(typeMappings ?? TypeMappings, dataObjectStore) + { + InitializeContext(); + } + + /// + /// Initialize a new entity context using the specified Brightstar connection string + /// + /// The connection to be used to connect to an existing BrightstarDB store + /// OPTIONAL: If set to true optmistic locking will be applied to all entity updates + /// + /// OPTIONAL: The URI identifier of the graph to be updated with any new triples created by operations on the store. If + /// not defined, the default graph in the store will be updated. + /// + /// + /// OPTIONAL: The URI identifiers of the graphs that will be queried to retrieve entities and their properties. + /// If not defined, all graphs in the store will be queried. + /// + /// + /// OPTIONAL: The URI identifier of the graph that contains version number statements for entities. + /// If not defined, the will be used. + /// + /// + /// OPTIONAL: A that overrides the default mappings generated + /// by reflection. + /// + public BrightstarDatabaseContext( + string connectionString, + bool? enableOptimisticLocking = null, + string updateGraphUri = null, + IEnumerable datasetGraphUris = null, + string versionGraphUri = null, + EntityMappingStore typeMappings = null + ) + : base( + typeMappings ?? TypeMappings, connectionString, enableOptimisticLocking, updateGraphUri, + datasetGraphUris, versionGraphUri) + { + InitializeContext(); + } + + /// + /// Initialize a new entity context using the specified Brightstar + /// connection string retrieved from the configuration. + /// + /// + /// OPTIONAL: A that overrides the default mappings generated + /// by reflection. + /// + public BrightstarDatabaseContext(EntityMappingStore typeMappings = null) : base(typeMappings ?? TypeMappings) + { + InitializeContext(); + } + + // specified target graphs + /// + /// Initialize a new entity context using the specified Brightstar + /// connection string retrieved from the configuration and the + /// + /// + /// The URI identifier of the graph to be updated with any new triples created by operations on the store. If + /// set to null, the default graph in the store will be updated. + /// + /// + /// The URI identifiers of the graphs that will be queried to retrieve entities and their properties. + /// If set to null, all graphs in the store will be queried. + /// + /// + /// The URI identifier of the graph that contains version number statements for entities. + /// If set to null, the value of will be used. + /// + /// + /// OPTIONAL: A that overrides the default mappings generated + /// by reflection. + /// + public BrightstarDatabaseContext( + string updateGraphUri, + IEnumerable datasetGraphUris, + string versionGraphUri, + EntityMappingStore typeMappings = null + ) : base(typeMappings ?? TypeMappings, updateGraphUri, datasetGraphUris, versionGraphUri) + { + InitializeContext(); + } + + public IEntitySet Bans { get; private set; } + + public IEntitySet CheatDetections { get; private set; } + + public IEntitySet Friends { get; private set; } + + public IEntitySet PublisherFiles { get; private set; } + + public IEntitySet Sessions { get; private set; } + + public IEntitySet Users { get; private set; } + + public IEntitySet UserFiles { get; private set; } + + private void InitializeContext() + { + Bans = new BrightstarEntitySet(this); + CheatDetections = new BrightstarEntitySet(this); + Friends = new BrightstarEntitySet(this); + PublisherFiles = new BrightstarEntitySet(this); + Sessions = new BrightstarEntitySet(this); + Users = new BrightstarEntitySet(this); + UserFiles = new BrightstarEntitySet(this); + } + } +} + +namespace NPSharp.CommandLine.Server.Database +{ + public class Ban : BrightstarEntityObject, IBan + { + public Ban(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) + { + } + + public Ban() + { + } + + public String Id + { + get { return GetIdentity(); } + set { SetIdentity(value); } + } + + #region Implementation of NPSharp.CommandLine.Server.Database.IBan + + public IUser User + { + get { return GetRelatedObject("User"); } + } + + public String Reason + { + get { return GetRelatedProperty("Reason"); } + set { SetRelatedProperty("Reason", value); } + } + + public DateTime ExpiryTime + { + get { return GetRelatedProperty("ExpiryTime"); } + set { SetRelatedProperty("ExpiryTime", value); } + } + + #endregion + } +} + +namespace NPSharp.CommandLine.Server.Database +{ + public class CheatDetection : BrightstarEntityObject, ICheatDetection + { + public CheatDetection(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) + { + } + + public CheatDetection() + { + } + + public String Id + { + get { return GetIdentity(); } + set { SetIdentity(value); } + } + + #region Implementation of NPSharp.CommandLine.Server.Database.ICheatDetection + + public IUser User + { + get { return GetRelatedObject("User"); } + } + + public UInt32 CheatId + { + get { return GetRelatedProperty("CheatId"); } + set { SetRelatedProperty("CheatId", value); } + } + + public String Reason + { + get { return GetRelatedProperty("Reason"); } + set { SetRelatedProperty("Reason", value); } + } + + public DateTime ExpiryTime + { + get { return GetRelatedProperty("ExpiryTime"); } + set { SetRelatedProperty("ExpiryTime", value); } + } + + #endregion + } +} + +namespace NPSharp.CommandLine.Server.Database +{ + public class Friend : BrightstarEntityObject, IFriend + { + public Friend(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) + { + } + + public Friend() + { + } + + public String Id + { + get { return GetIdentity(); } + set { SetIdentity(value); } + } + + #region Implementation of NPSharp.CommandLine.Server.Database.IFriend + + public IUser User + { + get { return GetRelatedObject("User"); } + } + + public UInt32 FriendUserId + { + get { return GetRelatedProperty("FriendUserId"); } + set { SetRelatedProperty("FriendUserId", value); } + } + + public String FriendName + { + get { return GetRelatedProperty("FriendName"); } + set { SetRelatedProperty("FriendName", value); } + } + + #endregion + } +} + +namespace NPSharp.CommandLine.Server.Database +{ + public class PublisherFile : BrightstarEntityObject, IPublisherFile + { + public PublisherFile(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) + { + } + + public PublisherFile() + { + } + + public String Id + { + get { return GetIdentity(); } + set { SetIdentity(value); } + } + + #region Implementation of NPSharp.CommandLine.Server.Database.IPublisherFile + + public String FileName + { + get { return GetRelatedProperty("FileName"); } + set { SetRelatedProperty("FileName", value); } + } + + public Byte[] FileData + { + get { return GetRelatedProperty("FileData"); } + set { SetRelatedProperty("FileData", value); } + } + + #endregion + } +} + +namespace NPSharp.CommandLine.Server.Database +{ + public class Session : BrightstarEntityObject, ISession + { + public Session(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) + { + } + + public Session() + { + } + + public String Id + { + get { return GetIdentity(); } + set { SetIdentity(value); } + } + + #region Implementation of NPSharp.CommandLine.Server.Database.ISession + + public IUser User + { + get { return GetRelatedObject("User"); } + } + + public DateTime ExpiryTime + { + get { return GetRelatedProperty("ExpiryTime"); } + set { SetRelatedProperty("ExpiryTime", value); } + } + + #endregion + } +} + +namespace NPSharp.CommandLine.Server.Database +{ + public class User : BrightstarEntityObject, IUser + { + public User(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) + { + } + + public User() + { + } + + public String Id + { + get { return GetIdentity(); } + set { SetIdentity(value); } + } + + #region Implementation of NPSharp.CommandLine.Server.Database.IUser + + public String UserName + { + get { return GetRelatedProperty("UserName"); } + set { SetRelatedProperty("UserName", value); } + } + + public String UserMail + { + get { return GetRelatedProperty("UserMail"); } + set { SetRelatedProperty("UserMail", value); } + } + + public String PasswordHash + { + get { return GetRelatedProperty("PasswordHash"); } + set { SetRelatedProperty("PasswordHash", value); } + } + + public DateTime LastLogin + { + get { return GetRelatedProperty("LastLogin"); } + set { SetRelatedProperty("LastLogin", value); } + } + + public ICollection Sessions + { + get { return GetRelatedObjects("Sessions"); } + set + { + if (value == null) throw new ArgumentNullException("value"); + SetRelatedObjects("Sessions", value); + } + } + + public ICollection Bans + { + get { return GetRelatedObjects("Bans"); } + set + { + if (value == null) throw new ArgumentNullException("value"); + SetRelatedObjects("Bans", value); + } + } + + public ICollection CheatDetections + { + get { return GetRelatedObjects("CheatDetections"); } + set + { + if (value == null) throw new ArgumentNullException("value"); + SetRelatedObjects("CheatDetections", value); + } + } + + public ICollection UserFiles + { + get { return GetRelatedObjects("UserFiles"); } + set + { + if (value == null) throw new ArgumentNullException("value"); + SetRelatedObjects("UserFiles", value); + } + } + + public ICollection FriendIDs + { + get { return GetRelatedObjects("FriendIDs"); } + set + { + if (value == null) throw new ArgumentNullException("value"); + SetRelatedObjects("FriendIDs", value); + } + } + + #endregion + } +} + +namespace NPSharp.CommandLine.Server.Database +{ + public class UserFile : BrightstarEntityObject, IUserFile + { + public UserFile(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) + { + } + + public UserFile() + { + } + + public String Id + { + get { return GetIdentity(); } + set { SetIdentity(value); } + } + + #region Implementation of NPSharp.CommandLine.Server.Database.IUserFile + + public IUser User + { + get { return GetRelatedObject("User"); } + set { SetRelatedObject("User", value); } + } + + public String FileName + { + get { return GetRelatedProperty("FileName"); } + set { SetRelatedProperty("FileName", value); } + } + + public Byte[] FileData + { + get { return GetRelatedProperty("FileData"); } + set { SetRelatedProperty("FileData", value); } + } + + #endregion + } +} \ No newline at end of file diff --git a/src/npserv/Database/BrightstarDatabaseContext.tt b/src/npserv/Database/BrightstarDatabaseContext.tt new file mode 100644 index 0000000..effffeb --- /dev/null +++ b/src/npserv/Database/BrightstarDatabaseContext.tt @@ -0,0 +1,918 @@ +<#@ template debug="true" hostSpecific="true" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="EnvDTE80" #> +<#@ import namespace="System" #> +<#@ import namespace="System.IO" #> +<#@ import namespace="System.Diagnostics" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Collections" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="EnvDTE" #> +<#@ import namespace="EnvDTE80" #> +<#@ import namespace="Microsoft.VisualStudio.TextTemplating"#> +<#@ include file="EF.Utility.CS.ttinclude"#> +<# +var code = new CodeGenerationTools(this); +var helper = new Helper(this); +var namespaceName = code.VsNamespaceSuggestion(); +var contextClassName = System.IO.Path.GetFileNameWithoutExtension(this.Host.TemplateFile); +WriteHeader(helper.GetExtraUsings().ToArray()); +BeginNamespace(code, namespaceName); +WriteContextClass(code, helper, contextClassName); +EndNamespace(namespaceName); +foreach(var i in helper.GetDecoratedInterfaces()) { + WriteEntityClass(code, helper, i); +} +#> +<#+ +public void WriteHeader(params string[] extraUsings) { +#> +// ----------------------------------------------------------------------- +// +// This code was generated from a template. +// +// Changes to this file may cause incorrect behaviour and will be lost +// if the code is regenerated. +// +//------------------------------------------------------------------------ +using System; +using System.Collections.Generic; +using System.Linq; +using BrightstarDB.Client; +using BrightstarDB.EntityFramework; + +<#=String.Join(String.Empty, extraUsings.Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#> +<#+ +} + +public void BeginNamespace(CodeGenerationTools code, string namespaceName) +{ + CodeRegion region = new CodeRegion(this); + if (!String.IsNullOrEmpty(namespaceName)) + { +#> +namespace <#=code.EscapeNamespace(namespaceName) #> +{ +<#+ + PushIndent(CodeRegion.GetIndent(1)); + } +} + +public void EndNamespace(string namespaceName) { + if (!String.IsNullOrEmpty(namespaceName)) { + PopIndent(); + #> +} +<#+ + } +} + +private void WriteContextClass(CodeGenerationTools code, Helper helper, string contextClassName) { +#> +public partial class <#=code.Escape(contextClassName) #> : BrightstarEntityContext { + private static readonly EntityMappingStore TypeMappings; + + static <#= code.Escape(contextClassName) #>() + { + TypeMappings = new EntityMappingStore(); + var provider = new ReflectionMappingProvider(); +<#+ + foreach(var i in helper.GetDecoratedInterfaces()) + { +#> + provider.AddMappingsForType(TypeMappings, typeof(<#=i.InterfaceFullName#>)); + TypeMappings.SetImplMapping<<#=i.InterfaceFullName#>, <#=code.CreateFullName(i.InterfaceNamespaceName, i.ClassName)#>>(); +<#+ + } +#> + } + + /// + /// Initialize a new entity context using the specified BrightstarDB + /// Data Object Store connection + /// + /// The connection to the BrightstarDB Data Object Store that will provide the entity objects + /// OPTIONAL: A that overrides the default mappings generated by reflection. + public <#= code.Escape(contextClassName) #>(IDataObjectStore dataObjectStore, EntityMappingStore typeMappings = null) : base(typeMappings ?? TypeMappings, dataObjectStore) + { + InitializeContext(); + } + + /// + /// Initialize a new entity context using the specified Brightstar connection string + /// + /// The connection to be used to connect to an existing BrightstarDB store + /// OPTIONAL: If set to true optmistic locking will be applied to all entity updates + /// OPTIONAL: The URI identifier of the graph to be updated with any new triples created by operations on the store. If + /// not defined, the default graph in the store will be updated. + /// OPTIONAL: The URI identifiers of the graphs that will be queried to retrieve entities and their properties. + /// If not defined, all graphs in the store will be queried. + /// OPTIONAL: The URI identifier of the graph that contains version number statements for entities. + /// If not defined, the will be used. + /// OPTIONAL: A that overrides the default mappings generated by reflection. + public <#= code.Escape(contextClassName) #>( + string connectionString, + bool? enableOptimisticLocking=null, + string updateGraphUri = null, + IEnumerable datasetGraphUris = null, + string versionGraphUri = null, + EntityMappingStore typeMappings = null + ) : base(typeMappings ?? TypeMappings, connectionString, enableOptimisticLocking, updateGraphUri, datasetGraphUris, versionGraphUri) + { + InitializeContext(); + } + + /// + /// Initialize a new entity context using the specified Brightstar + /// connection string retrieved from the configuration. + /// + /// OPTIONAL: A that overrides the default mappings generated by reflection. + public <#= code.Escape(contextClassName) #>(EntityMappingStore typeMappings = null) : base(typeMappings ?? TypeMappings) + { + InitializeContext(); + } + + /// + /// Initialize a new entity context using the specified Brightstar + /// connection string retrieved from the configuration and the + // specified target graphs + /// + /// The URI identifier of the graph to be updated with any new triples created by operations on the store. If + /// set to null, the default graph in the store will be updated. + /// The URI identifiers of the graphs that will be queried to retrieve entities and their properties. + /// If set to null, all graphs in the store will be queried. + /// The URI identifier of the graph that contains version number statements for entities. + /// If set to null, the value of will be used. + /// OPTIONAL: A that overrides the default mappings generated by reflection. + public <#= code.Escape(contextClassName) #>( + string updateGraphUri, + IEnumerable datasetGraphUris, + string versionGraphUri, + EntityMappingStore typeMappings = null + ) : base(typeMappings ?? TypeMappings, updateGraphUri:updateGraphUri, datasetGraphUris:datasetGraphUris, versionGraphUri:versionGraphUri) + { + InitializeContext(); + } + + private void InitializeContext() + { +<#+ + foreach(var i in helper.GetDecoratedInterfaces()) { +#> + <#= code.Escape(i.PluralizedName) #> = new BrightstarEntitySet<<#=i.InterfaceFullName#>>(this); +<#+ + } +#> + } + +<#+ + foreach(var i in helper.GetDecoratedInterfaces()) + { +#> + <#=i.EntitySetAccessLevel#> IEntitySet<<#=i.InterfaceFullName#>> <#= code.Escape(i.PluralizedName) #> + { + get; private set; + } + +<#+ + } +#> +} +<#+ +} + +private void WriteEntityClass(CodeGenerationTools code, Helper helper, ResourceInterface iface) +{ + BeginNamespace(code, iface.InterfaceNamespaceName); + var identityProperty = iface.IdentityProperty; + WriteClassAttributes(code, helper, iface); +#> + +<#= code.SpaceAfter(iface.EntitySetAccessLevel)#>partial class <#= iface.ClassName #> : BrightstarEntityObject, <#= iface.InterfaceName #> +{ + public <#= iface.ClassName#>(BrightstarEntityContext context, IDataObject dataObject) : base(context, dataObject) { } + public <#= iface.ClassName#>() : base() { } +<#+ + if (identityProperty != null) + { + ValidateIdentityProperty(identityProperty); +#> + public <#= ((CodeProperty)identityProperty).Type.AsFullName #> <#= identityProperty.Name #> { get {return GetIdentity(); } set { SetIdentity(value); } } +<#+ + } + + WriteInterfaceImplementation(code, helper, iface); + foreach(var b in iface.AllInterfaces){ + WriteInterfaceImplementation(code, helper, b); + } + + #> +} +<#+ + EndNamespace(iface.InterfaceNamespaceName); +} + +private void WriteInterfaceImplementation(CodeGenerationTools code, Helper helper, ResourceInterface iface) +{#> + #region Implementation of <#= iface.InterfaceFullName #> +<#+ + foreach(var p in iface.Properties) { + if (!p.Equals(iface.IdentityProperty)) + { + bool isCollectionProperty; + if (ValidateProperty(p, helper, out isCollectionProperty)) + { + WritePropertyAttributes(code, helper, p); + if (isCollectionProperty) + { + string generic, t; + Helper.TryParseGenericTypeName(p.Type.AsFullName, out generic, out t); + generic = Helper.GetEntityGeneric(generic); + if (generic == null) + { + this.Error(String.Format("There is no known mapping for the generic type {0} on the property {1} of type {2}", + generic, p.Name, p.Type.AsFullName)); + } + else + { +#> + public <#= generic#><<#=t#>> <#= p.Name #> + { +<#+ + if (helper.GetDecoratedInterfaces().Any(x=>x.InterfaceFullName.Equals(t))) + { + #> + get { return GetRelatedObjects<<#=t#>>(<#= code.CreateLiteral(p.Name) #>); } + set { if (value == null) throw new ArgumentNullException("value"); SetRelatedObjects(<#= code.CreateLiteral(p.Name)#>, value); } + <#+ + } + else + { + #> + get { return GetRelatedLiteralPropertiesCollection<<#=t#>>(<#= code.CreateLiteral(p.Name) #>); } + set { if (value == null) throw new ArgumentNullException("value"); SetRelatedLiteralPropertiesCollection<<#=t#>>(<#= code.CreateLiteral(p.Name)#>, value); } +<#+ + } +#> + } +<#+ + } + } + else + { + var itemType = GetPropertyTypeName(p.Type); +#> + + public <#= itemType #> <#= p.Name #> + { +<#+ + PushIndent(CodeRegion.GetIndent(2)); + if (IsValidLiteralType(helper, p.Type)) + { +#> + get { return GetRelatedProperty<<#= itemType #>>(<#=code.CreateLiteral(p.Name)#>); } + set { SetRelatedProperty(<#=code.CreateLiteral(p.Name)#>, value); } +<#+ + } + else + { + if (p.Getter != null) WriteSingleGetter(code, p); + if (p.Setter != null) WriteSingleSetter(code, p); + } + PopIndent(); +#> + } +<#+ + } + } + } + } +#> + #endregion +<#+ +} + +private void WriteCustomAttribute(Helper helper, CodeAttribute attr) +{ + if (attr.FullName.Equals("BrightstarDB.EntityFramework.ClassAttributeAttribute")) + { + var e = attr.Children.GetEnumerator(); + if (e.MoveNext()) + { + var classAttributeArg = e.Current as EnvDTE80.CodeAttributeArgument; + if (classAttributeArg != null) { + #><#=helper.Unquote(classAttributeArg.Value)#><#+ + } + } + } + if (attr.FullName.StartsWith("BrightstarDB.EntityFramework")) + { + return; + } + #> + + [<#= attr.FullName#><#+ + var childEnumerator = attr.Children.GetEnumerator(); + if (childEnumerator.MoveNext()) + { + bool keepGoing = true; + #>(<#+ + while (keepGoing) { + if (childEnumerator.Current is EnvDTE80.CodeAttributeArgument) + { + var arg = childEnumerator.Current as EnvDTE80.CodeAttributeArgument; + if (!String.IsNullOrEmpty(arg.Name)) { + #><#=arg.Name#>=<#=arg.Value#><#+ + } + else + { + #><#=arg.Value#><#+ + } + keepGoing = childEnumerator.MoveNext(); + if (keepGoing) { + #>, <#+ + } + } + } + #>)<#+ + } + #>]<#+ +} + +private void WriteClassAttributes(CodeGenerationTools code, Helper helper, ResourceInterface iface) +{ + foreach(var x in iface.Interface.Attributes) + { + if (x is CodeAttribute) { + WriteCustomAttribute(helper, x as CodeAttribute); + } + } +} + +private void WritePropertyAttributes(CodeGenerationTools code, Helper helper, CodeProperty property) +{ + foreach(var x in property.Attributes) + { + if (x is CodeAttribute) + { + var attr = x as CodeAttribute; + WriteCustomAttribute(helper, attr); + + } + } +} + +private bool IsValidLiteralType(Helper helper, CodeTypeRef t) +{ + if (Constants.BasicTypes.Contains(t.AsFullName) || + IsByteArray(t) || + t.CodeType.IsDerivedFrom["System.Enum"]) { + return true; + } + + string genericName, typeName; + if (Helper.TryParseGenericTypeName(t.AsFullName, out genericName, out typeName) + && genericName.Equals("System.Nullable") + && helper.GetEnums().Any(e=>e.FullName.Equals(typeName))) { + return true; + } + + return false; +} + +private bool IsByteArray(CodeTypeRef t) +{ + return t.TypeKind == vsCMTypeRef.vsCMTypeRefArray && t.ElementType.AsFullName == "System.Byte"; +} + +private void WriteCollectionGetter(CodeGenerationTools code, CodeProperty property, string itemType) { + if (Constants.BasicTypes.Contains(itemType)) + { + #> +get { return GetRelatedProperties<<#= itemType #>>(<#=code.CreateLiteral(property.Name) #>); } + <#+ + } + else + { +#> +get { return GetRelatedObjects<<#= itemType #>>(<#=code.CreateLiteral(property.Name)#>); } +<#+ + } +} + +private void WriteCollectionSetter(CodeGenerationTools code, CodeProperty property, string itemType) { + if (Constants.BasicTypes.Contains(itemType)) + { +#> +set { SetRelatedProperties(<#= code.CreateLiteral(property.Name) #>, value); } +<#+ + } + else + { +#> +set { SetRelatedObjects(<#= code.CreateLiteral(property.Name) #>, value ); } +<#+ + } +} + +private void WriteSingleGetter(CodeGenerationTools code, CodeProperty property) +{ + var itemType = property.Type.AsFullName; +#> +get { return GetRelatedObject<<#= itemType #>>(<#=code.CreateLiteral(property.Name)#>); } +<#+ +} + +private void WriteSingleSetter(CodeGenerationTools code, CodeProperty property) { + var itemType = property.Type.AsFullName; +#> +set { SetRelatedObject<<#= itemType #>>(<#=code.CreateLiteral(property.Name)#>, value); } +<#+ +} + +private string GetPropertyTypeName(CodeTypeRef propertyType) +{ + if (propertyType.TypeKind == vsCMTypeRef.vsCMTypeRefArray) { + return propertyType.ElementType.AsFullName + "[]"; + } else { + return propertyType.AsFullName; + } +} + +private void ValidateIdentityProperty(CodeProperty property) { + if (!property.Type.AsFullName.Equals("System.String")) + { + Error(String.Format("The property '{0}' must be of type String to be used as the identity property for an entity. If this property is intended to be the identity property for the entity please change its type to String. If it is not intended to be the identity property, either rename this property or create an identity property and decorate it with the [{1}] attribute.", + property.FullName, Constants.IdentityAttributeShortName)); + } + if (property.Setter != null) { + Error(String.Format("The property '{0}' must not have a setter to be used as the identity property for an entity. If this property is intended to be the identity property for the entity please remove the setter. If it is not intended to be the identity property, either rename this property or create an identity propertyn and decorate it with the [{1}] attribute.", + property.FullName, Constants.IdentityAttributeShortName)); + } +} + +private bool ValidateProperty(CodeProperty property, Helper helper, out bool isCollection) +{ + var propertyTypeName = property.Type.AsFullName; + isCollection = false; + bool isValid = false; + + if (IsValidLiteralType(helper, property.Type) || + helper.GetDecoratedInterfaces().Any(i=>i.InterfaceFullName.Equals(propertyTypeName))) + { + isValid = true; + } + else + { + string generic, t; + if (Helper.TryParseGenericTypeName(propertyTypeName, out generic, out t)) + { + if (Constants.CollectionTypes.Contains(generic) && + (Constants.BasicTypes.Contains(t) || helper.GetDecoratedInterfaces().Any(i=>i.InterfaceFullName.Equals(t)))) + { + isCollection = true; + isValid = true; + propertyTypeName = t; + } + } + } + if (!isValid) + { + Error("Invalid property: " + property.FullName + " - the property type " + propertyTypeName + " is not supported by Entity Framework."); + isCollection = false; + return false; + } + + var inversePropertyAttr = property.Attributes.OfType().FirstOrDefault( + attr => attr.FullName.Equals(Constants.InversePropertyAttributeName)); + if (inversePropertyAttr != null) + { + var arg = inversePropertyAttr.Children.OfType().FirstOrDefault(); + var inversePropertyName = arg.Value.Trim('\"'); + var targetInterface = helper.GetDecoratedInterfaces().FirstOrDefault(i=>i.InterfaceFullName.Equals(propertyTypeName)); + if (targetInterface == null) + { + this.Error("Invalid InverseProperty attribute on property " + property.Name + ". The property type " + propertyTypeName + " must be marked as an Entity."); + return false; + } + + var targetProperty = targetInterface.Properties.FirstOrDefault(p=>p.Name.Equals(inversePropertyName)); + if (targetProperty == null) + { + this.Error("Invalid InverseProperty attribute on property " + property.Name + ". A property named '" + inversePropertyName + "' cannot be found on the target interface type '" + targetInterface.InterfaceFullName + "'."); + return false; + } + } + return true; +} + +static class Constants { + public const string IdentityAttributeName = "BrightstarDB.EntityFramework.IdentifierAttribute"; + public const string IdentityAttributeShortName = "Identifier"; + public const string EntityAttributeName = "BrightstarDB.EntityFramework.EntityAttribute"; + public const string InversePropertyAttributeName = "BrightstarDB.EntityFramework.InversePropertyAttribute"; + /// + /// The property types that are supported entity property types + /// + public static readonly List BasicTypes = new List + { + "System.Boolean", + "System.Int16", + "System.Int64", + "System.Int32", + "System.UInt16", + "System.UInt32", + "System.UInt64", + "System.String", + "System.DateTime", + "System.Decimal", + "System.Double", + "System.Single", + "System.Uri", + "System.Byte", + "System.Char", + "System.SByte", + "BrightstarDB.Rdf.PlainLiteral", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + "System.Nullable", + }; + + /// + /// The generic collection types that are supported entity collection property types + /// + public static readonly List CollectionTypes = new List + { + "System.Collections.Generic.ISet", + "System.Collections.Generic.ICollection", + }; + + public static readonly List CoreImports = new List { + "System", "System.Collections.Generic", "System.Linq", "BrightstarDB.Client", "BrightstarDB.EntityFramework" + }; +} + +class Helper { + + private DTE _dte; + public static TextTransformation _transformation; + private ProjectItem _templateProjectItem; + private Project _project; + + public Helper(TextTransformation transformation) { + _transformation = transformation; + _templateProjectItem = DTE.Solution.FindProjectItem(Host.TemplateFile); + _project = _templateProjectItem.ContainingProject; + } + + public ITextTemplatingEngineHost Host { + get { + return _transformation.GetType().GetProperty("Host").GetValue(_transformation, null) as ITextTemplatingEngineHost; + } + } + + public DTE DTE + { + get { + if (_dte == null) { + IServiceProvider hostServiceProvider = (IServiceProvider)Host; + _dte = hostServiceProvider.GetService(typeof(DTE)) as DTE; + } + return _dte; + } + } + + public IEnumerable GetInterfaces() { + foreach(var pi in GetCodeProjectItems()) { + foreach(CodeElement ce in GetInterfaces(pi.FileCodeModel.CodeElements)) { + yield return ce; + } + } + } + + public IEnumerable GetDecoratedInterfaces() { + return GetCodeProjectItems().SelectMany(pi=>GetDecoratedInterfaces(pi.FileCodeModel.CodeElements)).Select(x=>new ResourceInterface(x)); + } + + /// + /// Returns an enumeration of all distinct using statements contained + /// in the files that define BrightstarDB Entity Framework entity interfaces + /// + public IEnumerable GetExtraUsings() { + return GetCodeProjectItems() + .Where(pi=>GetDecoratedInterfaces(pi.FileCodeModel.CodeElements).Any()) + .SelectMany(pi=>pi.FileCodeModel.CodeElements.OfType().Select(ce=>ce.Namespace)) + .Distinct().Except(Constants.CoreImports); + } + + /// + /// Returns an enumeration over all the enums types defined in the project + /// + /// + public IEnumerable GetEnums() { + foreach(var pi in GetCodeProjectItems()) { + foreach(CodeElement ce in GetEnums(pi.FileCodeModel.CodeElements)) { + yield return (CodeEnum)ce; + } + } + } + + /// + /// Pass-through write operation to allow this class to contain template output + /// + /// + public void Write(string text) { + _transformation.Write(text); + } + + /// + /// Pass-through write operation to allow this class to contain template output + /// + /// + public void Write(string msg, object[] args) { + _transformation.Write(msg, args); + } + + public static IEnumerable GetDecoratedInterfaces(CodeElements container) { + return GetInterfaces(container).Where(i=>i.Children.OfType().Any(c=>c.Kind == vsCMElement.vsCMElementAttribute && c.FullName.Equals(Constants.EntityAttributeName))); + } + + public static IEnumerable GetInterfaces(CodeElements container) { + foreach(CodeElement ce in container) { + if (ce.Kind == vsCMElement.vsCMElementInterface) { + yield return ce; + } else { + foreach(var child in GetInterfaces(ce.Children)) { + yield return child; + } + } + } + } + + public static IEnumerable GetEnums(CodeElements container) { + foreach(CodeElement ce in container) { + if (ce.Kind == vsCMElement.vsCMElementEnum) { + yield return ce; + } else { + foreach(var child in GetEnums(ce.Children)) { + yield return child; + } + } + } + } + + public static bool TryParseGenericTypeName(string genericTypeName, out string generic, out string t) + { + var regex = new System.Text.RegularExpressions.Regex(@"^([a-zA-Z0-9\.]+)<([^>]+)>$"); + var match = regex.Match(genericTypeName); + if (match.Success) + { + generic=match.Groups[1].Value; + t = match.Groups[2].Value; + return true; + } + else + { + generic = t = null; + return false; + } + } + + public static string GetEntityGeneric(string genericTypeName) + { + if (genericTypeName.Equals("System.Collections.Generic.ICollection")) + { + return "System.Collections.Generic.ICollection"; + } + return null; + } + + public IEnumerable GetCodeProjectItems() { + foreach(var pi in GetCodeProjectItems(_project.ProjectItems)) { + yield return pi; + } + } + + public string Unquote(string quotedString) + { + if(quotedString.StartsWith("\"")) + { + return quotedString.Trim('\"').Replace("\\\"", "\""); + } + else if (quotedString.StartsWith("@\"")) + { + return quotedString.TrimStart('@','\"').TrimEnd('\"'); + } + else + { + return quotedString; + } + } + private IEnumerable GetCodeProjectItems(ProjectItems projectItems) { + foreach(ProjectItem pi in projectItems) { + if (pi.Equals(_templateProjectItem)) { + continue; + } + if (pi.FileCodeModel != null) { + yield return pi; + } + if (pi.ProjectItems != null) { + foreach(var childItem in GetCodeProjectItems(pi.ProjectItems)) { + yield return childItem; + } + } + } + } +} + +class ResourceInterface { + private CodeInterface _interfaceCE; + private CodeProperty _identityProperty; + private string _className; + + public ResourceInterface(CodeInterface interfaceCE){ + _interfaceCE = interfaceCE; + _identityProperty = (CodeProperty)FindIdentityProperty(); + } + + public ResourceInterface(CodeElement rootElement) + { + _interfaceCE = ((CodeInterface)rootElement); + _identityProperty = (CodeProperty)FindIdentityProperty(); + } + + public IEnumerable Properties { + get + { + return _interfaceCE.Children + .OfType() + .Where(c=>c.Kind == vsCMElement.vsCMElementProperty) + .Select(c=>(CodeProperty)c); + } + } + + public CodeInterface Interface { + get { return _interfaceCE; } + } + + public IEnumerable BaseInterfaces + { + get + { + foreach(var baseInterface in _interfaceCE.Bases.OfType().Where(HasEntityAttribute)) + { + yield return new ResourceInterface(baseInterface); + } + } + } + + private bool HasEntityAttribute(CodeInterface iface) + { + try + { + return iface.Children.OfType().Any(c=>c.Kind == vsCMElement.vsCMElementAttribute && c.FullName.Equals(Constants.EntityAttributeName)); + } + catch + { + return false; + } + } + + public void GetAllInterfaces(List interfaces) + { + foreach (var ri in BaseInterfaces) + { + if (!interfaces.Contains(ri)) + { + interfaces.Add(ri); + } + ri.GetAllInterfaces(interfaces); + } + } + + public IEnumerable AllInterfaces { + get { + var resourceInterfaces = new List(); + GetAllInterfaces(resourceInterfaces); + return resourceInterfaces; + } + } + + private CodeProperty FindIdentityProperty() + { + // Find the identity property on the interface (if any) + var ret = Properties.Where( c=> + c.Attributes.OfType().Any( + attr => attr.FullName.Equals(Constants.IdentityAttributeName))).FirstOrDefault(); + if (ret == null) + ret = Properties.Where( c=> + (c.Name.Equals(ClassName+"Id") || c.Name.Equals(ClassName+"ID"))).FirstOrDefault(); + if (ret == null) + { + ret = Properties.Where( c=> + (c.Name.Equals("Id") || c.Name.Equals("ID"))).FirstOrDefault(); + } + + // if there is no indication on this class of an id property then check the interfaces we inherit from + if (ret == null) + { + foreach (var bi in AllInterfaces){ + ret = bi.FindIdentityProperty(); + if (ret != null) return ret; + } + } else { + foreach (var bi in AllInterfaces){ + var aret = bi.FindIdentityProperty(); + if (aret != null && (!aret.Name.Equals(ret.Name))) { + Helper._transformation.Error("Invalid identity property " + ret.Name + " on " + _interfaceCE.Name + " it differs from ancestor id " + aret.Name + " on " + bi.InterfaceName); + + } + } + } + + return ret; + } + + public void ValidateIdentityProperty(CodeProperty identityProperty){ + foreach (var bi in AllInterfaces){ + var aret = bi.FindIdentityProperty(); + if (aret != null && (aret.Name != identityProperty.Name)) { + throw new Exception("Invalid identity property. It differs from ancestor identity."); + } + } + } + + public string ClassName { + get { + if (_className == null) { + if (_interfaceCE.Name.StartsWith("I")) { + _className = _interfaceCE.Name.Substring(1); + } else { + _className = _interfaceCE.Name + "Impl"; + } + } + return _className; + } + } + + public string InterfaceName + { + get { return _interfaceCE.Name; } + } + + public string InterfaceFullName + { + get { return _interfaceCE.FullName; } + } + + public string InterfaceNamespaceName + { + get { return _interfaceCE.Namespace.FullName; } + } + + public CodeProperty IdentityProperty { + get {return _identityProperty; } + } + + public string PluralizedName { + get { return Pluralize(_interfaceCE.Name.StartsWith("I") ? _interfaceCE.Name.Substring(1) : _interfaceCE.Name); } + } + + public string Pluralize(string name) + { + if (name.EndsWith("y")) { + return name.Substring(0, name.Length - 1) + "ies"; + } + return name + "s"; + } + + public string EntitySetAccessLevel + { + get + { + switch (_interfaceCE.Access) { + case vsCMAccess.vsCMAccessPublic : + return "public"; + case vsCMAccess.vsCMAccessPrivate : + return "private"; + case vsCMAccess.vsCMAccessProject : + case vsCMAccess.vsCMAccessAssemblyOrFamily: + return "internal"; + default : + return "private"; + } + } + } +} +#> diff --git a/src/npserv/Database/IBan.cs b/src/npserv/Database/IBan.cs new file mode 100644 index 0000000..874fbbf --- /dev/null +++ b/src/npserv/Database/IBan.cs @@ -0,0 +1,17 @@ +using System; +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + [Entity] + public interface IBan + { + string Id { get; } + + IUser User { get; } + + string Reason { get; set; } + + DateTime ExpiryTime { get; set; } + } +} \ No newline at end of file diff --git a/src/npserv/Database/ICheatDetection.cs b/src/npserv/Database/ICheatDetection.cs new file mode 100644 index 0000000..2c99b6b --- /dev/null +++ b/src/npserv/Database/ICheatDetection.cs @@ -0,0 +1,19 @@ +using System; +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + [Entity] + public interface ICheatDetection + { + string Id { get; } + + IUser User { get; } + + uint CheatId { get; set; } + + string Reason { get; set; } + + DateTime ExpiryTime { get; set; } + } +} \ No newline at end of file diff --git a/src/npserv/Database/IFriend.cs b/src/npserv/Database/IFriend.cs new file mode 100644 index 0000000..52faadc --- /dev/null +++ b/src/npserv/Database/IFriend.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + [Entity] + public interface IFriend + { + string Id { get; } + + IUser User { get; } + + uint FriendUserId { get; set; } + + string FriendName { get; set; } + } +} diff --git a/src/npserv/Database/IPublisherFile.cs b/src/npserv/Database/IPublisherFile.cs new file mode 100644 index 0000000..14b046b --- /dev/null +++ b/src/npserv/Database/IPublisherFile.cs @@ -0,0 +1,14 @@ +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + [Entity] + public interface IPublisherFile + { + string Id { get; } + + string FileName { get; set; } + + byte[] FileData { get; set; } + } +} \ No newline at end of file diff --git a/src/npserv/Database/ISession.cs b/src/npserv/Database/ISession.cs new file mode 100644 index 0000000..c77f182 --- /dev/null +++ b/src/npserv/Database/ISession.cs @@ -0,0 +1,15 @@ +using System; +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + [Entity] + public interface ISession + { + string Id { get; } + + IUser User { get; } + + DateTime ExpiryTime { get; set; } + } +} \ No newline at end of file diff --git a/src/npserv/Database/IUser.cs b/src/npserv/Database/IUser.cs new file mode 100644 index 0000000..4a4c1f8 --- /dev/null +++ b/src/npserv/Database/IUser.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + [Entity] + public interface IUser + { + [Identifier("http://npserver.icedream.kthx.at/users/")] + string Id { get; } + + string UserName { get; set; } + + string UserMail { get; set; } + + string PasswordHash { get; set; } + + DateTime LastLogin { get; set; } + + [InverseProperty("User")] + ICollection Sessions { get; set; } + + [InverseProperty("User")] + ICollection Bans { get; set; } + + [InverseProperty("User")] + ICollection CheatDetections { get; set; } + + [InverseProperty("User")] + ICollection UserFiles { get; set; } + + [InverseProperty("User")] + ICollection FriendIDs { get; set; } + } +} \ No newline at end of file diff --git a/src/npserv/Database/IUserFile.cs b/src/npserv/Database/IUserFile.cs new file mode 100644 index 0000000..fde87fc --- /dev/null +++ b/src/npserv/Database/IUserFile.cs @@ -0,0 +1,16 @@ +using BrightstarDB.EntityFramework; + +namespace NPSharp.CommandLine.Server.Database +{ + [Entity] + public interface IUserFile + { + string Id { get; } + + IUser User { get; set; } + + string FileName { get; set; } + + byte[] FileData { get; set; } + } +} \ No newline at end of file diff --git a/src/npserv/Database/User.cs b/src/npserv/Database/User.cs deleted file mode 100644 index cb853bf..0000000 --- a/src/npserv/Database/User.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Collections.Generic; -using BCryptClass = BCrypt.Net.BCrypt; - -namespace NPSharp.CommandLine.Server.Database -{ - class Session - { - public Session() - { - Id = Guid.NewGuid().ToString("N"); - } - public string Id { get; set; } - public User User { get; set; } - public DateTime ExpiryTime { get; set; } - public TimeSpan ExpiresIn { get { return ExpiryTime - DateTime.Now; } } - public bool IsValid { get { return ExpiryTime >= DateTime.Now; } } - } - - class User - { - public uint Id { get; set; } - public string UserName { get; set; } - public string UserMail { get; set; } - public string PasswordHash { get; set; } - public DateTime LastLogin { get; set; } - public List BanIDs { get; set; } - public List CheatDetectionIDs { get; set; } - public List FriendIDs { get; set; } - - public bool ComparePassword(string pw) - { - return BCryptClass.Verify(pw, PasswordHash); - } - } - - class UserFile - { - public string Id { get; set; } - public string FileName { get; set; } - public uint UserID { get; set; } - public byte[] FileData { get; set; } - } - - class PublisherFile - { - public string Id { get; set; } - public string FileName { get; set; } - public byte[] FileData { get; set; } - } - - class Ban - { - public Ban() - { - Id = Guid.NewGuid().ToString("N"); - } - public string Id { get; set; } - public string Reason { get; set; } - public DateTime ExpiryTime { get; set; } - public TimeSpan ExpiresIn { get { return ExpiryTime - DateTime.Now; } } - public bool IsValid { get { return ExpiryTime >= DateTime.Now; } } - } - - class CheatDetection - { - public CheatDetection() - { - Id = Guid.NewGuid().ToString("N"); - } - public string Id { get; set; } - public uint CheatId { get; set; } - public uint UserId { get; set; } - public string Reason { get; set; } - public DateTime ExpiryTime { get; set; } - public TimeSpan ExpiresIn { get { return ExpiryTime - DateTime.Now; } } - public bool IsValid { get { return ExpiryTime >= DateTime.Now; } } - } -} diff --git a/src/npserv/Program.cs b/src/npserv/Program.cs index 732637a..7053bd5 100644 --- a/src/npserv/Program.cs +++ b/src/npserv/Program.cs @@ -1,6 +1,5 @@ using System; -using System.Collections.Generic; -using System.IO; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -11,22 +10,16 @@ using log4net.Core; using log4net.Layout; using NPSharp.Authentication; using NPSharp.CommandLine.Server.Database; -using Raven.Client; -using Raven.Client.Embedded; -using Raven.Client.Linq; -using Raven.Database.Server; namespace NPSharp.CommandLine.Server { - class Program + internal class Program { private static ILog _log; - private static IDocumentStore _database; - private static IDocumentSession _db; private static SessionAuthenticationServer _authServer; private static NPServer _np; - static void Main() + private static void Main() { InitializeLogging(); _log.Info("NP server is about to start up, this might take a few seconds..."); @@ -39,162 +32,151 @@ namespace NPSharp.CommandLine.Server Thread.Sleep(Timeout.Infinite); } - static void InitializeDatabase() + private static BrightstarDatabaseContext OpenDatabase(string store = "NP") { - _log.Debug("Starting Raven database..."); + // TODO: This line is CREATING a new database but it's supposed to open it only if it's already created. Look up! + return + new BrightstarDatabaseContext( + "type=embedded;storesdirectory=Database\\;storename=" + store, + true); + } -#if DEBUG - Directory.CreateDirectory(@"Raven"); - Directory.CreateDirectory(@"Raven\CompiledIndexCache"); -#endif - Directory.CreateDirectory(@"Database"); + private static void InitializeDatabase() + { + _log.Debug("Preparing database..."); - NonAdminHttp.EnsureCanListenToWhenInNonAdminContext(12002); - var database = new EmbeddableDocumentStore + using (var db = OpenDatabase()) { - DataDirectory = "Database", - UseEmbeddedHttpServer = true - }; - database.Configuration.Port = 12002; - database.Configuration.AllowLocalAccessWithoutAuthorization = true; - database.Configuration.DataDirectory = "Database"; - _database = database.Initialize(); + // Skip user creation if there are already registered users - _database.Conventions.IdentityTypeConvertors.Add(new UInt32Converter()); + // ReSharper disable once UseMethodAny.0 + // since SPARQL-to-LINQ does not have support for Any() yet + if (db.Users.Count() > 0) + return; - // Set up initial admin user - _db = _database.OpenSession(); - //using (var db = _database.OpenSession()) - //{ - if (!_db.Query().Any()) - { - _log.Warn("Creating default admin user because no users could be found in the database..."); - var adminUser = new User() - { - BanIDs = new List(), - CheatDetectionIDs = new List(), - FriendIDs = new List(), - PasswordHash = BCrypt.Net.BCrypt.HashPassword("test"), - UserMail = "admin@localhost", - UserName = "admin" - }; - _db.Store(adminUser); - _db.SaveChanges(); - _log.Warn("Default admin user created. For details see below."); - _log.Warn("\tUsername: admin"); - _log.Warn("\tPassword: test"); - _log.Warn("This only happens when no users can be found in the database. Change the details or create a new user to access the server asap!"); - } - //} + // Create first user (test:test) + var testUser = db.Users.Create(); + testUser.PasswordHash = BCrypt.Net.BCrypt.HashPassword("test"); + testUser.UserMail = "test@localhost"; + testUser.UserName = "test"; - // Endless loop to clean up expired stuff + _log.InfoFormat( + "Created first user with following details:" + Environment.NewLine + Environment.NewLine + + "Username: {0}" + Environment.NewLine + "Password: {1}", + testUser.UserName, + "test"); + + db.SaveChanges(); + + _log.DebugFormat("First user id is {0}", testUser.Id); + } + + // Cleanup thread Task.Factory.StartNew(() => { - while (_database != null && !_database.WasDisposed) + while (true) { - using (var db = _database.OpenSession()) + using (var dbForCleanup = OpenDatabase()) { - var expiredSessions = db.Query().Where(s => !s.IsValid).ToArray(); - foreach (var session in expiredSessions) - db.Delete(session); + _log.Debug("Starting cleanup..."); + foreach (var session in dbForCleanup.Sessions.Where(s => s.ExpiryTime < DateTime.Now).ToArray()) + { + _log.DebugFormat("Session {0} became invalid", session.Id); + dbForCleanup.DeleteObject(session); + } + foreach (var ban in dbForCleanup.Bans.Where(s => s.ExpiryTime < DateTime.Now).ToArray()) + { + _log.DebugFormat("Ban {0} became invalid", ban.Id); + dbForCleanup.DeleteObject(ban); + } + foreach ( + var cheatDetection in + dbForCleanup.CheatDetections.Where(s => s.ExpiryTime < DateTime.Now).ToArray()) + { + _log.DebugFormat("Cheat detection {0} became invalid", cheatDetection.Id); + dbForCleanup.DeleteObject(cheatDetection); + } - var expiredBans = db.Query().Where(b => !b.IsValid).ToArray(); - foreach (var ban in expiredBans) - db.Delete(ban); + _log.Debug("Saving cleanup..."); + dbForCleanup.SaveChanges(); - var expiredCheatDetections = db.Query().Where(cd => !cd.IsValid).ToArray(); - foreach (var cd in expiredCheatDetections) - db.Delete(cd); - - _log.DebugFormat( - "Purging {0} invalid sessions, {1} invalid bans and {2} invalid cheat detections", - expiredSessions.Length, - expiredBans.Length, - expiredCheatDetections.Length); - - db.SaveChanges(); + _log.Debug("Cleanup done."); } - Thread.Sleep(TimeSpan.FromMinutes(5)); + Thread.Sleep(TimeSpan.FromSeconds(30)); } + + // TODO: implement some way to cancel this loop + // ReSharper disable once FunctionNeverReturns }); } - static void InitializeAuthServer() + private static void InitializeAuthServer() { _log.Debug("Starting authentication server..."); _authServer = new SessionAuthenticationServer(); _authServer.Authenticating += (loginUsername, loginPassword) => { - //using (var db = _database.OpenSession()) - //{ - var resp = new SessionAuthenticationResult(); - - // Check if we have any user to which the given credentials fit - var users = _db - // database processing - .Query() - .Customize(x => x - .Include(o => o.BanIDs) - .Include(o => o.CheatDetectionIDs)) - .Where(u => u.UserName == loginUsername) - .ToArray() + using (var db = OpenDatabase()) + { + var matchingUsers = + db.Users.Where(u => u.UserName == loginUsername).ToArray() // brightstar level + .Where(u => BCrypt.Net.BCrypt.Verify(loginPassword, u.PasswordHash)).ToArray() // local level + ; - // local processing - .Where(u => u.ComparePassword(loginPassword)) - .ToArray(); - if (!users.Any()) - { - resp.Reason = - "Login details are incorrect. Please check your username and password and try again."; - return resp; - } - var user = users.Single(); + if (!matchingUsers.Any()) + return new SessionAuthenticationResult {Reason = "Invalid credentials"}; - // Check if user is banned - var bans = _db.Load(user.BanIDs); - if (bans.Any(b => b.IsValid)) + var user = matchingUsers.Single(); + + // Check for bans + var bans = user.Bans.Where(b => b.ExpiryTime > DateTime.Now).ToArray(); + if (bans.Any()) { - var ban = bans.First(b => b.IsValid); - resp.Reason = string.Format("You're currently banned: {0} (expires in {1})", ban.Reason, - ban.ExpiresIn.ToString("g")); // TODO: Format as d days h hours m minutes and s seconds - return resp; + var ban = bans.First(); + return new SessionAuthenticationResult + { + Reason = string.Format("You're banned: {0} (until {1})", ban.Reason, ban.ExpiryTime) + }; } - // Check if user was hacking - var cheatDetections = _db.Load(user.CheatDetectionIDs); - if (cheatDetections.Any(b => b.IsValid)) + // Check for cheat detections + var cheatDetections = + user.CheatDetections.Where(c => c.ExpiryTime > DateTime.Now).ToArray(); + if (cheatDetections.Any()) { - var ban = cheatDetections.First(b => b.IsValid); - resp.Reason = string.Format("You have been seen using a cheat: {0} (expires in {1})", ban.Reason, - ban.ExpiresIn.ToString("g")); // TODO: Format as d days h hours m minutes and s seconds - return resp; + var cheatDetection = cheatDetections.First(); + return new SessionAuthenticationResult + { + Reason = + string.Format("Detected cheat #{0}: {1} (until {2})", cheatDetection.CheatId, + cheatDetection.Reason, cheatDetection.ExpiryTime) + }; } - // Create a session for this user - var session = new Session() - { - ExpiryTime = DateTime.Now + TimeSpan.FromMinutes(5), - User = user - }; - _db.Store(session); + // Create user session + var session = db.Sessions.Create(); + session.ExpiryTime = DateTime.Now + TimeSpan.FromMinutes(3); + user.Sessions.Add(session); - // Update user's last login time + // Update user's last login data user.LastLogin = DateTime.Now; - _db.Store(user); - resp.UserID = user.Id; - resp.UserMail = user.UserMail; - resp.UserName = user.UserName; - resp.SessionToken = session.Id; - resp.Success = true; + // Save to database + db.SaveChanges(); - // Save everything to the database now - _db.SaveChanges(); - - return resp; - //} - }; + // Return session information + return new SessionAuthenticationResult + { + Success = true, + SessionToken = session.Id, + UserID = uint.Parse(user.Id, NumberStyles.Integer), + UserMail = user.UserMail, + UserName = user.UserName + }; + } + } + ; _authServer.Start(); } @@ -203,14 +185,15 @@ namespace NPSharp.CommandLine.Server _log.Debug("Starting NP server..."); _np = new NPServer(3036) { - AuthenticationHandler = new RavenDatabaseAuthenticationHandler(_database), - FileServingHandler = new RavenDatabaseFileServingHandler(_database) - // TODO: Implement the other handlers + AuthenticationHandler = new BrightstarDatabaseAuthenticationHandler(OpenDatabase()), + FileServingHandler = new BrightstarDatabaseFileServingHandler(OpenDatabase()), + FriendsHandler = null, + UserAvatarHandler = null }; _np.Start(); } - static void InitializeLogging() + private static void InitializeLogging() { if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX) { @@ -223,7 +206,14 @@ namespace NPSharp.CommandLine.Server #endif Layout = new PatternLayout("<%d{HH:mm:ss}> [%logger:%thread] %level: %message%newline"), }; - BasicConfigurator.Configure(new IAppender[] { appender, new DebugAppender { Layout = appender.Layout, Threshold = Level.All } }); + + BasicConfigurator.Configure( + new IAppender[] + { + appender, + new DebugAppender {Layout = appender.Layout, Threshold = Level.All} + } + ); } else { @@ -232,41 +222,64 @@ namespace NPSharp.CommandLine.Server #if DEBUG Threshold = Level.Debug, #else - Threshold = Level.Info, + Threshold = Level.Info, #endif Layout = new PatternLayout("<%d{HH:mm:ss}> [%logger:%thread] %level: %message%newline"), }; - appender.AddMapping(new ColoredConsoleAppender.LevelColors - { - Level = Level.Debug, - ForeColor = ColoredConsoleAppender.Colors.Cyan | ColoredConsoleAppender.Colors.HighIntensity - }); - appender.AddMapping(new ColoredConsoleAppender.LevelColors - { - Level = Level.Info, - ForeColor = ColoredConsoleAppender.Colors.Green | ColoredConsoleAppender.Colors.HighIntensity - }); - appender.AddMapping(new ColoredConsoleAppender.LevelColors - { - Level = Level.Warn, - ForeColor = ColoredConsoleAppender.Colors.Purple | ColoredConsoleAppender.Colors.HighIntensity - }); - appender.AddMapping(new ColoredConsoleAppender.LevelColors - { - Level = Level.Error, - ForeColor = ColoredConsoleAppender.Colors.Red | ColoredConsoleAppender.Colors.HighIntensity - }); - appender.AddMapping(new ColoredConsoleAppender.LevelColors - { - Level = Level.Fatal, - ForeColor = ColoredConsoleAppender.Colors.White | ColoredConsoleAppender.Colors.HighIntensity, - BackColor = ColoredConsoleAppender.Colors.Red - }); + + appender.AddMapping( + new ColoredConsoleAppender.LevelColors + { + Level = Level.Debug, + ForeColor = ColoredConsoleAppender.Colors.Cyan | ColoredConsoleAppender.Colors.HighIntensity + } + ); + appender.AddMapping( + new ColoredConsoleAppender.LevelColors + { + Level = Level.Info, + ForeColor = + ColoredConsoleAppender.Colors.Green | ColoredConsoleAppender.Colors.HighIntensity + } + ); + + appender.AddMapping( + new ColoredConsoleAppender.LevelColors + { + Level = Level.Warn, + ForeColor = + ColoredConsoleAppender.Colors.Purple | ColoredConsoleAppender.Colors.HighIntensity + } + ); + + appender.AddMapping( + new ColoredConsoleAppender.LevelColors + { + Level = Level.Error, + ForeColor = ColoredConsoleAppender.Colors.Red | ColoredConsoleAppender.Colors.HighIntensity + } + ); + appender.AddMapping( + new ColoredConsoleAppender.LevelColors + { + Level = Level.Fatal, + ForeColor = + ColoredConsoleAppender.Colors.White | ColoredConsoleAppender.Colors.HighIntensity, + BackColor = ColoredConsoleAppender.Colors.Red + } + ); + appender.ActivateOptions(); - BasicConfigurator.Configure(new IAppender[] { appender, new DebugAppender { Layout = appender.Layout, Threshold = Level.All } }); + BasicConfigurator.Configure( + new IAppender[] + { + appender, + new DebugAppender {Layout = appender.Layout, Threshold = Level.All} + } + ); } _log = LogManager.GetLogger("Main"); } } -} +} \ No newline at end of file diff --git a/src/npserv/Properties/AssemblyInfo.cs b/src/npserv/Properties/AssemblyInfo.cs index cb7195c..00beb8b 100644 --- a/src/npserv/Properties/AssemblyInfo.cs +++ b/src/npserv/Properties/AssemblyInfo.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; // Allgemeine Informationen über eine Assembly werden über die folgenden // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, // die mit einer Assembly verknüpft sind. + [assembly: AssemblyTitle("npserv")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -16,9 +17,11 @@ using System.Runtime.InteropServices; // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. + [assembly: ComVisible(false)] // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird + [assembly: Guid("098bf075-4a4b-437c-9283-011ffb6ff277")] // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: @@ -31,5 +34,6 @@ using System.Runtime.InteropServices; // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] + [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/src/npserv/RavenDatabaseAuthenticationHandler.cs b/src/npserv/RavenDatabaseAuthenticationHandler.cs deleted file mode 100644 index 0c6a59c..0000000 --- a/src/npserv/RavenDatabaseAuthenticationHandler.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using NPSharp.CommandLine.Server.Database; -using NPSharp.Steam; -using Raven.Client; - -namespace NPSharp.CommandLine.Server -{ - class RavenDatabaseAuthenticationHandler : IAuthenticationHandler - { - //private readonly IDocumentStore _database; - private readonly IDocumentSession _db; - - public RavenDatabaseAuthenticationHandler(IDocumentStore database) - { - //_database = database; - _db = database.OpenSession(); - } - - ~RavenDatabaseAuthenticationHandler() - { - _db.Dispose(); - } - - public AuthenticationResult AuthenticateUser(NPServerClient client, string username, string password) - { - // Nah, authenticating this way is deprecated as fuck. - return new AuthenticationResult(); - } - - public AuthenticationResult AuthenticateUser(NPServerClient client, string token) - { - //using (var db = _database.OpenSession()) - //{ - var session = _db.Load(token); - if (session == null) - { - // Invalid session token - return new AuthenticationResult(); - } - - // Remove session now since we don't need it anymore - _db.Delete(session); - _db.SaveChanges(); - - return new AuthenticationResult(new CSteamID() - { - AccountID = session.User.Id, - AccountInstance = 1, - AccountType = EAccountType.Individual, - AccountUniverse = EUniverse.Public - }); - //} - } - - public AuthenticationResult AuthenticateServer(NPServerClient client, string licenseKey) - { - throw new NotImplementedException(); - } - - public TicketValidationResult ValidateTicket(NPServerClient client, NPServerClient server) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/npserv/RavenDatabaseFileServingHandler.cs b/src/npserv/RavenDatabaseFileServingHandler.cs deleted file mode 100644 index e66d428..0000000 --- a/src/npserv/RavenDatabaseFileServingHandler.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Linq; -using System.Text; -using NPSharp.CommandLine.Server.Database; -using Raven.Client; - -namespace NPSharp.CommandLine.Server -{ - class RavenDatabaseFileServingHandler : IFileServingHandler - { - private readonly IDocumentStore _database; - - public RavenDatabaseFileServingHandler(IDocumentStore database) - { - _database = database; - } - - protected byte[] GetDefaultUserFile(string file) - { - switch (file) - { - case "iw4.stat": - return new byte[8 * 1024]; - default: - return null; - } - } - - protected byte[] GetDefaultPublisherFile(string file) - { - switch (file) - { - case "hello_world.txt": - case "motd-english.txt": - case "motd-german.txt": - case "motd-french.txt": - case "motd-russian.txt": - case "motd-spanish.txt": - return Encoding.UTF8.GetBytes("hello"); - case "playerlog.csv": - case "social_tu1.cfg": - case "heatmap.raw": - case "online_mp.img": - return new byte[0]; - default: - return null; - } - } - - public byte[] ReadUserFile(NPServerClient client, string file) - { - using (var db = _database.OpenSession()) - { - var userfile = db - .Query() - .Customize(uf => uf.Include(o => o.UserID)) - .SingleOrDefault(uf => - uf.FileName == file - && db.Load(uf.UserID).Id == client.UserID.AccountID); - - return userfile == null ? null : userfile.FileData; - } - } - - public byte[] ReadPublisherFile(NPServerClient client, string file) - { - using (var db = _database.OpenSession()) - { - var pubfiles = - db.Query() - .Where(uf => uf.FileName == file) - .ToArray(); - - return !pubfiles.Any() ? GetDefaultPublisherFile(file) : pubfiles.Single().FileData; - } - } - - public void WriteUserFile(NPServerClient client, string file, byte[] data) - { - using (var db = _database.OpenSession()) - { - var userfile = db - .Query() - .Customize(uf => uf.Include(o => o.UserID)) - .SingleOrDefault(uf => - uf.FileName == file - && db.Load(uf.UserID).Id == client.UserID.AccountID) - ?? new UserFile(); - - userfile.UserID = client.UserID.AccountID; - userfile.FileData = data; - userfile.FileName = file; - - db.Store(userfile); - db.SaveChanges(); - } - } - } -} diff --git a/src/npserv/UInt32Converter.cs b/src/npserv/UInt32Converter.cs deleted file mode 100644 index 58da796..0000000 --- a/src/npserv/UInt32Converter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using Raven.Client.Converters; - -namespace NPSharp.CommandLine.Server -{ - public class UInt32Converter : ITypeConverter - { - public bool CanConvertFrom(Type sourceType) - { - return sourceType == typeof(uint); - } - public string ConvertFrom(string tag, object value, bool allowNull) - { - var val = (uint)value; - if (val == 0 && allowNull) - return null; - return tag + value; - } - public object ConvertTo(string value) - { - return uint.Parse(value); - } - } -} diff --git a/src/npserv/npserv.csproj b/src/npserv/npserv.csproj index 91bc783..417427c 100644 --- a/src/npserv/npserv.csproj +++ b/src/npserv/npserv.csproj @@ -22,6 +22,7 @@ prompt 4 false + false pdbonly @@ -30,6 +31,7 @@ prompt 4 false + false $(SolutionDir)\bin\$(Configuration)\$(Platform)\ @@ -42,61 +44,59 @@ ..\..\packages\BCrypt-Official.0.1.109\lib\BCrypt.Net.dll + + ..\..\packages\BrightstarDBLibs.1.6.2.0\lib\net45\BrightstarDB.dll + + + ..\..\packages\dotNetRDF.1.0.4.3225\lib\net40\dotNetRDF.dll + + + ..\..\packages\HtmlAgilityPack.1.4.6\lib\Net45\HtmlAgilityPack.dll + ..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll - - ..\..\packages\Microsoft.Data.Edm.5.2.0\lib\net40\Microsoft.Data.Edm.dll - - - ..\..\packages\Microsoft.Data.OData.5.2.0\lib\net40\Microsoft.Data.OData.dll - - - ..\..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.8.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll - - - ..\..\packages\WindowsAzure.Storage.2.0.6.1\lib\net40\Microsoft.WindowsAzure.Storage.dll - ..\..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll - - ..\..\packages\RavenDB.Client.2.5.2878\lib\net45\Raven.Abstractions.dll - - - ..\..\packages\RavenDB.Embedded.2.5.2878\lib\net45\Raven.Client.Embedded.dll - - - ..\..\packages\RavenDB.Client.2.5.2878\lib\net45\Raven.Client.Lightweight.dll - - - ..\..\packages\RavenDB.Database.2.5.2878\lib\net45\Raven.Database.dll + + ..\..\packages\BrightstarDBLibs.1.6.2.0\lib\net45\Remotion.Linq.dll - - - - ..\..\packages\System.Spatial.5.2.0\lib\net40\System.Spatial.dll - - - False ..\..\packages\uHttpSharp.0.1.4.7\lib\net40\uhttpsharp.dll + + ..\..\packages\VDS.Common.1.2.0\lib\net40-client\VDS.Common.dll + - - - + + + + + + + + + + + True + True + BrightstarDatabaseContext.tt + - + + TextTemplatingFileGenerator + BrightstarDatabaseContext.cs + @@ -108,6 +108,9 @@ + + +