From 4954a924b8a5b8fd7a213a444027e74b936359be Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Wed, 16 Oct 2019 17:31:51 +0300 Subject: Added support for token authentication from MS to DB. --- .../Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 62f2dc984..7c0851d01 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -145,6 +145,8 @@ + + @@ -388,7 +390,7 @@ - + \ No newline at end of file -- cgit v1.3.1 From c7fa53084c674586ceee773ccbdc6b4c0a2ec7d4 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Mon, 9 Dec 2019 16:19:41 +0200 Subject: Implemented full TUP package update !!! --- .../FirmwareUpgrade/VersionFileDescriptor.proto | 1 - .../Tango.MachineStudio.MachineDesigner.csproj | 8 + .../ViewModels/MainViewVM.cs | 8 + .../ViewModels/TupViewVM.cs | 129 ++++++ .../Views/MachineDetailsView.xaml | 3 + .../Views/TupView.xaml | 60 +++ .../Views/TupView.xaml.cs | 28 ++ .../Tango.MachineStudio.Common.csproj | 17 +- .../Tup/TupFileBuilder.cs | 285 +++++++++++++ .../Tup/TupFileBuilderProgressEventArgs.cs | 16 + .../Web/DownloadLatestPPCVersionRequest.cs | 14 + .../Web/DownloadLatestPPCVersionResponse.cs | 21 + .../Web/MachineStudioWebClientBase.cs | 9 + .../Tango.MachineStudio.Common/packages.config | 1 + .../Tango.MachineStudio.UI.csproj | 6 +- .../MachineUpdate/IMachineUpdateManager.cs | 7 +- .../MachineUpdate/MachineUpdateManager.cs | 468 ++++++++++++++++++--- .../MachineUpdate/MachineUpdateResult.cs | 13 + .../MachineUpdate/UpdatePackageFile.cs | 13 - .../PPC/Tango.PPC.Common/Publish/PublishInfo.cs | 6 +- .../PPC/Tango.PPC.Common/Tango.PPC.Common.csproj | 1 - .../Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml | 12 +- .../Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs | 30 +- .../PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml | 5 +- Software/Visual_Studio/Tango.Core/DB/DbManager.cs | 33 +- .../FirmwareUpgrade/VersionFileDescriptor.cs | 37 +- .../ExaminerSequenceConfigurationRunner.cs | 9 + .../Tango.SQLExaminer/ExtensionMethods.cs | 21 + Software/Visual_Studio/Tango.SQLExaminer/Helper.cs | 2 +- .../Tango.SQLExaminer/Tango.SQLExaminer.csproj | 1 + .../SQLExaminer/SQLExaminer_TST.cs | 71 ++++ .../Controllers/MachineStudioController.cs | 65 +++ .../Controllers/PPCController.cs | 2 +- 33 files changed, 1257 insertions(+), 145 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs delete mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs create mode 100644 Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj') diff --git a/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto b/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto index ce44290a0..9e74cdee6 100644 --- a/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto +++ b/Software/PMR/Messages/FirmwareUpgrade/VersionFileDescriptor.proto @@ -10,5 +10,4 @@ message VersionFileDescriptor string FileName = 1; string Version = 2; VersionFileDestination Destination = 3; - bytes CheckSum = 4; } \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj index 6225bd7ad..69cc75461 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Tango.MachineStudio.MachineDesigner.csproj @@ -93,6 +93,7 @@ + ColorCalibrationView.xaml @@ -130,6 +131,9 @@ MachineUpdatesView.xaml + + TupView.xaml + SpoolsView.xaml @@ -185,6 +189,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + Designer MSBuild:Compile diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs index 820950290..768f93de1 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs @@ -140,6 +140,12 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels set { _machineUpdatesViewVM = value; RaisePropertyChangedAuto(); } } + private TupViewVM _tupViewVM; + public TupViewVM TupViewVM + { + get { return _tupViewVM; } + set { _tupViewVM = value; RaisePropertyChangedAuto(); } + } #endregion @@ -233,6 +239,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels ResetDeviceRegistrationCommand = new RelayCommand(ResetDeviceRegistration); MachineUpdatesViewVM = new MachineUpdatesViewVM(_notification); + TupViewVM = new TupViewVM(_notification); } #endregion @@ -478,6 +485,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels HardwareConfigurationViewVM.Init(ActiveMachine.Configuration); await MachineUpdatesViewVM.Init(ActiveMachine, ActiveMachineAdapter.Context); + TupViewVM.Init(ActiveMachine); ActiveMachine.Configuration.HardwareVersionChanged += Configuration_HardwareVersionChanged; diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs new file mode 100644 index 000000000..12ed09c75 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/TupViewVM.cs @@ -0,0 +1,129 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Core.Commands; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.Common.Tup; +using Tango.SharedUI; + +namespace Tango.MachineStudio.MachineDesigner.ViewModels +{ + public class TupViewVM : ViewModel + { + private INotificationProvider _notification; + + private String _latestVersion; + public String LatestVersion + { + get { return _latestVersion; } + set { _latestVersion = value; RaisePropertyChangedAuto(); } + } + + private Machine _machine; + public Machine Machine + { + get { return _machine; } + set { _machine = value; RaisePropertyChangedAuto(); } + } + + private String _filePath; + public String FilePath + { + get { return _filePath; } + set { _filePath = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private TupFileBuilderProgressEventArgs _progress; + public TupFileBuilderProgressEventArgs Progress + { + get { return _progress; } + set { _progress = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand CreateTupFileCommand { get; set; } + + public RelayCommand SelectFileCommand { get; set; } + + public TupViewVM() + { + + } + + public TupViewVM(INotificationProvider notification) : this() + { + _notification = notification; + CreateTupFileCommand = new RelayCommand(CreateTupFile, () => FilePath != null && IsFree); + SelectFileCommand = new RelayCommand(SelectFile); + } + + public void Init(Machine machine) + { + Machine = machine; + DisplayLatestPPCVersion(); + } + + private async void DisplayLatestPPCVersion() + { + TupFileBuilder builder = new TupFileBuilder(); + + try + { + LatestVersion = await builder.GetLatestPPCVersion(Machine.SerialNumber); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error retrieving latest PPC version."); + await Task.Delay(5000); + DisplayLatestPPCVersion(); + } + } + + private void SelectFile() + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = "Select package location"; + dlg.Filter = "Tango Update Package Files|*.tup"; + dlg.DefaultExt = ".tup"; + dlg.FileName = LatestVersion == null ? $"{Machine.SerialNumber}_Update.tup" : $"{Machine.SerialNumber}_Update_v{LatestVersion}.tup"; + + if (dlg.ShowDialog().Value) + { + FilePath = dlg.FileName; + } + } + + private async void CreateTupFile() + { + try + { + LogManager.Log($"Generating TUP file to '{FilePath}'..."); + + IsFree = false; + TupFileBuilder builder = new TupFileBuilder(); + builder.Progress += Builder_Progress; + await builder.Build(Machine.SerialNumber, FilePath); + + LogManager.Log("TUP file generated successfully."); + _notification.ShowInfo("Tango update package created successfuly."); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error generating tup file."); + _notification.ShowError($"An error occurred while generating the .tup file.\n{ex.FlattenMessage()}"); + } + finally + { + IsFree = true; + } + } + + private void Builder_Progress(object sender, TupFileBuilderProgressEventArgs e) + { + Progress = e; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml index 666a4ee4a..bcca83ca5 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineDetailsView.xaml @@ -64,6 +64,9 @@ + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml new file mode 100644 index 000000000..895a26ca0 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + Create a complete update package (.tup) in order to update this machine offline using a removable storage device. + + The latest PPC version is + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs new file mode 100644 index 000000000..fe01296d8 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/TupView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.MachineDesigner.Views +{ + /// + /// Interaction logic for SpoolsView.xaml + /// + public partial class TupView : UserControl + { + public TupView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 7c0851d01..3ce667afe 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -59,6 +59,9 @@ ..\..\Referenced Assemblies\SMO\Microsoft.SqlServer.AzureStorageEnum.dll + + ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + @@ -83,6 +86,9 @@ + + Tup\PublishInfo.cs + GlobalVersionInfo.cs @@ -95,6 +101,10 @@ + + + + @@ -291,6 +301,10 @@ {8491d07b-c1f6-4b62-a412-41b9fd2d6538} Tango.SharedUI + + {e1e66ed9-597d-45fa-8048-de90a6930484} + Tango.SQLExaminer + {74e700b0-1156-4126-be40-ee450d3c3026} Tango.Transport @@ -387,10 +401,11 @@ + - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs new file mode 100644 index 000000000..6dd8b82f7 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilder.cs @@ -0,0 +1,285 @@ +using Ionic.Zip; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tango.BL; +using Tango.Core; +using Tango.Core.DB; +using Tango.Core.DI; +using Tango.MachineStudio.Common.Web; +using Tango.SQLExaminer; +using Tango.Transport.Web; +using Tango.Core.ExtensionMethods; +using Tango.PPC.Common.Publish; +using Tango.Settings; +using Tango.Core.Components; +using System.Text.RegularExpressions; + +namespace Tango.MachineStudio.Common.Tup +{ + public class TupFileBuilder : ExtendedObject + { + public event EventHandler Progress; + + public Task Build(String serialNumber, String filePath) + { + return Task.Factory.StartNew(() => + { + String tempDbName = "Tango_TUP"; + var tempPackageFolder = TemporaryManager.CreateFolder(); + String tempBackupFolder = "C:\\MachineStudioTUP"; + String tempBackupFile = Path.Combine(tempBackupFolder, tempDbName + ".bak"); + var tempZipFile = TemporaryManager.CreateImaginaryFile(); + DbManager dbManager = null; + + LogManager.Log("Generating tup file..."); + LogManager.Log($"Tup file: '{filePath}.'"); + LogManager.Log($"Temporary db name: '{tempDbName}'."); + LogManager.Log($"Temporary package folder: '{tempPackageFolder}'."); + LogManager.Log($"Temporary db backup folder: '{tempBackupFolder}'."); + LogManager.Log($"Temporary db backup file: '{tempBackupFile}'."); + LogManager.Log($"Temporary zip file: '{tempZipFile}'."); + + try + { + LogManager.Log("Initializing..."); + + OnProgress("Initializing..."); + + Core.DataSource localDataSource = new Core.DataSource() + { + Address = "localhost\\SQLEXPRESS", + IntegratedSecurity = true, + Type = DataSourceType.SQLServer, + Catalog = null, + }; + + try + { + LogManager.Log($"Trying to connect via SQLEXPRESS:\n{localDataSource.ToJsonString()}"); + dbManager = DbManager.FromDataSource(localDataSource); + } + catch (Exception ex) + { + try + { + LogManager.Log(ex, "Could not connect using SQLEXPRESS. Trying local DB..."); + + CmdCommand command = new CmdCommand("sqllocaldb", "info \"MSSQLLocalDB\""); + var result = command.Run().Result; + + String pattern = "np:.+"; + Regex reg = new Regex(pattern); + var match = reg.Match(result.StandardOutput); + String address = match.ToString(); + if (address.Contains("np:")) + { + localDataSource.Address = address; + address = address.Trim().Replace("\r", ""); + } + else + { + throw new ArgumentException("Could not parse LocalDB address string."); + } + + LogManager.Log($"Trying to connect via LocalDB:\n{localDataSource.ToJsonString()}"); + dbManager = DbManager.FromDataSource(localDataSource); + } + catch (Exception x) + { + LogManager.Log(x, "Could not find any database service for this operation."); + throw x; + } + } + + + + OnProgress("Downloading latest PPC version..."); + + LogManager.Log("Connecting to machine service..."); + MachineStudioWebClient client = TangoIOC.Default.GetInstance(); + + LogManager.Log("Requesting latest PPC version from machine service..."); + var response = client.DownloadLatestPPCVersion(new DownloadLatestPPCVersionRequest() { SerialNumber = serialNumber }).Result; + + LogManager.Log($"Machine service response:\n{response.ToJsonString()}"); + + var remoteDataSource = response.DataSource; + + using (AutoFileDownloader downloader = new AutoFileDownloader(response.BlobAddress, response.CdnAddress, tempZipFile)) + { + downloader.Progress += (x, e) => + { + OnProgress($"Downloading latest PPC version '{response.Version}'...", false, e.Current, e.Total); + }; + + downloader.ResolveMode().GetAwaiter().GetResult(); + + LogManager.Log($"Downloading latest PPC version from: '{downloader.Address}'"); + + downloader.Download().Wait(); + } + + LogManager.Log("Extracting PPC version package..."); + + OnProgress("Extracting PPC package..."); + + using (ZipFile zip = new ZipFile(tempZipFile)) + { + int currentEntry = 0; + + zip.ExtractProgress += (x, args) => + { + if (args.EventType == ZipProgressEventType.Extracting_AfterExtractEntry) + { + OnProgress("Extracting PPC package...", false, currentEntry++, zip.Entries.Count); + } + }; + + zip.ExtractAll(tempPackageFolder); + } + + OnProgress("Extracting version information..."); + LogManager.Log("Extracting publish information..."); + PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(tempPackageFolder, "version.json"))); + LogManager.Log($"Publish Information:\n{publishInfo}"); + + LogManager.Log("Modifying publish information to custom tup file..."); + publishInfo.IsMachineTupPackage = true; + publishInfo.MachineSerialNumber = serialNumber; + publishInfo.MachineDeploymentSlot = SettingsManager.Default.GetOrCreate().DeploymentSlot; + + OnProgress("Creating temporary database..."); + + LogManager.Log($"Creating temporary db backup directory '{tempBackupFolder}'"); + + Directory.CreateDirectory(tempBackupFolder); + + LogManager.Log($"Creating new database: '{tempDbName}'"); + + //Create temp db + dbManager.Create(tempDbName, Path.Combine(tempBackupFolder, tempDbName + ".mdf")); + + OnProgress("Generating database snapshot..."); + + LogManager.Log("Starting database synchronization..."); + + Thread.Sleep(2000); + + localDataSource.Catalog = tempDbName; + + ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner( + Path.Combine(tempPackageFolder, "Provision Scripts", "config.xml"), + Path.Combine(tempPackageFolder, "Provision Scripts"), + remoteDataSource, + localDataSource, + serialNumber); + + runner.ScriptExecuting += (x, item) => + { + LogManager.Log($"Executing script '{item.FileName}'..."); + OnProgress($"{item.Name}..."); + }; + + runner.Log += (x, log) => + { + LogManager.Log(log); + }; + + runner.Run().GetAwaiter().GetResult(); + + OnProgress("Generating database snapshot..."); + + if (File.Exists(tempBackupFile)) + { + LogManager.Log($"Deleting file '{tempBackupFile}'"); + File.Delete(tempBackupFile); + } + + LogManager.Log($"Generating backup for '{tempDbName}' to '{tempBackupFile}'..."); + + dbManager.Backup(tempDbName, tempBackupFile); + + OnProgress("Injecting database snapshot to PPC package..."); + + using (ZipFile zip = new ZipFile(tempZipFile)) + { + LogManager.Log($"Injecting file '{tempBackupFile}' to original package at '{tempZipFile}'..."); + zip.AddFile(tempBackupFile, "/"); + + LogManager.Log($"Injecting modified publish information..."); + zip.UpdateEntry("version.json", publishInfo.ToJson()); + + zip.Save(); + } + + LogManager.Log($"Copying '{tempZipFile}' to '{filePath}'..."); + + File.Copy(tempZipFile, filePath, true); + + OnProgress("Completed", false, 100, 100); + + LogManager.Log("TUP file generation completed successfully."); + } + catch (Exception ex) + { + LogManager.Log(ex, "TUP file generation failed."); + OnProgress("Failed", false, 0, 100); + throw ex; + } + finally + { + LogManager.Log($"Removing '{tempZipFile}'."); + tempZipFile.Delete(); + LogManager.Log($"Removing '{tempPackageFolder}'."); + tempPackageFolder.Delete(); + + try + { + LogManager.Log($"Removing database '{tempDbName}'."); + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + dbManager.Dispose(); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error removing temp database '{tempDbName}'."); + } + + try + { + LogManager.Log($"Removing '{tempBackupFolder}'."); + Directory.Delete(tempBackupFolder, true); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error removing folder '{tempBackupFolder}'."); + } + } + }); + } + + public async Task GetLatestPPCVersion(String serialNumber) + { + MachineStudioWebClient client = TangoIOC.Default.GetInstance(); + var response = await client.DownloadLatestPPCVersion(new DownloadLatestPPCVersionRequest() { SerialNumber = serialNumber }); + return response.Version; + } + + private void OnProgress(String message, bool isIntermediate = true, double progress = 0, double total = 100) + { + Progress?.Invoke(this, new TupFileBuilderProgressEventArgs() + { + Message = message, + IsIntermediate = isIntermediate, + Progress = progress, + Total = total, + }); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs new file mode 100644 index 000000000..ada69dd40 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tup/TupFileBuilderProgressEventArgs.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Common.Tup +{ + public class TupFileBuilderProgressEventArgs + { + public double Progress { get; set; } + public double Total { get; set; } + public bool IsIntermediate { get; set; } + public String Message { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.cs new file mode 100644 index 000000000..24d465e69 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionRequest.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.MachineStudio.Common.Web +{ + public class DownloadLatestPPCVersionRequest : WebRequestMessage + { + public String SerialNumber { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs new file mode 100644 index 000000000..2cc6b731a --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestPPCVersionResponse.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Transport.Web; + +namespace Tango.MachineStudio.Common.Web +{ + public class DownloadLatestPPCVersionResponse : WebResponseMessage + { + public String Version { get; set; } + + public String BlobAddress { get; set; } + + public String CdnAddress { get; set; } + + public DataSource DataSource { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs index 131f89515..c2d0dd3e6 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs @@ -94,5 +94,14 @@ namespace Tango.MachineStudio.Common.Web return Post("RefreshToken", request); } + /// + /// Executes the DownloadLatestPPCVersion action and returns Tango.MachineStudio.Common.Web.DownloadLatestPPCVersionResponse. + /// + /// + public Task DownloadLatestPPCVersion(Tango.MachineStudio.Common.Web.DownloadLatestPPCVersionRequest request) + { + return Post("DownloadLatestPPCVersion", request); + } + } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config index f871776f5..6fd5091a8 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/packages.config @@ -9,4 +9,5 @@ + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 991eb9da6..c6cf624b3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -448,6 +448,10 @@ {8491d07b-c1f6-4b62-a412-41b9fd2d6538} Tango.SharedUI + + {e1e66ed9-597d-45fa-8048-de90a6930484} + Tango.SQLExaminer + {998f8471-dc1b-41b6-9d96-354e1b4e7a32} Tango.TFS @@ -661,7 +665,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs index 3655aa462..e11eab3a5 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.PMR.Synchronization; +using Tango.PPC.Common.Publish; using Tango.PPC.Common.UpdatePackages; using Tango.PPC.Common.Web; @@ -43,14 +44,14 @@ namespace Tango.PPC.Common.MachineUpdate /// if set to true updates the embedded device firmware. /// if set to true updates the embedded device FPGA version and other parameters. /// - Task Update(String serialNumber, bool setupFirmware, bool setupFPGA); + Task Update(bool setupFirmware, bool setupFPGA); /// /// Performs a machine update using the specified software update package path. /// /// Name of the file. /// - Task UpdateFromTUP(String fileName); + Task UpdateFromTUP(String fileName, bool setupFirmware, bool setupFPGA); /// /// Checks if any update are available for the specified machine serial number. @@ -77,7 +78,7 @@ namespace Tango.PPC.Common.MachineUpdate /// /// The file path. /// - Task GetUpdatePackageFileInfo(String filePath); + Task GetUpdatePackageFileInfo(String filePath); /// /// Checks whether any post update packages needs to be installed. diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs index 5296a9f34..7e742ceb6 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs @@ -22,6 +22,7 @@ using Tango.PMR.Synchronization; using Tango.PPC.Common.Application; using Tango.PPC.Common.Connection; using Tango.PPC.Common.Navigation; +using Tango.PPC.Common.Publish; using Tango.PPC.Common.UpdatePackages; using Tango.PPC.Common.Web; using Tango.Settings; @@ -117,7 +118,10 @@ namespace Tango.PPC.Common.MachineUpdate private void LogManager_NewLog(object sender, LogItemBase e) { - _logs.Add(e); + if (_isUpdating) + { + _logs.Add(e); + } } #endregion @@ -133,37 +137,80 @@ namespace Tango.PPC.Common.MachineUpdate }); } - private async void OnFailed(Exception ex, TaskCompletionSource completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, Tango.Core.DataSource localDataSource) + private async void OnFailed(Exception ex, TaskCompletionSource completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, String backupsFolder, String tempDbName, Tango.Core.DataSource localDataSource, String tempUpdatePackageFolder = null) { LogManager.Log(ex, "An error occurred in machine update."); - if (performDatabaseRollback) + await Task.Factory.StartNew(() => { - LogManager.Log("Rolling back database changes..."); - using (DbManager db = DbManager.FromDataSource(localDataSource)) + if (performDatabaseRollback) + { + LogManager.Log("Rolling back database changes..."); + + using (DbManager db = DbManager.FromDataSource(localDataSource)) + { + try + { + UpdateProgress("Rollback", "Rolling back database changes..."); + db.Restore(localDataSource.Catalog, dbBackupFile); + LogManager.Log("Database restored successfully."); + } + catch (Exception e) + { + LogManager.Log(e, "Could not rollback the database."); + } + finally + { + try + { + File.Delete(dbBackupFile); + } + catch { } + } + } + } + + if (tempDbName != null) { try { - UpdateProgress("Rollback", "Rolling back database changes..."); - await Task.Factory.StartNew(() => db.Restore(localDataSource.Catalog, dbBackupFile)); - LogManager.Log("Database restored successfully."); + LogManager.Log($"Removing temporary database '{tempDbName}'..."); + using (DbManager dbManager = DbManager.FromDataSource(localDataSource)) + { + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + } } - catch (Exception e) + catch (Exception exx) { - LogManager.Log(e, "Could not rollback the database."); - throw ex; + LogManager.Log(exx, "Error removing temporary database."); } - finally + } + + try + { + Directory.Delete(backupsFolder, true); + } + catch (Exception ee) + { + LogManager.Log(ee, $"Error deleting backups folder '{backupsFolder}'."); + } + + if (tempUpdatePackageFolder != null) + { + try { - try - { - File.Delete(dbBackupFile); - } - catch { } + Directory.Delete(tempUpdatePackageFolder, true); + } + catch (Exception eee) + { + LogManager.Log(eee, "Error removing temporary package folder."); } } - } + + }); completionSource.SetException(ex); @@ -188,13 +235,50 @@ namespace Tango.PPC.Common.MachineUpdate _isUpdating = false; } - private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource completionSource, DownloadUpdateResponse response, String dbBackupFile) + private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource completionSource, DownloadUpdateResponse response, String tempDbName, String backupsFolder, Core.DataSource localDataSource) { - try + await Task.Factory.StartNew(() => { - File.Delete(dbBackupFile); - } - catch { } + if (tempDbName != null) + { + try + { + LogManager.Log($"Removing temporary database '{tempDbName}'..."); + using (DbManager dbManager = DbManager.FromDataSource(localDataSource)) + { + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error removing temporary database."); + } + } + + try + { + Directory.Delete(backupsFolder, true); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error deleting backups folder '{backupsFolder}'."); + } + + if (!result.RequiresBinariesUpdate) + { + try + { + Directory.Delete(result.UpdatePackagePath, true); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error removing temporary package folder."); + } + } + + }); completionSource.SetResult(result); @@ -315,7 +399,7 @@ namespace Tango.PPC.Common.MachineUpdate /// or /// /// Database tango does not exists. - public async Task Update(String serialNumber, bool setupFirmware, bool setupFPGA) + public async Task Update(bool setupFirmware, bool setupFPGA) { _logs.Clear(); @@ -325,6 +409,13 @@ namespace Tango.PPC.Common.MachineUpdate bool performDatabaseRollback = false; String dbBackupFile = null; DownloadUpdateResponse update_response = null; + String backupsFolder = "C:\\Backups"; + + //Create temporary folders for packages. + var _newPackageTempFolder = TemporaryManager.CreateFolder(); + _newPackageTempFolder.Persist = true; + + String serialNumber = _machineProvider.Machine.SerialNumber; try { @@ -371,10 +462,6 @@ namespace Tango.PPC.Common.MachineUpdate LogManager.Log($"Machine update response received: {Environment.NewLine}{update_response.ToJsonString()}"); - //Create temporary folders for packages. - var _newPackageTempFolder = TemporaryManager.CreateFolder(); - _newPackageTempFolder.Persist = true; - LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}."); //Download software package. @@ -413,8 +500,12 @@ namespace Tango.PPC.Common.MachineUpdate UpdateProgress("Downloading software package", "Extracting package..."); LogManager.Log("Extracting downloaded zip file..."); - //Extract software package. - ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder); + + await Task.Factory.StartNew(() => + { + //Extract software package. + ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder); + }); LogManager.Log("Copying latest updater utility to application path..."); //Copy new updater utility to app path. @@ -464,8 +555,8 @@ namespace Tango.PPC.Common.MachineUpdate //Create Database Backup try { - Directory.CreateDirectory("C:\\Backups"); - dbBackupFile = $"C:\\Backups\\{Path.GetRandomFileName()}.bak"; + Directory.CreateDirectory(backupsFolder); + dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak"; LogManager.Log($"Creating database backup to '{dbBackupFile}'..."); await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile)); performDatabaseRollback = true; @@ -548,7 +639,7 @@ namespace Tango.PPC.Common.MachineUpdate handler.Failed += (_, ex) => { stream.Dispose(); - OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, localDataSource); + OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder); }; handler.Completed += (_, __) => { @@ -557,12 +648,12 @@ namespace Tango.PPC.Common.MachineUpdate OnCompleted(new MachineUpdateResult() { UpdatePackagePath = _newPackageTempFolder, - }, result, update_response, dbBackupFile); + }, result, update_response, null, backupsFolder, localDataSource); }; handler.Canceled += (_, __) => { stream.Dispose(); - OnFailed(new Exception("The operation has been canceled."), result, update_response, performDatabaseRollback, dbBackupFile, localDataSource); + OnFailed(new Exception("The operation has been canceled."), result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder); }; handler.Progress += (_, e) => { @@ -574,12 +665,12 @@ namespace Tango.PPC.Common.MachineUpdate OnCompleted(new MachineUpdateResult() { UpdatePackagePath = _newPackageTempFolder, - }, result, update_response, dbBackupFile); + }, result, update_response, null, backupsFolder, localDataSource); } } catch (Exception ex) { - OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, localDataSource); + OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder); } return await result.Task; @@ -875,31 +966,284 @@ namespace Tango.PPC.Common.MachineUpdate /// /// Name of the file. /// - public Task UpdateFromTUP(string fileName) + public async Task UpdateFromTUP(string fileName, bool setupFirmware, bool setupFPGA) { - return Task.Factory.StartNew(() => + _logs.Clear(); + + TaskCompletionSource result = new TaskCompletionSource(); + + var localDataSource = SettingsManager.Default.GetOrCreate().DataSource; + bool performDatabaseRollback = false; + String dbBackupFile = null; + String tempDbName = "Tango_TUP"; + String tempDbFileName = tempDbName + ".bak"; + String backupsFolder = "C:\\Backups"; + bool replaceBinaries = false; + + String serialNumber = _machineProvider.Machine.SerialNumber; + + //Create temporary folders for packages. + var _newPackageTempFolder = TemporaryManager.CreateFolder(); + _newPackageTempFolder.Persist = true; + + try { - LogManager.Log($"Starting machine update from update package '{fileName}'..."); + _isUpdating = true; + + LogManager.Log($"Starting machine update for serial number {serialNumber}..."); - //Create temporary folders for packages. - var _newPackageTempFolder = TemporaryManager.CreateFolder(); - _newPackageTempFolder.Persist = true; + //Connecting to machine... + LogManager.Log("Verifying machine connection and state..."); - LogManager.Log("Extracting downloaded zip file..."); - //Extract software package. - ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder); + UpdateProgress("Verifying machine state", "Initializing..."); + + await Task.Delay(1000); + + IMachineOperator op = _machineProvider.MachineOperator; + + if (setupFirmware) + { + LogManager.Log("Machine is configured to update firmware..."); + + if (op.State != Transport.TransportComponentState.Connected) + { + throw LogManager.Log(new InvalidOperationException("Could not perform an update while the machine is not connected.")); + } + if (op.Status != MachineStatuses.ReadyToDye) + { + throw LogManager.Log(new InvalidOperationException($"Could not perform an update while the machine is in {op.Status} status.")); + } + } + + UpdateProgress("Exploring package", "Extracting..."); + LogManager.Log("Extracting package..."); + + LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}."); + + await Task.Factory.StartNew(() => + { + //Extract software package. + ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder); + }); + + //Extracting publish info + UpdateProgress("Exploring package", "Verifying..."); + PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(_newPackageTempFolder, "version.json"))); + + if (!publishInfo.IsMachineTupPackage) + { + throw new InvalidOperationException("The specified tup file is invalid. Updating a machine from a tup file requires a custom generated package."); + } + + if (publishInfo.MachineSerialNumber != serialNumber) + { + throw new InvalidOperationException("The specified tup file is invalid. The package was generated for a different machine."); + } + + if (publishInfo.MachineDeploymentSlot != SettingsManager.Default.GetOrCreate().DeploymentSlot) + { + throw new InvalidOperationException("The specified tup file is invalid. The package was generated on a different environment."); + } + + replaceBinaries = _app_manager.Version.ToString() != publishInfo.ApplicationVersion; LogManager.Log("Copying latest updater utility to application path..."); + //Copy new updater utility to app path. File.Copy(Path.Combine(_newPackageTempFolder, "Tango.PPC.Updater.exe"), Path.Combine(PathHelper.GetStartupPath(), "Tango.PPC.Updater.exe"), true); - LogManager.Log("Update operation completed!"); + //Run pre-update packages. + try + { + UpdateProgress("Preparing", "Running update packages..."); + LogManager.Log("Running pre-update packages..."); + var packagesFolder = Path.Combine(_newPackageTempFolder, "Packages"); - return new MachineUpdateResult() + Version updateVersion = new Version(1, 0, 0, 0); + try + { + updateVersion = Version.Parse(publishInfo.ApplicationVersion); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error parsing new version string for package runner."); + } + + await _packageRunner.Run(PackageType.Pre, updateVersion, packagesFolder); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error running pre-update packages..."); + } + + //Synchronize database + UpdateProgress("Updating Database", "Initializing..."); + + UpdateProgress("Updating Database", "Connecting to local database..."); + LogManager.Log("Initializing database manager..."); + DbManager db = DbManager.FromDataSource(localDataSource); + + LogManager.Log("Checking Tango database exists on the local machine..."); + if (!db.Exists(localDataSource.Catalog)) + { + throw new InvalidProgramException("Database tango does not exists."); + } + + UpdateProgress("Updating Database", "Creating database backup..."); + + //Create Database Backup + try + { + Directory.CreateDirectory(backupsFolder); + dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak"; + LogManager.Log($"Creating database backup to '{dbBackupFile}'..."); + await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile)); + performDatabaseRollback = true; + LogManager.Log("Database backup created successfully."); + } + catch (Exception ex) + { + throw LogManager.Log(ex, "Update manager error while trying to create a database backup."); + } + + LogManager.Log("Extracting database file from package..."); + File.Copy(Path.Combine(_newPackageTempFolder, tempDbFileName), Path.Combine(backupsFolder, tempDbFileName)); + + LogManager.Log("Restoring package database as a new database..."); + db.RestoreAsNew(tempDbName, Path.Combine(backupsFolder, tempDbFileName), backupsFolder); + + Core.DataSource tempDbDataSource = new Core.DataSource(); + tempDbDataSource.Address = localDataSource.Address; + tempDbDataSource.IntegratedSecurity = localDataSource.IntegratedSecurity; + tempDbDataSource.Type = localDataSource.Type; + tempDbDataSource.Catalog = tempDbName; + + LogManager.Log("Disposing database manager."); + db.Dispose(); + + LogManager.Log($"Initializing {nameof(ExaminerSequenceConfigurationRunner)}..."); + + UpdateProgress("Updating Database", "Initializing update sequence..."); + + ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner( + Path.Combine(_newPackageTempFolder, "Update Scripts", "config.xml"), + Path.Combine(_newPackageTempFolder, "Update Scripts"), + tempDbDataSource, + localDataSource, + serialNumber); + + runner.Log += (x, msg) => { - UpdatePackagePath = _newPackageTempFolder, + LogManager.Log(msg); + ProgressLog?.Invoke(this, msg); }; - }); + + runner.ScriptExecuting += (x, item) => + { + LogManager.Log($"Executing script {item.ToString()}..."); + UpdateProgress("Updating Database", item.Name + "..."); + }; + + LogManager.Log("Starting synchronization process..."); + + try + { + await runner.Run(); + LogManager.Log("Synchronization completed successfully!"); + UpdateProgress("Updating Database", "Database synchronization completed successfully."); + } + catch (Exception ex) + { + throw LogManager.Log(ex, "Update manager error while trying to synchronize database."); + } + + LogManager.Log("Getting setup firmware/fpga directly from db.."); + + using (var dbManager = DbManager.FromDataSource(localDataSource)) + { + try + { + String firmware = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FIRMWARE"); + String fpga = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FPGA"); + + setupFirmware = bool.Parse(firmware); + setupFPGA = bool.Parse(fpga); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error getting new values of SETUP_FIRMWARE and SETUP_FPGA."); + } + } + + //Updating firmware + if (setupFirmware) + { + UpdateProgress("Updating Firmware", "Connecting to firmware device..."); + LogManager.Log(""); + LogManager.Log("-------------------------------------------------------------------------"); + LogManager.Log("Updating Firmware..."); + + UpdateProgress("Updating Firmware", "Loading firmware package..."); + var tfpPath = Path.Combine(_newPackageTempFolder, "firmware_package.tfp"); + var stream = new FileStream(tfpPath, FileMode.Open); + + if (!_machineProvider.Machine.IsDemo) + { + if (setupFPGA) + { + op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU | FirmwareUpgradeModes.TFP_PACKAGE; + } + else + { + op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU; + } + } + else + { + op.FirmwareUpgradeMode = FirmwareUpgradeModes.TFP_PACKAGE; + } + + var handler = await op.UpgradeFirmware(stream); + handler.Failed += (_, ex) => + { + stream.Dispose(); + OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + }; + handler.Completed += (_, __) => + { + UpdateProgress("Updating Firmware", "Firmware update completed successfully."); + stream.Dispose(); + OnCompleted(new MachineUpdateResult() + { + UpdatePackagePath = _newPackageTempFolder, + RequiresBinariesUpdate = replaceBinaries, + }, result, null, tempDbName, backupsFolder, localDataSource); + }; + handler.Canceled += (_, __) => + { + stream.Dispose(); + OnFailed(new Exception("The operation has been canceled."), result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + }; + handler.Progress += (_, e) => + { + UpdateProgress("Updating Firmware", e.Message, false, e.Current, e.Total); + }; + } + else + { + OnCompleted(new MachineUpdateResult() + { + UpdatePackagePath = _newPackageTempFolder, + RequiresBinariesUpdate = replaceBinaries, + }, result, null, tempDbName, backupsFolder, localDataSource); + } + } + catch (Exception ex) + { + OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + } + + return await result.Task; } /// @@ -907,25 +1251,23 @@ namespace Tango.PPC.Common.MachineUpdate /// /// The file path. /// - public Task GetUpdatePackageFileInfo(string filePath) + public Task GetUpdatePackageFileInfo(string filePath) { - return Task.Factory.StartNew(() => + return Task.Factory.StartNew(() => { - UpdatePackageFile file = new UpdatePackageFile(); - var tempFolder = TemporaryManager.CreateFolder(); - using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(filePath)) { - var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "Tango.PPC.UI.exe"); - appEntry.Extract(tempFolder); - } + var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "version.json"); + var reader = appEntry.OpenReader(); - FileVersionInfo info = FileVersionInfo.GetVersionInfo(Path.Combine(tempFolder, "Tango.PPC.UI.exe")); - file.Version = Version.Parse(info.ProductVersion); - - tempFolder.Delete(); + using (StreamReader stReader = new StreamReader(reader)) + { + String json = stReader.ReadToEnd(); + reader.Dispose(); - return file; + return PublishInfo.FromJson(json); + } + } }); } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs index 17ae394ee..85dd5b7d2 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs @@ -12,5 +12,18 @@ namespace Tango.PPC.Common.MachineUpdate /// Gets or sets the temporary update package path from which to get the last downloaded software version. /// public String UpdatePackagePath { get; set; } + + /// + /// Gets or sets a value indicating whether the application should replace it's binaries. + /// + public bool RequiresBinariesUpdate { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public MachineUpdateResult() + { + RequiresBinariesUpdate = true; + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs deleted file mode 100644 index df496c3be..000000000 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.PPC.Common.MachineUpdate -{ - public class UpdatePackageFile - { - public Version Version { get; set; } - } -} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs index 77717254e..df5690a05 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.PMR.FirmwareUpgrade; +using Tango.Web; namespace Tango.PPC.Common.Publish { @@ -13,6 +14,9 @@ namespace Tango.PPC.Common.Publish public String ApplicationVersion { get; set; } public VersionPackageDescriptor Firmware { get; set; } public String Comments { get; set; } + public bool IsMachineTupPackage { get; set; } + public String MachineSerialNumber { get; set; } + public DeploymentSlot MachineDeploymentSlot { get; set; } public PublishInfo() { @@ -24,7 +28,7 @@ namespace Tango.PPC.Common.Publish return JsonConvert.SerializeObject(this); } - public PublishInfo FromJson(String json) + public static PublishInfo FromJson(String json) { return JsonConvert.DeserializeObject(json); } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj index e3a23903e..d38b9c8e9 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj @@ -194,7 +194,6 @@ - diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml index 231f5dabb..a175b655e 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml @@ -6,16 +6,16 @@ xmlns:local="clr-namespace:Tango.PPC.UI.Dialogs" xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch" mc:Ignorable="d" - Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DesignHeight="555" d:DesignWidth="560" Width="550" Height="450" d:DataContext="{d:DesignInstance Type=local:UpdateFromFileViewVM, IsDesignTimeCreatable=False}"> + Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DesignHeight="555" d:DesignWidth="560" Width="570" Height="700" d:DataContext="{d:DesignInstance Type=local:UpdateFromFileViewVM, IsDesignTimeCreatable=False}"> - - CANCEL - UPDATE - + + CANCEL + UPDATE + - UPDATE PACKAGE + Tango Update Package The selected file contains a software update package. Press 'UPDATE' to start updating your system. diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs index 0371e94da..c0654f643 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs @@ -10,6 +10,7 @@ using Tango.Core.Helpers; using Tango.Explorer; using Tango.PPC.Common; using Tango.PPC.Common.MachineUpdate; +using Tango.PPC.Common.Publish; using Tango.PPC.Common.Web; using Tango.PPC.UI.Dialogs; using Tango.PPC.UI.Notifications.NotificationItems; @@ -209,7 +210,7 @@ namespace Tango.PPC.UI.ViewModels try { - _update_result = await MachineUpdateManager.Update(MachineProvider.Machine.SerialNumber, _checkUpdateResponse.SetupFirmware, _checkUpdateResponse.SetupFPGA); + _update_result = await MachineUpdateManager.Update(_checkUpdateResponse.SetupFirmware, _checkUpdateResponse.SetupFPGA); LogManager.Log("Machine update completed."); await NavigateTo(MachineUpdateView.UpdateCompletedView); } @@ -248,15 +249,15 @@ namespace Tango.PPC.UI.ViewModels { LogManager.Log("Completing machine update..."); - if (!IsDbUpdate) + if (IsDbUpdate || !_update_result.RequiresBinariesUpdate) { - String updater_exe = Path.Combine(_update_result.UpdatePackagePath, "Tango.PPC.Updater.exe"); - ApplicationManager.UpdateApplication(updater_exe, PathHelper.GetStartupPath()); + LogManager.Log("Restarting Application..."); + ApplicationManager.Restart(); } else { - LogManager.Log("Restarting Application..."); - ApplicationManager.Restart(); + String updater_exe = Path.Combine(_update_result.UpdatePackagePath, "Tango.PPC.Updater.exe"); + ApplicationManager.UpdateApplication(updater_exe, PathHelper.GetStartupPath()); } } @@ -375,7 +376,7 @@ namespace Tango.PPC.UI.ViewModels private async void HandleSoftwareUpdatePackageLoaded(ExplorerFileItem fileItem) { - UpdatePackageFile packageFile = null; + PublishInfo packageFile = null; try { @@ -383,38 +384,33 @@ namespace Tango.PPC.UI.ViewModels } catch (Exception ex) { - LogManager.Log(ex, $"Error loading update package file from {fileItem.Path}."); + LogManager.Log(ex, $"Error loading publish info from {fileItem.Path}."); await NotificationProvider.ShowError("An error occurred while trying to load the selected software update package. Please make sure the package is valid."); return; } - if (ApplicationManager.Version <= packageFile.Version) - { - await NotificationProvider.ShowError($"The selected update package (v{packageFile.Version.ToString()}) contains an older software version."); - return; - } - UpdateFromFileViewVM vm = new UpdateFromFileViewVM(); - vm.Version = packageFile.Version.ToString(); + vm.Version = packageFile.ApplicationVersion; await NotificationProvider.ShowDialog(vm); if (vm.DialogResult) { await NavigationManager.NavigateTo(Common.Navigation.NavigationView.MachineUpdateView); - await NavigateTo(MachineUpdateView.UpdateFromPackageView); + await NavigateTo(MachineUpdateView.UpdateProgressView); LogManager.Log("Starting machine update from package..."); try { - _update_result = await MachineUpdateManager.UpdateFromTUP(fileItem.Path); + _update_result = await MachineUpdateManager.UpdateFromTUP(fileItem.Path, MachineProvider.Machine.SetupFirmware, MachineProvider.Machine.SetupFpga); LogManager.Log("Machine update from package completed."); await NavigateTo(MachineUpdateView.UpdateCompletedView); } catch (Exception ex) { LogManager.Log(ex, "Machine update from package failed."); + FailedError = ex.FlattenMessage(); await NavigateTo(MachineUpdateView.UpdateFailedFromPackageView); } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml index fba8a599d..beb09be0d 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml @@ -194,8 +194,9 @@ CLOSE - - An error occurred while trying to update the machine. + + Update Failed + diff --git a/Software/Visual_Studio/Tango.Core/DB/DbManager.cs b/Software/Visual_Studio/Tango.Core/DB/DbManager.cs index 1d415fdb1..8601d67a0 100644 --- a/Software/Visual_Studio/Tango.Core/DB/DbManager.cs +++ b/Software/Visual_Studio/Tango.Core/DB/DbManager.cs @@ -65,9 +65,15 @@ namespace Tango.Core.DB #region Public Methods - public void Create(String name) + public void Create(String name, String filePath = null) { String command = String.Format("CREATE DATABASE {0}", name); + + if (filePath != null) + { + command = $"CREATE DATABASE {name} ON (name='{name}', filename='{filePath}')"; + } + SqlCommand cmd = new SqlCommand(command, _connection); cmd.ExecuteNonQuery(); } @@ -160,6 +166,13 @@ namespace Tango.Core.DB SetOnline(name); } + public void RestoreAsNew(String name, String file, String dbFolder) + { + String command = $"RESTORE DATABASE {name} FROM DISK='{file}' WITH MOVE '{name}' TO '{Path.Combine(dbFolder, name)}.mdf', MOVE '{name}_log' TO '{Path.Combine(dbFolder, name)}.ldf'"; + SqlCommand cmd = new SqlCommand(command, _connection); + cmd.ExecuteNonQuery(); + } + public void ClearDb() { if (!_connection.ConnectionString.ToLower().Contains("initial catalog")) @@ -265,6 +278,24 @@ EXEC sp_executesql @statement return cred; } + public String GetValue(String query, String columnName) + { + string sql = query; + var cm = new SqlCommand(sql, _connection); + var dr = cm.ExecuteReader(); + if (dr.Read()) + { + var value = dr[columnName]; + + if (value != null) + { + return value.ToString(); + } + } + + return null; + } + #endregion #region IDisposable diff --git a/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs b/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs index 98a6c2efc..96b0a8525 100644 --- a/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs +++ b/Software/Visual_Studio/Tango.PMR/FirmwareUpgrade/VersionFileDescriptor.cs @@ -23,16 +23,15 @@ namespace Tango.PMR.FirmwareUpgrade { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChtWZXJzaW9uRmlsZURlc2NyaXB0b3IucHJvdG8SGVRhbmdvLlBNUi5GaXJt", - "d2FyZVVwZ3JhZGUaHFZlcnNpb25GaWxlRGVzdGluYXRpb24ucHJvdG8ilAEK", + "d2FyZVVwZ3JhZGUaHFZlcnNpb25GaWxlRGVzdGluYXRpb24ucHJvdG8iggEK", "FVZlcnNpb25GaWxlRGVzY3JpcHRvchIQCghGaWxlTmFtZRgBIAEoCRIPCgdW", "ZXJzaW9uGAIgASgJEkYKC0Rlc3RpbmF0aW9uGAMgASgOMjEuVGFuZ28uUE1S", - "LkZpcm13YXJlVXBncmFkZS5WZXJzaW9uRmlsZURlc3RpbmF0aW9uEhAKCENo", - "ZWNrU3VtGAQgASgMQiUKI2NvbS50d2luZS50YW5nby5wbXIuZmlybXdhcmV1", - "cGdyYWRlYgZwcm90bzM=")); + "LkZpcm13YXJlVXBncmFkZS5WZXJzaW9uRmlsZURlc3RpbmF0aW9uQiUKI2Nv", + "bS50d2luZS50YW5nby5wbXIuZmlybXdhcmV1cGdyYWRlYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Tango.PMR.FirmwareUpgrade.VersionFileDestinationReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor), global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor.Parser, new[]{ "FileName", "Version", "Destination", "CheckSum" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor), global::Tango.PMR.FirmwareUpgrade.VersionFileDescriptor.Parser, new[]{ "FileName", "Version", "Destination" }, null, null, null) })); } #endregion @@ -66,7 +65,6 @@ namespace Tango.PMR.FirmwareUpgrade { fileName_ = other.fileName_; version_ = other.version_; destination_ = other.destination_; - checkSum_ = other.checkSum_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -107,17 +105,6 @@ namespace Tango.PMR.FirmwareUpgrade { } } - /// Field number for the "CheckSum" field. - public const int CheckSumFieldNumber = 4; - private pb::ByteString checkSum_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString CheckSum { - get { return checkSum_; } - set { - checkSum_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as VersionFileDescriptor); @@ -134,7 +121,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (FileName != other.FileName) return false; if (Version != other.Version) return false; if (Destination != other.Destination) return false; - if (CheckSum != other.CheckSum) return false; return true; } @@ -144,7 +130,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (FileName.Length != 0) hash ^= FileName.GetHashCode(); if (Version.Length != 0) hash ^= Version.GetHashCode(); if (Destination != 0) hash ^= Destination.GetHashCode(); - if (CheckSum.Length != 0) hash ^= CheckSum.GetHashCode(); return hash; } @@ -167,10 +152,6 @@ namespace Tango.PMR.FirmwareUpgrade { output.WriteRawTag(24); output.WriteEnum((int) Destination); } - if (CheckSum.Length != 0) { - output.WriteRawTag(34); - output.WriteBytes(CheckSum); - } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -185,9 +166,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (Destination != 0) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Destination); } - if (CheckSum.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(CheckSum); - } return size; } @@ -205,9 +183,6 @@ namespace Tango.PMR.FirmwareUpgrade { if (other.Destination != 0) { Destination = other.Destination; } - if (other.CheckSum.Length != 0) { - CheckSum = other.CheckSum; - } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -230,10 +205,6 @@ namespace Tango.PMR.FirmwareUpgrade { destination_ = (global::Tango.PMR.FirmwareUpgrade.VersionFileDestination) input.ReadEnum(); break; } - case 34: { - CheckSum = input.ReadBytes(); - break; - } } } } diff --git a/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs b/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs index de146ead3..b9ee0cf7a 100644 --- a/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs +++ b/Software/Visual_Studio/Tango.SQLExaminer/ExaminerSequenceConfigurationRunner.cs @@ -24,6 +24,15 @@ namespace Tango.SQLExaminer public ExaminerSequenceConfiguration Configuration { get; private set; } + public ExaminerSequenceConfigurationRunner(ExaminerSequenceConfiguration sequenceConfiguration, String scriptsFolder, Core.DataSource source, Core.DataSource target, String machineSerialNumber) + { + ScriptsFolder = scriptsFolder; + Source = source; + Target = target; + MachineSerialNumber = machineSerialNumber; + Configuration = sequenceConfiguration; + } + public ExaminerSequenceConfigurationRunner(String sequenceFile, String scriptsFolder, Core.DataSource source, Core.DataSource target, String machineSerialNumber) { SequenceFile = sequenceFile; diff --git a/Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs b/Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs new file mode 100644 index 000000000..09a830ab3 --- /dev/null +++ b/Software/Visual_Studio/Tango.SQLExaminer/ExtensionMethods.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.SQLExaminer; + +public static class ExtensionMethods +{ + public static String GetFilePath(this ExaminerConfigurationType type) + { + return Path.Combine(Helper.SQL_EXAMINER_CONFIG_FOLDER, type.ToString() + ".xml"); + } + + public static String GetFileName(this ExaminerConfigurationType type) + { + return type.ToString() + ".xml"; + } +} + diff --git a/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs b/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs index 5eb09b98c..3b4e238a7 100644 --- a/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs +++ b/Software/Visual_Studio/Tango.SQLExaminer/Helper.cs @@ -8,7 +8,7 @@ using Tango.Core.Helpers; namespace Tango.SQLExaminer { - internal static class Helper + public static class Helper { public static String SQL_EXAMINER_FOLDER = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "SQLExaminer"); public static String SQL_EXAMINER_CONFIG_FOLDER = Path.Combine(SQL_EXAMINER_FOLDER, "Configurations"); diff --git a/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj b/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj index b71a30dc0..17dcb1b22 100644 --- a/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj +++ b/Software/Visual_Studio/Tango.SQLExaminer/Tango.SQLExaminer.csproj @@ -69,6 +69,7 @@ + diff --git a/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs index 9b0385c23..e3e49ac5e 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs +++ b/Software/Visual_Studio/Tango.UnitTesting/SQLExaminer/SQLExaminer_TST.cs @@ -391,5 +391,76 @@ namespace Tango.UnitTesting.SQLExaminer //Should have no differences! Assert.IsFalse(data_report.HasDifferences); } + + [TestMethod] + public void Perform_Machine_Update_From_Backup() + { + String tempDbName = "Tango_TUP"; + + var source_db = GetSource("Tango"); + var target_db = GetSource(tempDbName); + + DbManager dbManager = DbManager.FromDataSource(source_db); + + //Create the backup for the tup file. + dbManager.Create(tempDbName); + + var configuration = GetFullConfiguration(); + + ExaminerSequenceConfigurationRunner runner = + new ExaminerSequenceConfigurationRunner( + configuration, + Tango.SQLExaminer.Helper.SQL_EXAMINER_CONFIG_FOLDER, + source_db, + target_db, + "1111"); + + runner.Run().GetAwaiter().GetResult(); + + String backupFile = "C:\\DB_Backups\\Tango_TEMP.bak"; + + dbManager.Backup(tempDbName, backupFile); + dbManager.SetOffline(tempDbName); + dbManager.SetOnline(tempDbName); + dbManager.Delete(tempDbName); + + //Now restore as different name + dbManager.RestoreAsNew(tempDbName, backupFile, "C:\\DB_Backups"); + } + + private ExaminerSequenceConfiguration GetFullConfiguration() + { + ExaminerSequenceConfiguration configuration = new ExaminerSequenceConfiguration(); + + configuration.Items.Add(new ExaminerSequenceItem() + { + Type = ExaminerSequenceItemType.Schema, + Direction = ExaminerSequenceItemDirection.SourceToTarget, + FileName = ExaminerConfigurationType.Schema.GetFileName(), + Index = 0, + Name = "Updating Schema", + }); + + configuration.Items.Add(new ExaminerSequenceItem() + { + Type = ExaminerSequenceItemType.Data, + Direction = ExaminerSequenceItemDirection.SourceToTarget, + FileName = ExaminerConfigurationType.OverrideData.GetFileName(), + Index = 1, + Name = "Updating Collections", + }); + + configuration.Items.Add(new ExaminerSequenceItem() + { + Type = ExaminerSequenceItemType.Data, + Direction = ExaminerSequenceItemDirection.SourceToTarget, + FileName = ExaminerConfigurationType.ProvisionMachine.GetFileName(), + Index = 2, + Name = "Configuring Machine", + RequiresSerialNumber = true, + }); + + return configuration; + } } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs index 2eeaa6e0e..378fc3eea 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs @@ -23,6 +23,10 @@ using Tango.Web.ActiveDirectory; using Tango.MachineService.Filters; using Tango.MachineService.Security; using Tango.Web.SQLServer; +using Tango.Core; +using Tango.Web.SMO; +using Tango.Core.DB; +using System.Threading.Tasks; namespace Tango.MachineService.Controllers { @@ -425,6 +429,67 @@ namespace Tango.MachineService.Controllers }; } + [HttpPost] + [JwtTokenFilter] + public DownloadLatestPPCVersionResponse DownloadLatestPPCVersion(DownloadLatestPPCVersionRequest request) + { + DownloadLatestPPCVersionResponse response = new DownloadLatestPPCVersionResponse(); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == request.SerialNumber); + + if (machine == null) + { + throw new AuthenticationException("The specified serial number could not be found."); + } + + var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid); + + var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + + response.Version = latest_machine_version.Version; + + var manager = new BlobStorageManager(); + var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); + var blob = container.GetBlockBlobReference(latest_machine_version.BlobName); + + response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60)); + + if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT)) + { + response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath; + } + + DbCredentials credentials = new DbCredentials(); + + using (SmoManager smo = new SmoManager()) + { + credentials = smo.CreateRandomLoginAndUser(); + + Task.Delay(TimeSpan.FromMinutes(PPCController.SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) => + { + using (SmoManager m = new SmoManager()) + { + m.DeleteLoginAndUser(credentials.UserName); + } + }); + } + + response.DataSource = new DataSource() + { + Address = MachineServiceConfig.DB_ADDRESS, + Catalog = MachineServiceConfig.DB_CATALOG, + UserName = credentials.UserName, + Password = credentials.Password, + IntegratedSecurity = false, + Type = DataSourceType.SQLServer, + }; + } + + return response; + } + #endregion } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 2dee09e69..0d9a2993b 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -32,7 +32,7 @@ namespace Tango.MachineService.Controllers private static List _pendingUploads; private static List _pendingUpdates; private ActiveDirectoryManager _ad_manager; - private const int SQL_TEMP_CREDENTIALS_EXP_MINUTS = 20; + public const int SQL_TEMP_CREDENTIALS_EXP_MINUTS = 20; public class TokenObject { -- cgit v1.3.1 From 5cb75f4b026a7842171369f58f5aba1c9678f60f Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Fri, 20 Dec 2019 17:47:51 +0200 Subject: Added error message for when external bridge failed due to udp port is already used. Implemented flexo font on mahcine studio. Added module title/image on MS. Updated some machine icons on MS. --- Software/Graphics/machine_new.png | Bin 0 -> 43275 bytes .../Fonts/Flexo-Black.otf | Bin 0 -> 112924 bytes .../Fonts/Flexo-BlackIt.otf | Bin 0 -> 121948 bytes .../Fonts/Flexo-Bold.otf | Bin 0 -> 112436 bytes .../Fonts/Flexo-BoldIt.otf | Bin 0 -> 121352 bytes .../Fonts/Flexo-Demi.otf | Bin 0 -> 112936 bytes .../Fonts/Flexo-DemiIt.otf | Bin 0 -> 122096 bytes .../Fonts/Flexo-Heavy.otf | Bin 0 -> 112632 bytes .../Fonts/Flexo-HeavyIt.otf | Bin 0 -> 122220 bytes .../Tango.MachineStudio.Common/Fonts/Flexo-It.otf | Bin 0 -> 120816 bytes .../Fonts/Flexo-Light.otf | Bin 0 -> 112116 bytes .../Fonts/Flexo-LightIt.otf | Bin 0 -> 120472 bytes .../Fonts/Flexo-Medium.otf | Bin 0 -> 112016 bytes .../Fonts/Flexo-MediumIt.otf | Bin 0 -> 121092 bytes .../Fonts/Flexo-Regular.otf | Bin 0 -> 111924 bytes .../Fonts/Flexo-Thin.otf | Bin 0 -> 112040 bytes .../Fonts/Flexo-ThinIt.otf | Bin 0 -> 120108 bytes .../Images/machine_new.png | Bin 0 -> 43275 bytes .../Images/machine_new_small.png | Bin 0 -> 16963 bytes .../Resources/MaterialDesign.xaml | 13 +++- .../Tango.MachineStudio.Common.csproj | 25 +++++++- .../Tango.MachineStudio.UI/MainWindow.xaml | 2 +- .../Notifications/DialogWindow.xaml | 2 +- .../Notifications/MessageBoxWindow.xaml | 2 +- .../Notifications/TextInputBoxWindow.xaml | 2 +- .../Tango.MachineStudio.UI.csproj | 5 +- .../ViewModels/MachineConnectionViewVM.cs | 3 + .../ViewModels/MainViewVM.cs | 14 +++-- .../Tango.MachineStudio.UI/Views/AboutView.xaml | 2 +- .../Views/ConnectionLostView.xaml | 2 +- .../Tango.MachineStudio.UI/Views/LoadingView.xaml | 2 +- .../Tango.MachineStudio.UI/Views/LoginView.xaml | 2 +- .../Views/MachineConnectionView.xaml | 2 +- .../Views/MachineLoginView.xaml | 2 +- .../Views/MachineSerialView.xaml | 2 +- .../Tango.MachineStudio.UI/Views/MainView.xaml | 69 +++++++++++++++++++-- .../Tango.MachineStudio.UI/Views/ShutdownView.xaml | 2 +- .../Windows/ExceptionWindow.xaml | 2 +- .../Windows/ModuleWindow.xaml | 14 ++++- .../Windows/ModuleWindow.xaml.cs | 9 +++ .../Tango.MachineStudio.UI/machine_new_small.ico | Bin 0 -> 132825 bytes .../ExternalBridge/ExternalBridgeScanner.cs | 6 +- 42 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 Software/Graphics/machine_new.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj') diff --git a/Software/Graphics/machine_new.png b/Software/Graphics/machine_new.png new file mode 100644 index 000000000..116e1e9c7 Binary files /dev/null and b/Software/Graphics/machine_new.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf new file mode 100644 index 000000000..0341d05db Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf new file mode 100644 index 000000000..e0823abdf Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf new file mode 100644 index 000000000..2b9144e5c Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf new file mode 100644 index 000000000..f21ed044d Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf new file mode 100644 index 000000000..ada716012 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf new file mode 100644 index 000000000..ab9a133a5 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf new file mode 100644 index 000000000..b3630c982 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf new file mode 100644 index 000000000..e47f75546 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf new file mode 100644 index 000000000..6f9b5fa49 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf new file mode 100644 index 000000000..27af39094 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf new file mode 100644 index 000000000..89085eeca Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf new file mode 100644 index 000000000..04b2a8853 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf new file mode 100644 index 000000000..91996979e Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf new file mode 100644 index 000000000..2703ba3f3 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf new file mode 100644 index 000000000..666c69931 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf new file mode 100644 index 000000000..b039daffe Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png new file mode 100644 index 000000000..116e1e9c7 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png new file mode 100644 index 000000000..378879ce1 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml index 177a4fe75..37e35b1ab 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml @@ -63,6 +63,13 @@ ../Fonts/#digital-7 + ../Fonts/#flexo + + + + + + @@ -526,7 +533,7 @@ - + @@ -774,6 +781,10 @@ + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 3ce667afe..5e874add1 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -127,6 +127,22 @@ + + + + + + + + + + + + + + + + @@ -401,11 +417,16 @@ - + + + + + + - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml index a76749b05..054d7b9d8 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml @@ -8,7 +8,7 @@ xmlns:views="clr-namespace:Tango.MachineStudio.UI.Views" xmlns:sharedControls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="Tango" Height="800" Width="1280" Foreground="{StaticResource MainWindow.Foreground}" + Title="Tango" Height="800" Width="1280" Foreground="{StaticResource MainWindow.Foreground}" FontFamily="{StaticResource flexo}" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}" Background="{DynamicResource MainWindow.Background}" WindowTitleBrush="{StaticResource MainWindow.WindowTitleColorBrush}"> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml index 41405f7fb..939adf5d5 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml @@ -7,7 +7,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Windows" mc:Ignorable="d" - Title="Machine Studio" MinHeight="220" SizeToContent="WidthAndHeight" MinWidth="600" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False"> + Title="Machine Studio" MinHeight="220" SizeToContent="WidthAndHeight" MinWidth="600" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml index 988e3c21f..888f49d3f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml @@ -8,7 +8,7 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False"> + Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml index a43fafb46..7d888d784 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml @@ -8,7 +8,7 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False"> + Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index d5084d051..1762205ad 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -36,7 +36,7 @@ 4 - machine.ico + machine_new_small.ico @@ -363,6 +363,7 @@ TCC\template.bmp Always + @@ -674,7 +675,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs index d1f3cc69e..0ea47c24a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core.Commands; +using Tango.Core.DI; using Tango.Emulations.ExternalBridge; using Tango.Integration.ExternalBridge; using Tango.MachineStudio.Common; @@ -108,6 +109,8 @@ namespace Tango.MachineStudio.UI.ViewModels catch (Exception ex) { LogManager.Log(ex, "Error starting external bridge scanner."); + Cancel(); + TangoIOC.Default.GetInstance().ShowError($"There is a problem with machine scanning.\n{ex.FlattenMessage()}"); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs index c7fd7a525..a7397835b 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs @@ -668,7 +668,7 @@ namespace Tango.MachineStudio.UI.ViewModels /// Starts the specified module. /// /// The module. - internal void StartModule(IStudioModule module) + internal async void StartModule(IStudioModule module) { IsMenuOpened = false; @@ -693,10 +693,9 @@ namespace Tango.MachineStudio.UI.ViewModels m.IsLoaded = false; } - CurrentModule = module; - if (module != null) { + CurrentModule = module; CurrentModule.IsLoaded = true; IsModuleLoaded = true; @@ -707,7 +706,10 @@ namespace Tango.MachineStudio.UI.ViewModels { IsModuleLoaded = false; LogManager.Log(String.Format("Navigating to Home...")); - (MainView.Self as MainView).NavigationControl.NavigateTo("Home"); + (MainView.Self as MainView).NavigationControl.NavigateTo("Home",() => + { + CurrentModule = module; + }); } } @@ -715,7 +717,7 @@ namespace Tango.MachineStudio.UI.ViewModels /// Opens the module in a new window. /// /// The module. - private void OpenModuleInWindow(IStudioModule module, Rect? bounds = null, WindowState? state = null) + private async void OpenModuleInWindow(IStudioModule module, Rect? bounds = null, WindowState? state = null) { if (module == null) return; @@ -725,6 +727,8 @@ namespace Tango.MachineStudio.UI.ViewModels StartModule(null); + await Task.Delay(1000); + LogManager.Log(String.Format("Starting module '{0}' in new window...", module.Name)); if (!(MainView.Self as MainView).NavigationControl.Elements.ToList().Exists(x => x.GetType() == module.MainViewType)) diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml index f7e90d4f5..82d628785 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml @@ -28,7 +28,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml index b2fa2b3e3..28937a438 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml @@ -18,7 +18,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml index df1c1b831..14fcc3a37 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml @@ -16,7 +16,7 @@ - + Machine Studio diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml index ec6091988..d93dbc127 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml @@ -42,7 +42,7 @@ - + Machine Studio diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml index 69ce4c855..581e87ed6 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml @@ -27,7 +27,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml index 7d0b2e25c..5be9ba089 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml @@ -29,7 +29,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml index eea90c7b9..2393ab6e7 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml @@ -23,7 +23,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index d427be9e5..3f1164526 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -231,10 +231,71 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml index cc1060b2a..6bda3fe2d 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml @@ -10,7 +10,7 @@ - + Machine Studio diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml index 25fe4af5d..6b80fad43 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Windows" mc:Ignorable="d" - WindowStyle="None" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Width="800" Height="600" Background="Transparent" d:DataContext="{d:DesignInstance Type=local:ExceptionWindow, IsDesignTimeCreatable=False}"> + WindowStyle="None" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Width="800" Height="600" Background="Transparent" d:DataContext="{d:DesignInstance Type=local:ExceptionWindow, IsDesignTimeCreatable=False}" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml index 47b36070a..5db0277cc 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml @@ -10,7 +10,7 @@ xmlns:views="clr-namespace:Tango.MachineStudio.UI.Views" xmlns:sharedControls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="{Binding RelativeSource={RelativeSource Self},Path=ModuleContext.Module.Name}" Height="800" Width="1280" WindowStartupLocation="CenterOwner" WindowState="Maximized" Foreground="#494949" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}"> + Title="Machine Studio" Height="800" Width="1280" WindowStartupLocation="CenterOwner" WindowState="Maximized" Foreground="#494949" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}" FontFamily="{StaticResource flexo}"> @@ -29,8 +29,16 @@ - - + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs index 7ca062645..cfea78964 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs @@ -12,6 +12,8 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Tango.Core.DI; +using Tango.MachineStudio.Common.StudioApplication; using Tango.MachineStudio.UI.ViewModels; namespace Tango.MachineStudio.UI.Windows @@ -32,6 +34,13 @@ namespace Tango.MachineStudio.UI.Windows public ModuleWindow() { InitializeComponent(); + + ContentRendered += ModuleWindow_ContentRendered; + } + + private void ModuleWindow_ContentRendered(object sender, EventArgs e) + { + Title = "MACHINE STUDIO " + TangoIOC.Default.GetInstance().Version.ToString(3); } public ModuleWindow(MainViewVM mainViewVM, ModuleWindowVM moduleVM, FrameworkElement view) : this() diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico new file mode 100644 index 000000000..dd159c221 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico differ diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs index b84942643..e20b12d1a 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs @@ -60,7 +60,6 @@ namespace Tango.Integration.ExternalBridge public ExternalBridgeScanner() { _settings = SettingsManager.Default.GetOrCreate(); - _server = new UdpClient(_settings.ExternalBridgeServiceDiscoveryPort); AvailableMachines = new SynchronizedObservableCollection(); } @@ -73,6 +72,11 @@ namespace Tango.Integration.ExternalBridge { LogManager.Log("External bridge scanner started..."); + if (_server == null) + { + _server = new UdpClient(_settings.ExternalBridgeServiceDiscoveryPort); + } + IsStarted = true; foreach (var machine in AvailableMachines.OfType().ToList()) -- cgit v1.3.1 From b9c104e259ca24d2ae7ca82387209779fefddd34 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sun, 19 Jan 2020 00:30:23 +0200 Subject: Implemented machine studio connection via access token WORKING!. Implemented machine studio login method selection. --- ...go.MachineStudio.Storage_yjpbed13_wpftmp.csproj | 154 ++++++++++++++++++ .../Authentication/IAuthenticationProvider.cs | 2 +- .../MachineStudioSettings.cs | 6 + .../Tango.MachineStudio.Common.csproj | 3 +- .../Tango.MachineStudio.Common/Web/LoginMethod.cs | 17 ++ .../Tango.MachineStudio.Common/Web/LoginRequest.cs | 1 + .../DefaultAuthenticationProvider.cs | 3 +- .../Images/active_directory.png | Bin 0 -> 15300 bytes .../Tango.MachineStudio.UI/Images/login.png | Bin 0 -> 6401 bytes .../Images/machinestudio_login.png | Bin 0 -> 21788 bytes .../Tango.MachineStudio.UI.csproj | 5 +- .../ViewModels/LoginViewVM.cs | 29 +++- .../Tango.MachineStudio.UI/Views/LoginView.xaml | 76 ++++++--- .../Tango.MachineStudio.UI/Views/MainView.xaml | 2 +- .../Tango.BL/ObservablesContextExtension.cs | 24 ++- .../Tango.Web/SQLServer/SQLServerManager.cs | 1 + .../Controllers/MachineStudioController.cs | 181 ++++++++++++--------- 17 files changed, 395 insertions(+), 109 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage_yjpbed13_wpftmp.csproj create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginMethod.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/active_directory.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/machinestudio_login.png (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage_yjpbed13_wpftmp.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage_yjpbed13_wpftmp.csproj new file mode 100644 index 000000000..698c6fe82 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage_yjpbed13_wpftmp.csproj @@ -0,0 +1,154 @@ + + + + + Debug + AnyCPU + {5991F6B5-EA4E-41E9-A4F6-7D3A50010FD6} + library + Tango.MachineStudio.Storage + Tango.MachineStudio.Storage + v4.6.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + true + full + false + ..\..\..\Build\Machine Studio\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\..\Build\Machine Studio\Release\ + TRACE + prompt + 4 + + + + + + GlobalVersionInfo.cs + + + + + + + + + + MainView.xaml + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + {f441feee-322a-4943-b566-110e12fd3b72} + Tango.BL + + + {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} + Tango.Core + + + {4206ac58-3b57-4699-8835-90bf6db01a61} + Tango.Integration + + + {bc932dbd-7cdb-488c-99e4-f02cf441f55e} + Tango.Logging + + + {8491d07b-c1f6-4b62-a412-41b9fd2d6538} + Tango.SharedUI + + + {74e700b0-1156-4126-be40-ee450d3c3026} + Tango.Transport + + + {43135fb9-41db-4f87-9771-cf2c762027c0} + Tango.FirmwarePackageGenerator + + + {cb0b0aa2-bb24-4bca-a720-45e397684e12} + Tango.MachineStudio.Common + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs index 74969fd27..cb231fa05 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs @@ -29,7 +29,7 @@ namespace Tango.MachineStudio.Common.Authentication /// The email. /// The password. /// - AuthenticationLoginResult Login(String email, String password, bool bypassVersionCheck = false); + AuthenticationLoginResult Login(String email, String password, LoginMethod method, bool bypassVersionCheck = false); /// /// Logs-out the current logged-in user. diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs index 6ab26028f..91eaa857d 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs @@ -8,6 +8,7 @@ using System.Windows; using Tango.BL; using Tango.Integration.Operation; using Tango.Logging; +using Tango.MachineStudio.Common.Web; using Tango.PMR.Printing; using Tango.Settings; using Tango.Web; @@ -39,6 +40,11 @@ namespace Tango.MachineStudio.Common /// public String LastLoginPassword { get; set; } + /// + /// Gets or sets the last login method. + /// + public LoginMethod LastLoginMethod { get; set; } + /// /// Gets or sets a value indicating whether to save the user credentials. /// diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 5e874add1..2df984c7c 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -105,6 +105,7 @@ + @@ -426,7 +427,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginMethod.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginMethod.cs new file mode 100644 index 000000000..83f1c0850 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginMethod.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Common.Web +{ + public enum LoginMethod + { + [Description("Active Directory")] + ActiveDirectory, + [Description("Standard User")] + StandardUser, + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginRequest.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginRequest.cs index 577f5e208..1727a2c6e 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginRequest.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginRequest.cs @@ -12,5 +12,6 @@ namespace Tango.MachineStudio.Common.Web public String Version { get; set; } public String Email { get; set; } public String Password { get; set; } + public LoginMethod Method { get; set; } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs index c992d0768..209b26505 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs @@ -90,7 +90,7 @@ namespace Tango.MachineStudio.UI.Authentication /// The password. /// /// Login failed for user " + email - public AuthenticationLoginResult Login(string email, string password, bool bypassVersionCheck = false) + public AuthenticationLoginResult Login(string email, string password, LoginMethod method, bool bypassVersionCheck = false) { _refreshTokenTimer.Stop(); @@ -118,6 +118,7 @@ namespace Tango.MachineStudio.UI.Authentication Email = email, Password = password, Version = appVersion, + Method = method, }).Result; } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/active_directory.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/active_directory.png new file mode 100644 index 000000000..4cced33e0 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/active_directory.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login.png new file mode 100644 index 000000000..9f7d0b9ba Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/machinestudio_login.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/machinestudio_login.png new file mode 100644 index 000000000..98f1b286a Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/machinestudio_login.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 565489f0b..efe8fc6b1 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -363,6 +363,9 @@ TCC\template.bmp Always + + + @@ -676,7 +679,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs index cf34764d9..9c2367f93 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs @@ -102,6 +102,21 @@ namespace Tango.MachineStudio.UI.ViewModels set { _enableSlotSelection = value; RaisePropertyChangedAuto(); } } + private bool _isActiveDirectory; + public bool IsActiveDirectory + { + get { return _isActiveDirectory; } + set { _isActiveDirectory = value; RaisePropertyChangedAuto(); if (value) IsStandardUser = false; } + } + + private bool _isStandardUser; + public bool IsStandardUser + { + get { return _isStandardUser; } + set { _isStandardUser = value; RaisePropertyChangedAuto(); if (value) IsActiveDirectory = false; } + } + + /// /// Gets or sets the login command. @@ -131,6 +146,15 @@ namespace Tango.MachineStudio.UI.ViewModels Email = _settings.LastLoginEmail; DeploymentSlot = _settings.DeploymentSlot; RememberMe = _settings.RememberMe; + + if (_settings.LastLoginMethod == LoginMethod.ActiveDirectory) + { + IsActiveDirectory = true; + } + else + { + IsStandardUser = true; + } try { @@ -154,11 +178,13 @@ namespace Tango.MachineStudio.UI.ViewModels IsLogging = true; InvalidateRelayCommands(); + LoginMethod loginMethod = IsActiveDirectory ? LoginMethod.ActiveDirectory : LoginMethod.StandardUser; + await Task.Factory.StartNew(() => { _settings.DeploymentSlot = DeploymentSlot; - LoginResponse result = _authenticationProvider.Login(Email, Password, _settings.ByPassEnvironmentVersionCheck).Response; + LoginResponse result = _authenticationProvider.Login(Email, Password, loginMethod, _settings.ByPassEnvironmentVersionCheck).Response; if (result.VersionChangeRequired && !_settings.ByPassEnvironmentVersionCheck) { @@ -183,6 +209,7 @@ namespace Tango.MachineStudio.UI.ViewModels _settings.LastLoginEmail = Email; _settings.RememberMe = RememberMe; + _settings.LastLoginMethod = loginMethod; _settings.LastLoginPassword = RememberMe ? cryptographer.Encrypt(Password) : null; _settings.Save(); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml index d93dbc127..e7428dd28 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml @@ -45,35 +45,57 @@ Machine Studio - - + + + + + + + + + + - - - Login to your account - - - - - - - - - - - - - - Environment selection requires restarting the application - Remember me - + - - - Logging you in... - - - + + + Login to your account + + + + + + + + + + + + + + + + + + Environment selection requires restarting the application + Remember me + + + + + Logging you in... + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 020343ba0..48f7b46d3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -55,7 +55,7 @@ IsChecked="{Binding Source={x:Reference MenuToggleButton}, Path=IsChecked, Mode=TwoWay}" /> - + diff --git a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs index 263574f68..3d330b797 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Data.Entity; using System.Data.Entity.Core.Objects; using System.Data.Entity.Infrastructure; +using System.Data.SqlClient; using System.Data.SQLite; using System.IO; using System.Linq; @@ -25,18 +26,27 @@ namespace Tango.BL private ObservablesContextAdapter _adapter; private static DataSource _override_datasource; private DataSource _dataSource; + private static List _open_contexts; /// /// Gets a value indicating whether this instance is disposed. /// public bool IsDisposed { get; private set; } + /// + /// Initializes the class. + /// + static ObservablesContext() + { + _open_contexts = new List(); + } + /// /// Initializes a new instance of the class. /// public ObservablesContext() { - + _open_contexts.Add(this); } /// @@ -46,6 +56,7 @@ namespace Tango.BL /// if set to true will try to connect to an .mdf file. public ObservablesContext(DataSource dataSource) : base(dataSource.ToConnection(), true) { + _open_contexts.Add(this); _dataSource = dataSource; Database.SetInitializer(null); Configuration.LazyLoadingEnabled = false; @@ -286,6 +297,7 @@ namespace Tango.BL /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { + _open_contexts.Remove(this); base.Dispose(disposing); IsDisposed = true; } @@ -296,6 +308,16 @@ namespace Tango.BL { _override_datasource.AccessToken = accessToken; _override_datasource.AccessTokenExpiration = expiration; + + foreach (var context in _open_contexts.Where(x => x._dataSource.Type == DataSourceType.AccessToken)) + { + context._dataSource = _override_datasource; + var connection = context.Database.Connection as SqlConnection; + if (connection != null) + { + connection.AccessToken = context._dataSource.AccessToken; + } + } } } } diff --git a/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs b/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs index ce83d387c..8bc84f7b5 100644 --- a/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs +++ b/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs @@ -15,6 +15,7 @@ namespace Tango.Web.SQLServer public AuthenticationResult GetAccessToken() { var authContext = new AuthenticationContext(_service_root); + authContext.TokenCache.Clear(); ClientCredential clientCredentials = new ClientCredential(WebConfig.CLIENT_ID, WebConfig.APP_SECRET); AuthenticationResult authResult = authContext.AcquireTokenAsync("https://database.windows.net/", clientCredentials).Result; return authResult; diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs index da5ce16f7..0fd116361 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs @@ -286,20 +286,9 @@ namespace Tango.MachineService.Controllers public LoginResponse Login(LoginRequest request) { AuthenticationResult authResult = null; - - try - { - authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); - } - catch (Exception ex) - { - throw new AuthenticationException(ex.FlattenMessage()); - } - - if (!_ad_manager.CanUserAccessCurrentEnvironment(request.Email)) - { - throw new AuthenticationException($"You do not have permissions to access the {MachineServiceConfig.DEPLOYMENT_SLOT.ToDescription()} environment."); - } + User user = null; + DataSource dataSource = null; + IHashGenerator hash = new BasicHashGenerator(); Version client_version; @@ -310,84 +299,122 @@ namespace Tango.MachineService.Controllers bool versionChangeRequired = false; String requiredVersion = null; + bool isPasswordOK = false; - User user = null; - - using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + try { - db.Roles.ToList(); - db.Permissions.ToList(); - db.UsersRoles.ToList(); - db.RolesPermissions.ToList(); + authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); + isPasswordOK = true; + } + catch {} - user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower()).WithRolesAndPermissions().WithDeleted().Build(); + //Login via Active Directory + if (request.Method == LoginMethod.ActiveDirectory) + { + try + { + authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); + } + catch (Exception ex) + { + throw new AuthenticationException(ex.FlattenMessage()); + } - IHashGenerator g = new BasicHashGenerator(); + if (!_ad_manager.CanUserAccessCurrentEnvironment(request.Email)) + { + throw new AuthenticationException($"You do not have permissions to access the {MachineServiceConfig.DEPLOYMENT_SLOT.ToDescription()} environment."); + } - if (user == null) + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { - //Than add the user !! - User new_user = new User(); - new_user.Email = request.Email; - new_user.Password = g.Encrypt(request.Password); - new_user.Organization = db.Organizations.Include(x => x.Address).Single(x => x.Name == "Twine"); - new_user.Address = new_user.Organization.Address.Clone(); - new_user.Contact = new Contact() - { - FirstName = authResult.UserInfo.GivenName, - LastName = authResult.UserInfo.FamilyName, - FullName = authResult.UserInfo.GivenName + " " + authResult.UserInfo.FamilyName, - Email = request.Email, - }; + db.Roles.ToList(); + db.Permissions.ToList(); + db.UsersRoles.ToList(); + db.RolesPermissions.ToList(); - db.UsersRoles.Add(new UsersRole() - { - User = new_user, - Role = db.Roles.Single(x => (Roles)x.Code == Roles.User), - }); + user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower()).WithRolesAndPermissions().WithDeleted().Build(); - db.UsersRoles.Add(new UsersRole() + if (user == null) { - User = new_user, - Role = db.Roles.Single(x => (Roles)x.Code == Roles.MachineStudioUser), - }); + user = new User(); + user.Email = request.Email; + user.Password = hash.Encrypt(request.Password); + user.Organization = db.Organizations.Include(x => x.Address).Single(x => x.Name == "Twine"); + user.Address = user.Organization.Address.Clone(); + user.Contact = new Contact() + { + FirstName = authResult.UserInfo.GivenName, + LastName = authResult.UserInfo.FamilyName, + FullName = authResult.UserInfo.GivenName + " " + authResult.UserInfo.FamilyName, + Email = request.Email, + }; - new_user.LastLogin = DateTime.UtcNow; - db.Users.Add(new_user); - } - else - { - if (user.Deleted) + db.UsersRoles.Add(new UsersRole() + { + User = user, + Role = db.Roles.Single(x => (Roles)x.Code == Roles.User), + }); + + db.UsersRoles.Add(new UsersRole() + { + User = user, + Role = db.Roles.Single(x => (Roles)x.Code == Roles.MachineStudioUser), + }); + + user.Password = hash.Encrypt(request.Password); + + db.Users.Add(user); + } + else { - throw new AuthenticationException("Your account has been disabled. Please contact your administrator."); + if (user.Deleted) + { + throw new AuthenticationException("Your account has been disabled. Please contact your administrator."); + } } user.LastLogin = DateTime.UtcNow; - user.Password = g.Encrypt(request.Password); + + db.SaveChanges(); } - db.SaveChanges(); + dataSource = new DataSource() + { + Address = MachineServiceConfig.DB_ADDRESS, + Catalog = MachineServiceConfig.DB_CATALOG, + Type = Core.DataSourceType.Azure, + IntegratedSecurity = false, + UserName = request.Email, + Password = request.Password, + }; + } + //Login via Database standard user + else + { + var password = hash.Encrypt(request.Password); - if (MachineServiceConfig.ENFORCE_MACHINE_STUDIO_VERSION) + using (var db = ObservablesContextHelper.CreateContext()) { - var latest_version = db.MachineStudioVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower() && (isPasswordOK || x.Password == password)).WithRolesAndPermissions().WithDeleted().Build(); - if (latest_version != null && Version.Parse(latest_version.Version) != client_version) + if (user == null) { - versionChangeRequired = true; - requiredVersion = latest_version.Version; + throw new AuthenticationException("Invalid email or password."); } - } - } - Core.DataSource dataSource = null; + if (user.Deleted) + { + throw new AuthenticationException("Your account has been disabled. Please contact your administrator."); + } + + user.LastLogin = DateTime.UtcNow; + db.SaveChanges(); + } - if (MachineServiceConfig.USE_DB_ACCESS_TOKENS) - { SQLServerManager sqlServer = new SQLServerManager(); var accessToken = sqlServer.GetAccessToken(); - dataSource = new Core.DataSource() + dataSource = new DataSource() { Address = MachineServiceConfig.DB_ADDRESS, Catalog = MachineServiceConfig.DB_CATALOG, @@ -397,19 +424,23 @@ namespace Tango.MachineService.Controllers AccessTokenExpiration = accessToken.ExpiresOn.UtcDateTime }; } - else + + //Enforce Machine Studio Version ? + if (MachineServiceConfig.ENFORCE_MACHINE_STUDIO_VERSION) { - dataSource = new Core.DataSource() + using (var db = ObservablesContextHelper.CreateContext()) { - Address = MachineServiceConfig.DB_ADDRESS, - Catalog = MachineServiceConfig.DB_CATALOG, - Type = Core.DataSourceType.Azure, - IntegratedSecurity = false, - UserName = request.Email, - Password = request.Password, - }; + var latest_version = db.MachineStudioVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + + if (latest_version != null && Version.Parse(latest_version.Version) != client_version) + { + versionChangeRequired = true; + requiredVersion = latest_version.Version; + } + } } + //Return data source return new LoginResponse() { DataSource = dataSource, -- cgit v1.3.1