From 466340a97f8a158570f84fc12238101ca9c124ec Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Thu, 19 Nov 2020 01:46:41 +0200 Subject: Data store improvements. Added line number to logs viewer. Added DataStore Create Write Global permission. Added FSE application path to "Path" environment variable for dsUtil. Completed dsUtil. --- .../Advanced Installer Projects/FSE Installer.aip | 52 ++++++-- .../DataStore/Tango.DataStore.CLI/DataStoreUtil.cs | 131 +++++++++++++++++++++ .../Tango.DataStore.CLI/DataStoreUtilSettings.cs | 15 +++ .../DataStore/Tango.DataStore.CLI/Options.cs | 21 +++- .../DataStore/Tango.DataStore.CLI/Program.cs | 66 +---------- .../Tango.DataStore.CLI/Tango.DataStore.CLI.csproj | 6 + .../ViewModels/DataStoreViewVM.cs | 14 +-- .../ViewModels/MachineViewVM.cs | 2 +- .../Help/proc-doc.chm | Bin 245435 -> 245437 bytes .../Views/LogFileTabView.xaml | 5 +- .../FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs | 3 +- .../FSE/Tango.FSE.UI/Tango.FSE.UI.csproj | 4 + .../Tango.BL/Enumerations/Permissions.cs | 12 +- .../Controllers/DataStoreController.cs | 20 +++- 14 files changed, 255 insertions(+), 96 deletions(-) create mode 100644 Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtil.cs create mode 100644 Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtilSettings.cs (limited to 'Software/Visual_Studio') diff --git a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip index dc6557505..86a02fb0f 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip @@ -63,6 +63,8 @@ + + @@ -303,8 +305,10 @@ - - + + + + @@ -314,6 +318,7 @@ + @@ -361,6 +366,7 @@ + @@ -372,10 +378,10 @@ - - - - + + + + @@ -755,16 +761,27 @@ + + + + + + + + + + + + + + + + + - - - - - - @@ -927,6 +944,9 @@ + + + @@ -1246,13 +1266,19 @@ + - + + + + + + diff --git a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtil.cs b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtil.cs new file mode 100644 index 000000000..b18476e3f --- /dev/null +++ b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtil.cs @@ -0,0 +1,131 @@ +using ConsoleTables; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Cryptography; +using Tango.DataStore.Web; +using Tango.Settings; +using Tango.Web; + +namespace Tango.DataStore.CLI +{ + public class DataStoreConsole + { + public void Get(GetOptions options) + { + try + { + ApplyAutoLogin(options); + + if (options.MachineSerialNumber != null) + { + Console.WriteLine($"Retrieving data store values for '{options.MachineSerialNumber}'..."); + } + else + { + Console.WriteLine("Retrieving global data store values..."); + } + + var client = CreateClient(options.Email, options.Password, options.Environment); + + var items = client.Get(options.MachineSerialNumber, options.Collection, options.Key).ToList(); + + ConsoleTable table = new ConsoleTable("COLLECTION", "KEY", "DATA TYPE", "PROTO TYPE", "STATE", "GLOBAL", "LOCAL"); + + foreach (var item in items) + { + table.AddRow(item.Collection, item.Key, item.DataType, item.ProtoMessageType != MessageType.None ? item.ProtoMessageType.ToString() : null, item.Type, item.GlobalValue.ToStringSafe().ToOneLine(), item.LocalValue.ToStringSafe().ToOneLine()); + } + + Console.WriteLine(); + Console.WriteLine("DATA STORE RESULTS:"); + Console.WriteLine(); + + table.Write(); + } + catch (Exception ex) + { + Console.WriteLine(ex.FlattenMessage()); + } + } + + public void Put(PutOptions options) + { + try + { + ApplyAutoLogin(options); + + if (options.MachineSerialNumber != null) + { + Console.WriteLine($"Storing data store value for '{options.MachineSerialNumber}'..."); + } + else + { + Console.WriteLine("Storing global data store value..."); + } + + var client = CreateClient(options.Email, options.Password, options.Environment); + + if (options.DataType == Web.DataType.Proto) + { + options.Value = options.Value.ToStringOrEmpty().Replace("'", "\""); + } + + client.Put(new DataStoreWebPutItem() + { + Collection = options.Collection, + Key = options.Key, + DataType = options.DataType, + MachineSerialNumber = options.MachineSerialNumber, + ProtoMessageType = options.ProtoMessageType, + Value = options.Value + }); + + Console.WriteLine($"Item '{options.Key}' stored successfully."); + } + catch (Exception ex) + { + Console.WriteLine(ex.FlattenMessage()); + } + } + + public void AutoLogin(LoginConfig options) + { + MachineLevelCryptographer crypt = new MachineLevelCryptographer(); + var settings = SettingsManager.Default.GetOrCreate(); + settings.Email = options.Email; + settings.Password = crypt.Encrypt(options.Password); + settings.Save(); + } + + private void ApplyAutoLogin(OptionsBase options) + { + if (options.Email == null && options.Password == null) + { + MachineLevelCryptographer crypt = new MachineLevelCryptographer(); + var settings = SettingsManager.Default.GetOrCreate(); + options.Email = settings.Email; + options.Password = crypt.Decrypt(settings.Password); + } + } + + private DataStoreClient CreateClient(String email, String password, DeploymentSlot slot) + { + String token = String.Empty; + + HttpClient http = new HttpClient(); + DataStoreClient dsClient = new DataStoreClient(slot.ToAddress(), http); + var response = dsClient.Login(new LoginRequest() + { + Email = email, + Password = password, + }); + http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", response.Token); + + return dsClient; + } + } +} diff --git a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtilSettings.cs b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtilSettings.cs new file mode 100644 index 000000000..58380d231 --- /dev/null +++ b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/DataStoreUtilSettings.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Settings; + +namespace Tango.DataStore.CLI +{ + public class DataStoreUtilSettings : SettingsBase + { + public String Email { get; set; } + public String Password { get; set; } + } +} diff --git a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Options.cs b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Options.cs index 150756671..fd91a5722 100644 --- a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Options.cs +++ b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Options.cs @@ -4,16 +4,17 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.DataStore.Web; using Tango.Web; namespace Tango.DataStore.CLI { public class OptionsBase { - [Option(longName: "email", HelpText = "Email address.", Required = true)] + [Option(longName: "email", HelpText = "Email address.")] public String Email { get; set; } - [Option(longName: "password", HelpText = "Password.", Required = true)] + [Option(longName: "password", HelpText = "Password.")] public String Password { get; set; } [Option(longName: "env", HelpText = "The target environment.", Required = true)] @@ -45,7 +46,23 @@ namespace Tango.DataStore.CLI [Option(longName: "key", HelpText = "New or existing item key", Required = true)] public String Key { get; set; } + [Option(longName: "data-type", HelpText = "Item data type", Required = true)] + public Web.DataType DataType { get; set; } + + [Option(longName: "proto-type", HelpText = "Protobuf message type when data-type is 'Proto'.")] + public MessageType ProtoMessageType { get; set; } + [Option(longName: "value", HelpText = "Item value", Required = true)] public String Value { get; set; } } + + [Verb("login-config", HelpText = "Stores the specified credentials for use with the --auto-login flag.")] + public class LoginConfig + { + [Option(longName: "email", HelpText = "Email address.")] + public String Email { get; set; } + + [Option(longName: "password", HelpText = "Password.")] + public String Password { get; set; } + } } diff --git a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Program.cs b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Program.cs index db4f54620..85dfbb0bb 100644 --- a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Program.cs +++ b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Program.cs @@ -19,7 +19,7 @@ namespace Tango.DataStore.CLI { var console = new DataStoreConsole(); - var result = Parser.Default.ParseArguments(args) + var result = Parser.Default.ParseArguments(args) .WithParsed((options) => { console.Get(options); @@ -28,6 +28,10 @@ namespace Tango.DataStore.CLI { console.Put(options); }) + .WithParsed((options) => + { + console.AutoLogin(options); + }) .WithNotParsed((errors) => { @@ -41,64 +45,4 @@ namespace Tango.DataStore.CLI } } } - - public class DataStoreConsole - { - public void Get(GetOptions options) - { - try - { - if (options.MachineSerialNumber != null) - { - Console.WriteLine($"Retrieving data store values for '{options.MachineSerialNumber}'..."); - } - else - { - Console.WriteLine("Retrieving global data store values..."); - } - - var client = CreateClient(options.Email, options.Password, options.Environment); - - var items = client.Get(options.MachineSerialNumber, options.Collection, options.Key).ToList(); - - ConsoleTable table = new ConsoleTable("COLLECTION", "KEY", "DATA TYPE", "STATE", "GLOBAL", "LOCAL"); - - foreach (var item in items) - { - table.AddRow(item.Collection, item.Key, item.DataType, item.Type, item.GlobalValue.ToStringSafe().ToOneLine(), item.LocalValue.ToStringSafe().ToOneLine()); - } - - Console.WriteLine(); - Console.WriteLine("DATA STORE RESULTS:"); - Console.WriteLine(); - - table.Write(); - } - catch (Exception ex) - { - Console.WriteLine(ex.FlattenMessage()); - } - } - - public void Put(PutOptions options) - { - - } - - private DataStoreClient CreateClient(String email, String password, DeploymentSlot slot) - { - String token = String.Empty; - - HttpClient http = new HttpClient(); - DataStoreClient dsClient = new DataStoreClient(slot.ToAddress(), http); - var response = dsClient.Login(new LoginRequest() - { - Email = "roy@twine-s.com", - Password = "1Creativity", - }); - http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", response.Token); - - return dsClient; - } - } } diff --git a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Tango.DataStore.CLI.csproj b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Tango.DataStore.CLI.csproj index 28aab4ef7..42b0b95dc 100644 --- a/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Tango.DataStore.CLI.csproj +++ b/Software/Visual_Studio/DataStore/Tango.DataStore.CLI/Tango.DataStore.CLI.csproj @@ -63,6 +63,8 @@ + + @@ -85,6 +87,10 @@ {e4927038-348d-4295-aaf4-861c58cb3943} Tango.PMR + + {d8f1ad85-526a-4f50-b6dc-d437af63d8d8} + Tango.Settings + {5001990f-977b-48ff-b217-0236a5022ad8} Tango.Web diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/DataStoreViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/DataStoreViewVM.cs index d8bd8791a..46f388461 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/DataStoreViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/DataStoreViewVM.cs @@ -114,7 +114,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels private async void EditItem(DataStoreItemModel item) { - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreWrite)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreWrite)) { await NotificationProvider.ShowError("The current user profile does not allow editing of the data store.\nPlease contact your administrator."); return; @@ -133,7 +133,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels private async void AddCollection() { - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreCreate)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreCreate)) { await NotificationProvider.ShowError("The current user profile does not allow creating new data store collections.\nPlease contact your administrator."); return; @@ -174,7 +174,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels private async void AddItem() { - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreCreate)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreCreate)) { await NotificationProvider.ShowError("The current user profile does not allow creating new data store items.\nPlease contact your administrator."); return; @@ -217,7 +217,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels private async void RemoveCollection(DataStoreCollectionModel collection) { - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreCreate)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreCreate)) { await NotificationProvider.ShowError("The current user profile does not allow deleting data store collections.\nPlease contact your administrator."); return; @@ -229,7 +229,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels private async void RemoveItem(DataStoreItemModel item) { - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreCreate)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreCreate)) { await NotificationProvider.ShowError("The current user profile does not allow deleting data store items.\nPlease contact your administrator."); return; @@ -263,7 +263,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels private async void SaveModel() { - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreWrite)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreWrite)) { await NotificationProvider.ShowError("The current user profile does not allow editing of the data store.\nPlease contact your administrator."); return; @@ -332,7 +332,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels { base.OnNavigatedTo(); - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreRead)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreRead)) { return; } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/MachineViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/MachineViewVM.cs index dd2430415..fd953a0b8 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/MachineViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.MachineConfiguration/ViewModels/MachineViewVM.cs @@ -33,7 +33,7 @@ namespace Tango.FSE.MachineConfiguration.ViewModels { if (value == NavigationView.DataStoreView) { - if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_DataStoreRead)) + if (!CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.DataStoreRead)) { Task.Delay(500).ContinueWith((x) => { diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm index 8777b5768..ef7ec26c0 100644 Binary files a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm differ diff --git a/Software/Visual_Studio/FSE/Tango.FSE.LogViewer.UI/Views/LogFileTabView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.LogViewer.UI/Views/LogFileTabView.xaml index 8f06dac0d..92064f9fd 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.LogViewer.UI/Views/LogFileTabView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.LogViewer.UI/Views/LogFileTabView.xaml @@ -16,7 +16,7 @@ Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> - + @@ -24,6 +24,7 @@ + @@ -34,7 +35,7 @@ - + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs index fa70e630e..964eb990b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs @@ -8,5 +8,4 @@ using System.Windows; // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Tango FSE")] -[assembly: AssemblyVersion("1.1.1.0")] - +[assembly: AssemblyVersion("1.1.1.0")] diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 4b4d46a78..2a79629a3 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -601,6 +601,10 @@ + + {6189b8c3-7af9-43dd-8a61-a8a05f526f62} + Tango.DataStore.CLI + {208C8BD8-72C6-4E3C-ACAA-351091A2ACC7} Tango.PPC.Shared diff --git a/Software/Visual_Studio/Tango.BL/Enumerations/Permissions.cs b/Software/Visual_Studio/Tango.BL/Enumerations/Permissions.cs index 5bf6095f5..51e98f6f4 100644 --- a/Software/Visual_Studio/Tango.BL/Enumerations/Permissions.cs +++ b/Software/Visual_Studio/Tango.BL/Enumerations/Permissions.cs @@ -305,19 +305,19 @@ namespace Tango.BL.Enumerations /// (Allows viewing data store items) /// [Description("Allows viewing data store items")] - FSE_DataStoreRead = 1026, + DataStoreRead = 1026, /// /// (Allows writing to data store items) /// [Description("Allows writing to data store items")] - FSE_DataStoreWrite = 1027, + DataStoreWrite = 1027, /// /// (Allows creating data store items and collections) /// [Description("Allows creating data store items and collections")] - FSE_DataStoreCreate = 1028, + DataStoreCreate = 1028, /// /// (Allows resetting the machine counters) @@ -331,5 +331,11 @@ namespace Tango.BL.Enumerations [Description("Allows resetting the machine device registration")] FSE_ResetMachineDeviceRegistration = 1030, + /// + /// (Allows creating creating and editing the global data store) + /// + [Description("Allows creating creating and editing the global data store")] + DataStoreCreateWriteGlobal = 1031, + } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/DataStoreController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/DataStoreController.cs index 0d35bd776..383a59850 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/DataStoreController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/DataStoreController.cs @@ -62,6 +62,11 @@ namespace Tango.MachineService.Controllers throw new AuthenticationException("Your account has been disabled. Please contact your administrator."); } + if (!user.HasPermission(Permissions.DataStoreRead)) + { + throw new AuthenticationException("You are not authorized to access the data store."); + } + var token = WebToken.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject() { UserGuid = user.Guid, @@ -81,7 +86,7 @@ namespace Tango.MachineService.Controllers { try { - if (!RequestToken.Object.Permissions.Contains(Permissions.FSE_DataStoreRead)) + if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreRead)) { throw CreateHttpException(new AuthenticationException("The current user was not authorized to read from the data store."), HttpStatusCode.Unauthorized); } @@ -150,9 +155,9 @@ namespace Tango.MachineService.Controllers { try { - if (!RequestToken.Object.Permissions.Contains(Permissions.FSE_DataStoreWrite)) + if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreWrite)) { - throw CreateHttpException(new AuthenticationException("The current user was not authorized to write to the data store."), HttpStatusCode.BadRequest); + throw CreateHttpException(new AuthenticationException("The current user was not authorized to write to the data store."), HttpStatusCode.Unauthorized); } if (item.Collection == null || item.Key == null) @@ -177,7 +182,7 @@ namespace Tango.MachineService.Controllers if (dbItem == null) { - if (!RequestToken.Object.Permissions.Contains(Permissions.FSE_DataStoreCreate)) + if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreCreate)) { throw CreateHttpException(new AuthenticationException("The current user was not authorized to create new items on the data store."), HttpStatusCode.Unauthorized); } @@ -197,11 +202,16 @@ namespace Tango.MachineService.Controllers } else { + if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreCreateWriteGlobal)) + { + throw CreateHttpException(new AuthenticationException("The current user was not authorized to write to the global data store."), HttpStatusCode.Unauthorized); + } + GlobalDataStoreItem dbItem = db.GlobalDataStoreItems.FirstOrDefault(x => x.CollectionName == item.Collection && x.Key == item.Key); if (dbItem == null) { - if (!RequestToken.Object.Permissions.Contains(Permissions.FSE_DataStoreCreate)) + if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreCreate)) { throw CreateHttpException(new AuthenticationException("The current user was not authorized to create new items on the data store."), HttpStatusCode.Unauthorized); } -- cgit v1.3.1