From e22086cc88b74c0419570c2139b376e205f6a62b Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Thu, 2 Aug 2018 16:14:46 -0500 Subject: [PATCH 1/2] Add data initializer. --- .../Abstractions/IHookDbInitializer.cs | 19 ++++++ .../Abstractions/IInitializationLoader.cs | 14 +++++ .../Accounts/AccountDbInitializer.cs | 24 +++++++ BotSharp.Core/Accounts/User.cs | 60 ++++++++++++++++++ BotSharp.Core/Accounts/UserAuth.cs | 36 +++++++++++ BotSharp.Core/BotSharp.Core.csproj | 2 +- BotSharp.Core/Engines/BotEngineBase.cs | 5 +- BotSharp.Core/Engines/BotTrainer.cs | 13 ++-- BotSharp.Core/Engines/DbInitializer.cs | 33 ++++++++++ .../Dialogflow/AgentImporterInDialogflow.cs | 6 +- BotSharp.Core/Engines/Rasa/RasaAi.cs | 9 ++- BotSharp.RestApi/AgentController.cs | 2 +- .../AuthenticationController.cs | 62 +++++++++++++++++++ .../Authentication/VmUserLogin.cs | 22 +++++++ BotSharp.UI/README.md | 2 +- BotSharp.UI/src/config/config.js | 3 +- BotSharp.UI/src/main.js | 2 +- BotSharp.UI/src/views/account/login.vue | 2 +- BotSharp.UI/src/views/account/settings.vue | 4 +- BotSharp.UnitTest/AgentTest.cs | 3 +- BotSharp.UnitTest/TestEssential.cs | 7 ++- BotSharp.WebHost/BotSharp.WebHost.csproj | 1 + BotSharp.WebHost/InitializationLoader.cs | 26 ++++++++ BotSharp.WebHost/Startup.cs | 18 ++++-- BotSharp.sln | 8 ++- 25 files changed, 351 insertions(+), 32 deletions(-) create mode 100644 BotSharp.Core/Abstractions/IHookDbInitializer.cs create mode 100644 BotSharp.Core/Abstractions/IInitializationLoader.cs create mode 100644 BotSharp.Core/Accounts/AccountDbInitializer.cs create mode 100644 BotSharp.Core/Accounts/User.cs create mode 100644 BotSharp.Core/Accounts/UserAuth.cs create mode 100644 BotSharp.Core/Engines/DbInitializer.cs create mode 100644 BotSharp.RestApi/Authentication/AuthenticationController.cs create mode 100644 BotSharp.RestApi/Authentication/VmUserLogin.cs create mode 100644 BotSharp.WebHost/InitializationLoader.cs diff --git a/BotSharp.Core/Abstractions/IHookDbInitializer.cs b/BotSharp.Core/Abstractions/IHookDbInitializer.cs new file mode 100644 index 00000000..f0e86df6 --- /dev/null +++ b/BotSharp.Core/Abstractions/IHookDbInitializer.cs @@ -0,0 +1,19 @@ +using EntityFrameworkCore.BootKit; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Abstractions +{ + /// + /// Initialize data for modules + /// + public interface IHookDbInitializer + { + /// + /// value smaller is higher priority + /// + int Priority { get; } + void Load(Database dc); + } +} diff --git a/BotSharp.Core/Abstractions/IInitializationLoader.cs b/BotSharp.Core/Abstractions/IInitializationLoader.cs new file mode 100644 index 00000000..befa988a --- /dev/null +++ b/BotSharp.Core/Abstractions/IInitializationLoader.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.Core.Abstractions +{ + public interface IInitializationLoader + { + int Priority { get; } + void Initialize(IConfiguration config, IHostingEnvironment env); + } +} diff --git a/BotSharp.Core/Accounts/AccountDbInitializer.cs b/BotSharp.Core/Accounts/AccountDbInitializer.cs new file mode 100644 index 00000000..abd95840 --- /dev/null +++ b/BotSharp.Core/Accounts/AccountDbInitializer.cs @@ -0,0 +1,24 @@ +using BotSharp.Core.Abstractions; +using EntityFrameworkCore.BootKit; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace BotSharp.Core.Accounts +{ + public class AccountDbInitializer : IHookDbInitializer + { + public int Priority => 100; + + public void Load(Database dc) + { + ImportAccount(dc); + } + + private void ImportAccount(Database dc) + { + var dataPath = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Accounts"); + } + } +} diff --git a/BotSharp.Core/Accounts/User.cs b/BotSharp.Core/Accounts/User.cs new file mode 100644 index 00000000..c33816ed --- /dev/null +++ b/BotSharp.Core/Accounts/User.cs @@ -0,0 +1,60 @@ +using EntityFrameworkCore.BootKit; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace BotSharp.Core.Accounts +{ + /// + /// User profile + /// + [Table("User")] + public class User : DbRecord, IDbRecord + { + [Required] + [StringLength(64)] + public String UserName { get; set; } + + [Required] + [StringLength(64)] + [DataType(DataType.EmailAddress)] + public String Email { get; set; } + + [StringLength(32)] + public String FirstName { get; set; } + + [StringLength(32)] + public String LastName { get; set; } + + [MaxLength(256)] + public String Description { get; set; } + + [Required] + [DataType(DataType.DateTime)] + public DateTime SignupDate { get; set; } + + [DataType(DataType.Date)] + public DateTime? Birthday { get; set; } + + [MaxLength(36)] + public String Nationality { get; set; } + + [NotMapped] + public String FullName + { + get + { + return FirstName + (String.IsNullOrEmpty(LastName) ? "" : " " + LastName); + } + } + + public UserAuth Authenticaiton { get; set; } + + public User() + { + SignupDate = DateTime.UtcNow; + } + } +} diff --git a/BotSharp.Core/Accounts/UserAuth.cs b/BotSharp.Core/Accounts/UserAuth.cs new file mode 100644 index 00000000..1079ed4e --- /dev/null +++ b/BotSharp.Core/Accounts/UserAuth.cs @@ -0,0 +1,36 @@ +using EntityFrameworkCore.BootKit; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace BotSharp.Core.Accounts +{ + /// + /// User authentication + /// + [Table("UserAuth")] + public class UserAuth : DbRecord, IDbRecord + { + [StringLength(36)] + public String UserId { get; set; } + + [Required] + [StringLength(256)] + [DataType(DataType.Password)] + public String Password { get; set; } + + [Required] + [StringLength(64)] + public String Salt { get; set; } + + [StringLength(32)] + public String ActivationCode { get; set; } + + public Boolean IsActivated { get; set; } + + [ForeignKey("UserId")] + public User User { get; set; } + } +} diff --git a/BotSharp.Core/BotSharp.Core.csproj b/BotSharp.Core/BotSharp.Core.csproj index 871040fe..32d95246 100644 --- a/BotSharp.Core/BotSharp.Core.csproj +++ b/BotSharp.Core/BotSharp.Core.csproj @@ -36,12 +36,12 @@ - + diff --git a/BotSharp.Core/Engines/BotEngineBase.cs b/BotSharp.Core/Engines/BotEngineBase.cs index 345da2c1..0e05b241 100644 --- a/BotSharp.Core/Engines/BotEngineBase.cs +++ b/BotSharp.Core/Engines/BotEngineBase.cs @@ -28,7 +28,8 @@ namespace BotSharp.Core.Engines public BotEngineBase() { dc = new DefaultDataContextLoader().GetDefaultDc(); - DbInitializerPath = $"{Database.ContentRootPath}App_Data{Path.DirectorySeparatorChar}DbInitializer{Path.DirectorySeparatorChar}"; + string dataPath = AppDomain.CurrentDomain.GetData("DataPath").ToString(); + DbInitializerPath = Path.Join(dataPath, $"DbInitializer"); } public Agent LoadAgent(string id) @@ -62,7 +63,7 @@ namespace BotSharp.Core.Engines { var importer = new TAgentImporter(); - string dataDir = $"{DbInitializerPath}Agents{Path.DirectorySeparatorChar}"; + string dataDir = Path.Join(DbInitializerPath, "Agents"); int row = dc.DbTran(() => { diff --git a/BotSharp.Core/Engines/BotTrainer.cs b/BotSharp.Core/Engines/BotTrainer.cs index b6c6c994..c5b6984f 100644 --- a/BotSharp.Core/Engines/BotTrainer.cs +++ b/BotSharp.Core/Engines/BotTrainer.cs @@ -8,6 +8,7 @@ using BotSharp.Core.Intents; using DotNetToolkit; using EntityFrameworkCore.BootKit; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Newtonsoft.Json.Linq; namespace BotSharp.Core.Engines @@ -43,22 +44,24 @@ namespace BotSharp.Core.Engines }); // Get NLP Provider - string providerName = Database.Configuration.GetSection($"{config}:Provider").Value; - var provider = TypeHelper.GetInstance(providerName, Database.Assemblies) as INlpPipeline; - provider.Configuration = Database.Configuration.GetSection("BotSharpAi"); + var config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"); + var assemblies = (string[])AppDomain.CurrentDomain.GetData("Assemblies"); + string providerName = config.GetSection($"{config}:Provider").Value; + var provider = TypeHelper.GetInstance(providerName, assemblies) as INlpPipeline; + provider.Configuration = config.GetSection("BotSharpAi"); provider.Process(agent, data); //var corpus = agent.GrabCorpus(dc); // pipe process - var pipelines = Database.Configuration.GetSection($"{config}:Pipe").Value + var pipelines = config.GetSection($"{config}:Pipe").Value .Split(',') .Select(x => x.Trim()) .ToList(); pipelines.ForEach(pipeName => { - var pipe = TypeHelper.GetInstance(pipeName, Database.Assemblies) as INlpPipeline; + var pipe = TypeHelper.GetInstance(pipeName, assemblies) as INlpPipeline; pipe.Configuration = provider.Configuration; pipe.Process(agent, data); }); diff --git a/BotSharp.Core/Engines/DbInitializer.cs b/BotSharp.Core/Engines/DbInitializer.cs new file mode 100644 index 00000000..d9d5c066 --- /dev/null +++ b/BotSharp.Core/Engines/DbInitializer.cs @@ -0,0 +1,33 @@ +using BotSharp.Core.Abstractions; +using DotNetToolkit; +using EntityFrameworkCore.BootKit; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BotSharp.Core.Engines +{ + public class DbInitializer : IInitializationLoader + { + public int Priority => 1; + + public void Initialize(IConfiguration config, IHostingEnvironment env) + { + var dc = new DefaultDataContextLoader().GetDefaultDc(); + + var assemblies = (string[])AppDomain.CurrentDomain.GetData("Assemblies"); + var instances = TypeHelper.GetInstanceWithInterface(assemblies); + + // initial app db order by priority + instances.OrderBy(x => x.Priority).ToList() + .ForEach(instance => + { + Console.WriteLine($"DbInitializer: {instance.ToString()}"); + dc.Transaction(() => instance.Load(dc)); + }); + } + } +} diff --git a/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs b/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs index 3a6a1016..b76c9d2c 100644 --- a/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs +++ b/BotSharp.Core/Engines/Dialogflow/AgentImporterInDialogflow.cs @@ -28,7 +28,7 @@ namespace BotSharp.Core.Engines public Agent LoadAgent(AgentImportHeader agentHeader, string agentDir) { // load agent profile - string data = File.ReadAllText($"{agentDir}{Path.DirectorySeparatorChar}Dialogflow{Path.DirectorySeparatorChar}{agentHeader.Name}{Path.DirectorySeparatorChar}agent.json"); + string data = File.ReadAllText(Path.Join(agentDir, "Dialogflow", $"agentHeader.Name{Path.DirectorySeparatorChar}agent.json")); var agent = JsonConvert.DeserializeObject(data); agent.Name = agentHeader.Name; agent.Id = agentHeader.Id; @@ -56,7 +56,7 @@ namespace BotSharp.Core.Engines public void LoadCustomEntities(Agent agent, string agentDir) { agent.Entities = new List(); - string entityDir = $"{agentDir}{Path.DirectorySeparatorChar}Dialogflow{Path.DirectorySeparatorChar}{agent.Name}{Path.DirectorySeparatorChar}entities"; + string entityDir = Path.Join(agentDir, "Dialogflow", $"{agent.Name}{Path.DirectorySeparatorChar}entities"); if (!Directory.Exists(entityDir)) return; Directory.EnumerateFiles(entityDir) @@ -91,7 +91,7 @@ namespace BotSharp.Core.Engines public void LoadIntents(Agent agent, string agentDir) { agent.Intents = new List(); - string intentDir = $"{agentDir}{Path.DirectorySeparatorChar}Dialogflow{Path.DirectorySeparatorChar}{agent.Name}{Path.DirectorySeparatorChar}intents"; + string intentDir = Path.Join(agentDir, "Dialogflow", $"{agent.Name}{Path.DirectorySeparatorChar}intents"); if (!Directory.Exists(intentDir)) return; Directory.EnumerateFiles(intentDir) diff --git a/BotSharp.Core/Engines/Rasa/RasaAi.cs b/BotSharp.Core/Engines/Rasa/RasaAi.cs index 0106b03f..fceac1af 100644 --- a/BotSharp.Core/Engines/Rasa/RasaAi.cs +++ b/BotSharp.Core/Engines/Rasa/RasaAi.cs @@ -83,7 +83,8 @@ namespace BotSharp.Core.Engines private IRestResponse CallRasa(string projectId, string text, string model) { - var client = new RestClient($"{Database.Configuration.GetSection("Rasa:Nlu").Value}"); + var config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"); + var client = new RestClient($"{config.GetSection("Rasa:Nlu").Value}"); var rest = new RestRequest("parse", Method.POST); string json = JsonConvert.SerializeObject(new { Project = projectId, Q = text, Model = model }, @@ -105,7 +106,8 @@ namespace BotSharp.Core.Engines }; var corpus = GetIntentExpressions(); - var client = new RestClient($"{Database.Configuration.GetSection("Rasa:Nlu").Value}"); + var config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"); + var client = new RestClient($"{config.GetSection("Rasa:Nlu").Value}"); var contextHashs = corpus.UserSays .Select(x => x.ContextHash) @@ -195,7 +197,8 @@ namespace BotSharp.Core.Engines rest.AddQueryParameter("project", agent.Id); rest.AddQueryParameter("model", ctx); string trainingConfig = agent.Language == "zh" ? "config_jieba_mitie_sklearn.yml" : "config_mitie_sklearn.yml"; - string body = File.ReadAllText($"{Database.ContentRootPath}{Path.DirectorySeparatorChar}Settings{Path.DirectorySeparatorChar}{trainingConfig}"); + var contentRootPatch = AppDomain.CurrentDomain.GetData("ContentRootPath").ToString(); + string body = File.ReadAllText(Path.Join(contentRootPatch, "Settings", trainingConfig)); body = $"{body}\r\ndata: {json}"; rest.AddParameter("application/x-yml", body, ParameterType.RequestBody); diff --git a/BotSharp.RestApi/AgentController.cs b/BotSharp.RestApi/AgentController.cs index 49bc2de2..257d0afa 100644 --- a/BotSharp.RestApi/AgentController.cs +++ b/BotSharp.RestApi/AgentController.cs @@ -26,7 +26,7 @@ namespace BotSharp.RestApi [HttpGet("{agentId}")] public ActionResult Restore([FromRoute] String agentId) { - var botsHeaderFilePath = $"{Database.ContentRootPath}App_Data{Path.DirectorySeparatorChar}DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}agents.json"; + var botsHeaderFilePath = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), $"DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}agents.json"); var agents = JsonConvert.DeserializeObject>(System.IO.File.ReadAllText(botsHeaderFilePath)); var rasa = new RasaAi(); diff --git a/BotSharp.RestApi/Authentication/AuthenticationController.cs b/BotSharp.RestApi/Authentication/AuthenticationController.cs new file mode 100644 index 00000000..d50135a9 --- /dev/null +++ b/BotSharp.RestApi/Authentication/AuthenticationController.cs @@ -0,0 +1,62 @@ +using BotSharp.Core.Accounts; +using DotNetToolkit; +using DotNetToolkit.JwtHelper; +using EntityFrameworkCore.BootKit; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BotSharp.RestApi.Authentication +{ + /// + /// User authentication + /// + public class AuthenticationController : ControllerBase + { + /// + /// Get user token + /// + /// + /// + [AllowAnonymous] + [HttpPost("/token")] + public IActionResult Token([FromBody] VmUserLogin userModel) + { + if (String.IsNullOrEmpty(userModel.UserName) || String.IsNullOrEmpty(userModel.Password)) + { + return new BadRequestObjectResult("Username and password should not be empty."); + } + + var dc = new DefaultDataContextLoader().GetDefaultDc(); + + // validate from local + var user = (from usr in dc.Table() + join auth in dc.Table() on usr.Id equals auth.UserId + where usr.Email == userModel.UserName + select auth).FirstOrDefault(); + + if (user != null) + { + // validate password + string hash = PasswordHelper.Hash(userModel.Password, user.Salt); + if (user.Password == hash) + { + return Ok(JwtToken.GenerateToken((IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"), user.UserId)); + } + else + { + return BadRequest("Authorization Failed."); + } + } + else + { + return BadRequest("Account doesn't exist"); + } + } + } + +} diff --git a/BotSharp.RestApi/Authentication/VmUserLogin.cs b/BotSharp.RestApi/Authentication/VmUserLogin.cs new file mode 100644 index 00000000..b49960bb --- /dev/null +++ b/BotSharp.RestApi/Authentication/VmUserLogin.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BotSharp.RestApi.Authentication +{ + /// + /// User login view model + /// + public class VmUserLogin + { + /// + /// User identity, email or phone + /// + public String UserName { get; set; } + + /// + /// User password + /// + public String Password { get; set; } + } +} diff --git a/BotSharp.UI/README.md b/BotSharp.UI/README.md index e707404a..f6a500bc 100644 --- a/BotSharp.UI/README.md +++ b/BotSharp.UI/README.md @@ -4,7 +4,7 @@ Voiceweb AI Chatbot Web Console ## How to install #### Download source code ````sh -git clone https://github.com/voicecoin/voiceweb-chatbot-vue +git clone https://github.com/Oceania2018/BotSharp ```` #### Run node.js server ````sh diff --git a/BotSharp.UI/src/config/config.js b/BotSharp.UI/src/config/config.js index dc97e657..2504523b 100644 --- a/BotSharp.UI/src/config/config.js +++ b/BotSharp.UI/src/config/config.js @@ -2,8 +2,7 @@ import Env from './env'; let config = { env: Env, - authURL: 'http://0.0.0.0:3112', - baseURL: (Env == 'development' ? `http://0.0.0.0:3112` : `http://0.0.0.0:3112`), + baseURL: (Env == 'development' ? `http://localhost:3112` : `http://localhost:3112`), testAccount: {username: `botsharp@gmail.com`, password: (Env == 'development' ? `botsharp` : `botsharp`)} }; export default config; \ No newline at end of file diff --git a/BotSharp.UI/src/main.js b/BotSharp.UI/src/main.js index 7e6ed28f..41e08fef 100644 --- a/BotSharp.UI/src/main.js +++ b/BotSharp.UI/src/main.js @@ -88,7 +88,7 @@ const store = new Vuex.Store({ authenticated(state, token) { localStorage.setItem('token', token); router.push('/agent/agents'); - HTTP.get('/account', { baseURL: config.authURL }) + HTTP.get('/account', { baseURL: config.baseURL }) .then(response => { state.user = response.data; localStorage.setItem('user', JSON.stringify(response.data)); diff --git a/BotSharp.UI/src/views/account/login.vue b/BotSharp.UI/src/views/account/login.vue index 0256103a..00181b64 100644 --- a/BotSharp.UI/src/views/account/login.vue +++ b/BotSharp.UI/src/views/account/login.vue @@ -56,7 +56,7 @@ }) }, getToken() { - this.$ajax.post(`/token`, this.formInline, { baseURL: this.$config.authURL }) + this.$ajax.post(`/token`, this.formInline, { baseURL: this.$config.baseURL }) .then(response => { this.$store.commit('authenticated', response.data) }); diff --git a/BotSharp.UI/src/views/account/settings.vue b/BotSharp.UI/src/views/account/settings.vue index 5af7d924..3cc737ef 100644 --- a/BotSharp.UI/src/views/account/settings.vue +++ b/BotSharp.UI/src/views/account/settings.vue @@ -52,7 +52,7 @@ }, created() { let agentId = this.$route.query.agentId; - this.$ajax.get(`/Account`, { baseURL: this.$config.authURL }) + this.$ajax.get(`/Account`, { baseURL: this.$config.baseURL }) .then(response => { this.user = response.data; }); @@ -61,7 +61,7 @@ updateAgent(agentId){ this.$ajax.put('/v1/Agents/' + agentId, this.agent) .then(response => { - this.$Message.info("保存成功"); + this.$Message.info("Saved"); }); } } diff --git a/BotSharp.UnitTest/AgentTest.cs b/BotSharp.UnitTest/AgentTest.cs index 9b5c2499..1c043195 100644 --- a/BotSharp.UnitTest/AgentTest.cs +++ b/BotSharp.UnitTest/AgentTest.cs @@ -45,7 +45,8 @@ namespace BotSharp.UnitTest [TestMethod] public void RestoreAgentFromDialogflowToRasaTest() { - var botsHeaderFilePath = $"{Database.ContentRootPath}App_Data{Path.DirectorySeparatorChar}DbInitializer{Path.DirectorySeparatorChar}Agents{Path.DirectorySeparatorChar}agents.json"; + string dataPath = AppDomain.CurrentDomain.GetData("DataPath").ToString(); + var botsHeaderFilePath = Path.Join(dataPath, "DbInitializer", $"Agents{Path.DirectorySeparatorChar}agents.json"); var agents = JsonConvert.DeserializeObject>(File.ReadAllText(botsHeaderFilePath)); agents.ForEach(agentHeader => { diff --git a/BotSharp.UnitTest/TestEssential.cs b/BotSharp.UnitTest/TestEssential.cs index d4180f6c..6be81cfc 100644 --- a/BotSharp.UnitTest/TestEssential.cs +++ b/BotSharp.UnitTest/TestEssential.cs @@ -25,10 +25,11 @@ namespace BotSharp.UnitTest { configurationBuilder.AddJsonFile(setting, optional: false, reloadOnChange: true); }); - Database.Configuration = configurationBuilder.Build(); - Database.Assemblies = new String[] { "BotSharp.Core" }; - Database.ContentRootPath = contentRoot; + AppDomain.CurrentDomain.SetData("DataPath", Path.Join(contentRoot, "App_Data")); + AppDomain.CurrentDomain.SetData("Configuration", configurationBuilder.Build()); + AppDomain.CurrentDomain.SetData("ContentRootPath", contentRoot); + AppDomain.CurrentDomain.SetData("Assemblies", new String[] { "BotSharp.Core" }); dc = new DefaultDataContextLoader().GetDefaultDc(); } diff --git a/BotSharp.WebHost/BotSharp.WebHost.csproj b/BotSharp.WebHost/BotSharp.WebHost.csproj index 458f02fd..d029ebba 100644 --- a/BotSharp.WebHost/BotSharp.WebHost.csproj +++ b/BotSharp.WebHost/BotSharp.WebHost.csproj @@ -57,6 +57,7 @@ + diff --git a/BotSharp.WebHost/InitializationLoader.cs b/BotSharp.WebHost/InitializationLoader.cs new file mode 100644 index 00000000..f6e475d1 --- /dev/null +++ b/BotSharp.WebHost/InitializationLoader.cs @@ -0,0 +1,26 @@ +using BotSharp.Core.Abstractions; +using DotNetToolkit; +using EntityFrameworkCore.BootKit; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace BotSharp.WebHost +{ + public class InitializationLoader + { + public IHostingEnvironment Env { get; set; } + public IConfiguration Config { get; set; } + public void Load() + { + var assemblies = (string[])AppDomain.CurrentDomain.GetData("Assemblies"); + var appsLoaders1 = TypeHelper.GetInstanceWithInterface(assemblies); + appsLoaders1.ForEach(loader => { + loader.Initialize(Config, Env); + }); + } + } +} diff --git a/BotSharp.WebHost/Startup.cs b/BotSharp.WebHost/Startup.cs index 4a160690..ec930233 100644 --- a/BotSharp.WebHost/Startup.cs +++ b/BotSharp.WebHost/Startup.cs @@ -50,8 +50,10 @@ namespace BotSharp.WebHost // register platform dependency services.AddTransient((provider) => { - var implements = TypeHelper.GetClassesWithInterface(Database.Assemblies); - string platform = Database.Configuration.GetValue("BotPlatform"); + var assemblies = (String[])AppDomain.CurrentDomain.GetData("Assemblies"); + var config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"); + var implements = TypeHelper.GetClassesWithInterface(assemblies); + string platform = config.GetValue("BotPlatform"); var implement = implements.FirstOrDefault(x => x.Name.Split('.').Last() == platform); var instance = (IBotPlatform)Activator.CreateInstance(implement); @@ -100,9 +102,15 @@ namespace BotSharp.WebHost app.UseMvc(); - Database.Configuration = Configuration; - Database.ContentRootPath = env.ContentRootPath; - Database.Assemblies = Configuration.GetValue("Assemblies").Split(','); + AppDomain.CurrentDomain.SetData("DataPath", Path.Join(env.ContentRootPath, "App_Data")); + AppDomain.CurrentDomain.SetData("Configuration", Configuration); + AppDomain.CurrentDomain.SetData("ContentRootPath", env.ContentRootPath); + AppDomain.CurrentDomain.SetData("Assemblies", Configuration.GetValue("Assemblies").Split(',')); + + InitializationLoader loader = new InitializationLoader(); + loader.Env = env; + loader.Config = Configuration; + loader.Load(); } } } diff --git a/BotSharp.sln b/BotSharp.sln index c4a7b664..d16f478e 100644 --- a/BotSharp.sln +++ b/BotSharp.sln @@ -11,7 +11,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.RestApi", "BotShar EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.WebHost", "BotSharp.WebHost\BotSharp.WebHost.csproj", "{03DCA427-327A-4FC9-9A2F-57D17F16708C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.MachineLearning", "BotSharp.MachineLearning\BotSharp.MachineLearning.csproj", "{E664115A-AE86-49E9-8AE4-D4589A568CD7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.MachineLearning", "BotSharp.MachineLearning\BotSharp.MachineLearning.csproj", "{E664115A-AE86-49E9-8AE4-D4589A568CD7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.BootKit", "..\EntityFrameworkCore.BootKit\EntityFrameworkCore.BootKit\EntityFrameworkCore.BootKit.csproj", "{A5F6D16F-E6F4-449E-AA52-7830B4897F88}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -39,6 +41,10 @@ Global {E664115A-AE86-49E9-8AE4-D4589A568CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {E664115A-AE86-49E9-8AE4-D4589A568CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU {E664115A-AE86-49E9-8AE4-D4589A568CD7}.Release|Any CPU.Build.0 = Release|Any CPU + {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From fe47fa2d5cccd448ee7692b9ecae1f031e489b71 Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Thu, 2 Aug 2018 22:54:23 -0500 Subject: [PATCH 2/2] Added account initialization. --- BotSharp.Core/Accounts/AccountCore.cs | 64 +++++++++++++++++++ .../Accounts/AccountDbInitializer.cs | 17 ++++- BotSharp.Core/BotSharp.Core.csproj | 7 +- .../AuthenticationController.cs | 3 +- BotSharp.RestApi/BotSharp.RestApi.csproj | 13 ++++ BotSharp.UI/src/config/config.js | 2 +- .../DbInitializer/Accounts/users.json | 12 ++++ BotSharp.WebHost/BotSharp.WebHost.csproj | 1 - BotSharp.WebHost/Settings/auth.json | 9 +++ BotSharp.WebHost/Startup.cs | 16 +++-- BotSharp.sln | 6 -- 11 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 BotSharp.Core/Accounts/AccountCore.cs create mode 100644 BotSharp.WebHost/App_Data/DbInitializer/Accounts/users.json create mode 100644 BotSharp.WebHost/Settings/auth.json diff --git a/BotSharp.Core/Accounts/AccountCore.cs b/BotSharp.Core/Accounts/AccountCore.cs new file mode 100644 index 00000000..8c048c6b --- /dev/null +++ b/BotSharp.Core/Accounts/AccountCore.cs @@ -0,0 +1,64 @@ +using DotNetToolkit; +using EntityFrameworkCore.BootKit; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BotSharp.Core.Accounts +{ + public class AccountCore + { + private Database _dc; + private IConfiguration _config; + + public AccountCore(Database dc = null) + { + if (dc == null) + { + dc = new DefaultDataContextLoader().GetDefaultDc(); + } + else + { + _dc = dc; + } + + _config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"); + } + + public void CreateUser(User user) + { + user.Authenticaiton.IsActivated = false; + user.Authenticaiton.Salt = PasswordHelper.GetSalt(); + user.Authenticaiton.Password = PasswordHelper.Hash(user.Authenticaiton.Password, user.Authenticaiton.Salt); + user.Authenticaiton.ActivationCode = Guid.NewGuid().ToString("N"); + + _dc.Transaction(() => + { + _dc.Table().Add(user); + }); + + + $"Created user {user.Email}, user id: {user.Id}".Log(LogLevel.INFO); + } + + public void Activate(string activationCode) + { + var activation = _dc.Table().FirstOrDefault(x => x.ActivationCode == activationCode && !x.IsActivated); + if (activation == null) + { + } + else + { + _dc.Transaction(() => + { + activation = _dc.Table().FirstOrDefault(x => x.ActivationCode == activationCode); + activation.ActivationCode = String.Empty; + activation.IsActivated = true; + activation.UpdatedTime = DateTime.UtcNow; + }); + } + } + } +} diff --git a/BotSharp.Core/Accounts/AccountDbInitializer.cs b/BotSharp.Core/Accounts/AccountDbInitializer.cs index abd95840..0e55e6e0 100644 --- a/BotSharp.Core/Accounts/AccountDbInitializer.cs +++ b/BotSharp.Core/Accounts/AccountDbInitializer.cs @@ -1,8 +1,10 @@ using BotSharp.Core.Abstractions; using EntityFrameworkCore.BootKit; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; namespace BotSharp.Core.Accounts @@ -18,7 +20,20 @@ namespace BotSharp.Core.Accounts private void ImportAccount(Database dc) { - var dataPath = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "Accounts"); + var dataPath = Path.Join(AppDomain.CurrentDomain.GetData("DataPath").ToString(), "DbInitializer", "Accounts"); + string json = File.ReadAllText(Path.Join(dataPath, "users.json")); + + var users = JsonConvert.DeserializeObject>(json); + users.ForEach(user => + { + if (!dc.Table().Any(x => x.UserName == user.UserName)) + { + var core = new AccountCore(dc); + core.CreateUser(user); + core.Activate(user.Authenticaiton.ActivationCode); + } + }); + } } } diff --git a/BotSharp.Core/BotSharp.Core.csproj b/BotSharp.Core/BotSharp.Core.csproj index 32d95246..6378b2af 100644 --- a/BotSharp.Core/BotSharp.Core.csproj +++ b/BotSharp.Core/BotSharp.Core.csproj @@ -12,11 +12,11 @@ true Haiping Chen - BotSharp Chabot Platform + BotSharp Chatbot Platform Open source chatbot platform which is written in C# runs on .Net Core and is enterprise oriented. Integrated with multiple bot engines besides BotSharp bot engine. Modulized pipeline design make NLP tasks plugin easily. Abstract platform and NLP task, migrate existed chatbot from a platform into another platform perfectly through dump and restore. MIT https://github.com/Oceania2018/BotSharp - NLU, Chatbot, Bot, AI Bot + NLU, Chatbot, Bot, AI Bot, Artificial Intelligence, RPA 1.4.0 Add NLP pipeline. Support training model by input context. Since 2018 Haiping Chen @@ -36,12 +36,13 @@ + + - diff --git a/BotSharp.RestApi/Authentication/AuthenticationController.cs b/BotSharp.RestApi/Authentication/AuthenticationController.cs index d50135a9..72df1704 100644 --- a/BotSharp.RestApi/Authentication/AuthenticationController.cs +++ b/BotSharp.RestApi/Authentication/AuthenticationController.cs @@ -45,7 +45,8 @@ namespace BotSharp.RestApi.Authentication string hash = PasswordHelper.Hash(userModel.Password, user.Salt); if (user.Password == hash) { - return Ok(JwtToken.GenerateToken((IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"), user.UserId)); + var config = (IConfiguration)AppDomain.CurrentDomain.GetData("Configuration"); + return Ok(JwtToken.GenerateToken(config, user.UserId)); } else { diff --git a/BotSharp.RestApi/BotSharp.RestApi.csproj b/BotSharp.RestApi/BotSharp.RestApi.csproj index ed3204a0..6c85eac9 100644 --- a/BotSharp.RestApi/BotSharp.RestApi.csproj +++ b/BotSharp.RestApi/BotSharp.RestApi.csproj @@ -2,6 +2,19 @@ netcoreapp2.1 + true + Haiping Chen + Personal + BotSharp + Restful API for BotSharp.Core + https://github.com/Oceania2018/BotSharp + https://github.com/Oceania2018/BotSharp/tree/master/BotSharp.RestApi + MIT + https://raw.githubusercontent.com/Oceania2018/BotSharp/master/BotSharp.WebHost/wwwroot/images/BotSharp.png + Since 2018 Haiping Chen + https://github.com/Oceania2018/BotSharp/blob/master/LICENSE + NLU, Chatbot, Bot, AI Bot + Restful API for BotSharp.Core diff --git a/BotSharp.UI/src/config/config.js b/BotSharp.UI/src/config/config.js index 2504523b..9453ea59 100644 --- a/BotSharp.UI/src/config/config.js +++ b/BotSharp.UI/src/config/config.js @@ -3,6 +3,6 @@ import Env from './env'; let config = { env: Env, baseURL: (Env == 'development' ? `http://localhost:3112` : `http://localhost:3112`), - testAccount: {username: `botsharp@gmail.com`, password: (Env == 'development' ? `botsharp` : `botsharp`)} + testAccount: {username: `support@botsharp.io`, password: (Env == 'development' ? `botsharp` : ``)} }; export default config; \ No newline at end of file diff --git a/BotSharp.WebHost/App_Data/DbInitializer/Accounts/users.json b/BotSharp.WebHost/App_Data/DbInitializer/Accounts/users.json new file mode 100644 index 00000000..d723a700 --- /dev/null +++ b/BotSharp.WebHost/App_Data/DbInitializer/Accounts/users.json @@ -0,0 +1,12 @@ +[ + { + "userName": "support@botsharp.io", + "email": "support@botsharp.io", + "firstName": "Support", + "lastName": "Botsharp", + "description": "demo account", + "authenticaiton": { + "password": "botsharp" + } + } +] diff --git a/BotSharp.WebHost/BotSharp.WebHost.csproj b/BotSharp.WebHost/BotSharp.WebHost.csproj index d029ebba..458f02fd 100644 --- a/BotSharp.WebHost/BotSharp.WebHost.csproj +++ b/BotSharp.WebHost/BotSharp.WebHost.csproj @@ -57,7 +57,6 @@ - diff --git a/BotSharp.WebHost/Settings/auth.json b/BotSharp.WebHost/Settings/auth.json new file mode 100644 index 00000000..a73f7f4a --- /dev/null +++ b/BotSharp.WebHost/Settings/auth.json @@ -0,0 +1,9 @@ +{ + "TokenAuthentication": { + "SecretKey": "lfo54FYneUCJNL2EjP9ZxQ==", + "Issuer": "BotSharp", + "Audience": "BotSharp", + "CookieName": "token", + "Subject": "BotSharp" + } +} diff --git a/BotSharp.WebHost/Startup.cs b/BotSharp.WebHost/Startup.cs index 0480512d..8c3f91d2 100644 --- a/BotSharp.WebHost/Startup.cs +++ b/BotSharp.WebHost/Startup.cs @@ -103,15 +103,21 @@ namespace BotSharp.WebHost app.UseMvc(); - Database.Configuration = Configuration; - Database.ContentRootPath = env.ContentRootPath; - Database.Assemblies = Configuration.GetValue("Assemblies").Split(','); + AppDomain.CurrentDomain.SetData("DataPath", Path.Join(env.ContentRootPath, "App_Data")); + AppDomain.CurrentDomain.SetData("Configuration", Configuration); + AppDomain.CurrentDomain.SetData("ContentRootPath", env.ContentRootPath); + AppDomain.CurrentDomain.SetData("Assemblies", Configuration.GetValue("Assemblies").Split(',')); - Runcmd(); + InitializationLoader loader = new InitializationLoader(); + loader.Env = env; + loader.Config = Configuration; + loader.Load(); + + /*Runcmd(); var ai = new BotSharpAi(); ai.LoadAgent("6a9fd374-c43d-447a-97f2-f37540d0c725"); - ai.Train(); + ai.Train();*/ } public void Runcmd () diff --git a/BotSharp.sln b/BotSharp.sln index d16f478e..c3bb81a6 100644 --- a/BotSharp.sln +++ b/BotSharp.sln @@ -13,8 +13,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.WebHost", "BotShar EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.MachineLearning", "BotSharp.MachineLearning\BotSharp.MachineLearning.csproj", "{E664115A-AE86-49E9-8AE4-D4589A568CD7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.BootKit", "..\EntityFrameworkCore.BootKit\EntityFrameworkCore.BootKit\EntityFrameworkCore.BootKit.csproj", "{A5F6D16F-E6F4-449E-AA52-7830B4897F88}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,10 +39,6 @@ Global {E664115A-AE86-49E9-8AE4-D4589A568CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {E664115A-AE86-49E9-8AE4-D4589A568CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU {E664115A-AE86-49E9-8AE4-D4589A568CD7}.Release|Any CPU.Build.0 = Release|Any CPU - {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A5F6D16F-E6F4-449E-AA52-7830B4897F88}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE