From 8336c907a3084b7333e27da3a2ea601dfc4258f2 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Thu, 30 Apr 2020 20:17:10 +0300 Subject: FSE automatic update checks. --- .../Controllers/FSEController.cs | 65 +++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) (limited to 'Software/Visual_Studio/Web/Tango.MachineService/Controllers') diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs index bb3ef588f..7bf420df9 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs @@ -20,22 +20,17 @@ using Tango.Web.Security; using Tango.Web.SMO; using Tango.Web.SQLServer; using Tango.Web.Storage; +using static Tango.MachineService.Controllers.FSEController; namespace Tango.MachineService.Controllers { - public class FSEController : TangoController + public class FSEController : TangoController { public class TokenObject { public String UserGuid { get; set; } } - /// - /// Login to the service. - /// - /// The request. - /// - /// [HttpPost] public LoginResponse Login(LoginRequest request) { @@ -179,5 +174,61 @@ namespace Tango.MachineService.Controllers return response; } + + [HttpPost] + [JwtTokenFilter] + public CheckForUpdatesResponse CheckForUpdates(CheckForUpdatesRequest request) + { + CheckForUpdatesResponse response = new CheckForUpdatesResponse(); + + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + var versions = db.FseVersions.ToList(); + + FseVersion latestVersion = null; + + latestVersion = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + + Version currentVersion = Version.Parse(request.Version); + + String comments = String.Join(Environment.NewLine, versions.OrderBy(x => Version.Parse(x.Version)).Where(x => Version.Parse(x.Version) > currentVersion).Select(x => x.Comments)); + + if (latestVersion != null && Version.Parse(latestVersion.Version) != currentVersion) + { + var manager = new BlobStorageManager(); + var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER); + //var blob = container.GetBlockBlobReference(latestVersion.BlobName); + var installerBlob = container.GetBlockBlobReference(latestVersion.InstallerBlobName); + + //response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60)); + + if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT)) + { + //response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath; + response.InstallerCdnAddress = MachineServiceConfig.CDN_ENDPOINT + installerBlob.Uri.AbsolutePath; + } + + response.IsUpdateAvailable = true; + response.Version = latestVersion.Version; + response.Comments = latestVersion.Comments; + } + } + + return response; + } + + [HttpPost] + [JwtTokenFilter] + public RefreshTokenResponse RefreshToken(RefreshTokenRequest request) + { + SQLServerManager sqlServer = new SQLServerManager(); + var accessToken = sqlServer.GetAccessToken(); + + return new RefreshTokenResponse() + { + AccessToken = accessToken.AccessToken, + Expiration = accessToken.ExpiresOn.UtcDateTime, + }; + } } } -- cgit v1.3.1 From d7e74be2ba2a2a69302a25ce394540d8649c7997 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Fri, 1 May 2020 00:36:27 +0300 Subject: DefaultUpdatesManager. FSE Downloads Page on MachineService. --- .../Tango.FSE.UI/Updates/DefaultUpdatesManager.cs | 6 +- .../Tango.MachineService/App_Start/RouteConfig.cs | 11 + .../Controllers/FSEDownloadsController.cs | 60 +++++ .../Tango.MachineService/Images/fse/abstract1.png | Bin 0 -> 11647 bytes .../Tango.MachineService/Images/fse/abstract2.png | Bin 0 -> 153795 bytes .../Tango.MachineService/Images/fse/download.png | Bin 0 -> 2382 bytes .../Images/fse/machine_full.png | Bin 0 -> 16884 bytes .../Images/fse/twine_logo_colored.png | Bin 0 -> 27285 bytes .../Tango.MachineService.csproj | 8 + .../Views/FSEDownloads/Index.cshtml | 246 +++++++++++++++++++++ .../Views/FSEDownloads/IndexViewModel.cs | 27 +++ 11 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.png create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.png create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.png create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.png create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.png create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs (limited to 'Software/Visual_Studio/Web/Tango.MachineService/Controllers') diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Updates/DefaultUpdatesManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Updates/DefaultUpdatesManager.cs index f953ecf47..b236532bd 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Updates/DefaultUpdatesManager.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Updates/DefaultUpdatesManager.cs @@ -9,6 +9,7 @@ using Tango.Core.DI; using Tango.Core.ExtensionMethods; using Tango.FSE.BL.Web; using Tango.FSE.Common; +using Tango.FSE.Common.Authentication; using Tango.FSE.Common.FSEApplication; using Tango.FSE.Common.Notifications; using Tango.FSE.Common.Threading; @@ -41,6 +42,9 @@ namespace Tango.FSE.UI.Updates [TangoInject] private IDispatcherProvider DispatcherProvider { get; set; } + [TangoInject] + private IAuthenticationProvider AuthenticationProvider { get; set; } + /// /// Gets or sets a value indicating whether to perform an automatic update checks. @@ -181,7 +185,7 @@ namespace Tango.FSE.UI.Updates if (vm.DialogResult) { - Process.Start(response.InstallerCdnAddress); + Process.Start(AuthenticationProvider.CurrentEnvironment.MachineServiceAddress + "/fse"); } }); } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs b/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs index 613e83e72..51f476be5 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs @@ -13,6 +13,17 @@ namespace Tango.MachineService { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + routes.MapRoute( + name: "fse", + url: "fse", + defaults: new + { + controller = "FSEDownloads", + action = "Index", + id = UrlParameter.Optional + } + ); + routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs new file mode 100644 index 000000000..52eb2bbb5 --- /dev/null +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using Tango.BL; +using Tango.MachineService.Filters; +using Tango.MachineService.Models; +using Tango.Web.Helpers; +using System.Data.Entity; +using Tango.Web.Storage; +using System.IO; +using Microsoft.WindowsAzure.Storage.Blob; +using System.Net.Http; +using System.Net; +using System.Net.Http.Headers; +using System.Net.Mime; +using Tango.MachineService.Views.FSEDownloads; + +namespace Tango.MachineService.Controllers +{ + public class FSEDownloadsController : Controller + { + public ActionResult Index() + { + IndexViewModel model = new IndexViewModel(); + + using (var db = ObservablesContextHelper.CreateContext()) + { + var versions = db.FseVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).Take(6).ToList(); + + var manager = new BlobStorageManager(); + var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER); + + foreach (var item in versions) + { + var installerBlob = container.GetBlockBlobReference(item.InstallerBlobName); + + model.Downloads.Add(new FSEDownload() + { + Name = $"Tango FSE v{Version.Parse(item.Version).ToString(3)}", + Version = Version.Parse(item.Version).ToString(3), + Comments = item.Comments, + Date = item.LastUpdated.ToString("dddd, dd MMMM yyyy"), + Address = MachineServiceConfig.CDN_ENDPOINT + installerBlob.Uri.AbsolutePath + }); + } + + if (model.Downloads.Count > 0) + { + var latest = model.Downloads.First(); + model.Downloads.Remove(latest); + model.LatestDownload = latest; + } + } + + return View(model); + } + } +} \ No newline at end of file diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.png new file mode 100644 index 000000000..236545ae9 Binary files /dev/null and b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.png differ diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.png new file mode 100644 index 000000000..2742c71e5 Binary files /dev/null and b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.png differ diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.png new file mode 100644 index 000000000..b5d626701 Binary files /dev/null and b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.png differ diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.png new file mode 100644 index 000000000..ec4890e2e Binary files /dev/null and b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.png differ diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.png new file mode 100644 index 000000000..2204585dc Binary files /dev/null and b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.png differ diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj index ee5f3440e..67617ec7f 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj +++ b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj @@ -313,6 +313,7 @@ + @@ -333,6 +334,7 @@ + @@ -340,6 +342,12 @@ + + + + + + diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml new file mode 100644 index 000000000..fb64c18a1 --- /dev/null +++ b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml @@ -0,0 +1,246 @@ +@model Tango.MachineService.Views.FSEDownloads.IndexViewModel + +@{ + Layout = null; +} + + + + + + + + + + Tango FSE + + +
+ +
+
+ +
+
+ +
+ + Tango FSE + +
+ +
+
+ +
+ + @foreach (var item in Model.Downloads) + { +
+
+ + @item.Name + @item.Date +
+
+ +
+
+ @item.Comments +
+ + + Download + +
+ } +
+ +
+ +
Download Latest Version
+
v@(Model.LatestDownload.Version)
+
@Model.LatestDownload.Comments
+ DOWNLOAD +
+
+
+
+ + diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs new file mode 100644 index 000000000..398b5fcc1 --- /dev/null +++ b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Tango.MachineService.Views.FSEDownloads +{ + public class IndexViewModel + { + public List Downloads { get; set; } + public FSEDownload LatestDownload { get; set; } + + public IndexViewModel() + { + Downloads = new List(); + } + } + + public class FSEDownload + { + public String Name { get; set; } + public String Version { get; set; } + public String Date { get; set; } + public String Comments { get; set; } + public String Address { get; set; } + } +} \ No newline at end of file -- cgit v1.3.1 From 278d5d5c43f3e19169af5d996448d3a400f417e1 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sun, 10 May 2020 17:54:43 +0300 Subject: Fixed issue with PPC firmware update report on demo machines. --- .../Web/Tango.MachineService/Controllers/PPCController.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'Software/Visual_Studio/Web/Tango.MachineService/Controllers') diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 2049df665..28acb3647 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -344,11 +344,14 @@ namespace Tango.MachineService.Controllers response.IsUpdateAvailable = true; } - if (!String.IsNullOrWhiteSpace(request.FirmwareVersion)) + if (!machine.IsDemo && machine.SetupFirmware) { - if (Version.Parse(latest_machine_version.FirmwareVersion) > Version.Parse(request.FirmwareVersion)) + if (!String.IsNullOrWhiteSpace(request.FirmwareVersion)) { - response.IsUpdateAvailable = true; + if (Version.Parse(latest_machine_version.FirmwareVersion) > Version.Parse(request.FirmwareVersion)) + { + response.IsUpdateAvailable = true; + } } } -- cgit v1.3.1 From d4adb3a3faa36b4500c17e661e09ec2af338b353 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Mon, 11 May 2020 03:37:33 +0300 Subject: User invitation via Email ! --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../ViewModels/OrganizationUsersViewVM.cs | 1 + .../ViewModels/UserDetailsViewVM.cs | 44 +- .../Views/UserDetailsView.xaml | 2 +- .../Tango.FSE.BL/Services/AuthenticationService.cs | 16 + .../Tango.FSE.BL/Services/OrganizationsService.cs | 26 +- .../FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs | 18 + .../Messages/ForgotPasswordRequest.cs | 14 + .../Messages/ForgotPasswordResponse.cs | 14 + .../Messages/UserInvitationEmailRequest.cs | 17 + .../Messages/UserInvitationEmailResponse.cs | 14 + .../FSE/Tango.FSE.Web/Tango.FSE.Web.csproj | 4 + .../Referenced Assemblies/SendGrid/SendGrid.dll | Bin 0 -> 48640 bytes .../Referenced Assemblies/SendGrid/SendGrid.xml | 1388 ++++++++++++++++++++ .../Controllers/FSEController.cs | 80 +- .../Tango.MachineService/MachineServiceConfig.cs | 2 + .../Tango.MachineService.csproj | 5 +- .../Web/Tango.MachineService/Web.config | 2 + 19 files changed, 1621 insertions(+), 26 deletions(-) create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/ForgotPasswordRequest.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/ForgotPasswordResponse.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UserInvitationEmailRequest.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/UserInvitationEmailResponse.cs create mode 100644 Software/Visual_Studio/Referenced Assemblies/SendGrid/SendGrid.dll create mode 100644 Software/Visual_Studio/Referenced Assemblies/SendGrid/SendGrid.xml (limited to 'Software/Visual_Studio/Web/Tango.MachineService/Controllers') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index d29873151..20cd545f0 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index 826bbc8e3..d89fbab3d 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs index ff3978dff..334c8c263 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs @@ -107,6 +107,7 @@ namespace Tango.FSE.UsersAndRoles.ViewModels ModularNavigationManager.NavigateTo(UsersAndRolesView.UserDetailsView, new UserDetailsViewVM.NavigationObject() { IsNewUser = true, + Organization = Organization }); } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs index 304ee15c5..51ce71387 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs @@ -24,10 +24,18 @@ namespace Tango.FSE.UsersAndRoles.ViewModels public class NavigationObject { + public Organization Organization { get; set; } public User User { get; set; } public bool IsNewUser { get; set; } } + private Organization _organization; + public Organization Organization + { + get { return _organization; } + set { _organization = value; RaisePropertyChangedAuto(); } + } + private bool _isNewUser; public bool IsNewUser { @@ -95,6 +103,13 @@ namespace Tango.FSE.UsersAndRoles.ViewModels set { _rolesCollection = value; RaisePropertyChangedAuto(); } } + private bool _sendInvitation; + public bool SendInvitation + { + get { return _sendInvitation; } + set { _sendInvitation = value; RaisePropertyChangedAuto(); } + } + public RelayCommand SaveCommand { get; set; } public RelayCommand GeneratePasswordCommand { get; set; } @@ -103,6 +118,7 @@ namespace Tango.FSE.UsersAndRoles.ViewModels { SaveCommand = new RelayCommand(Save, () => IsFree); GeneratePasswordCommand = new RelayCommand(GeneratePassword); + SendInvitation = true; } private void GeneratePassword() @@ -216,7 +232,7 @@ namespace Tango.FSE.UsersAndRoles.ViewModels IsFree = false; - using (NotificationProvider.PushTaskItem("Saving user details...")) + using (var task = NotificationProvider.PushTaskItem("Saving user details...")) { var rolesToAdd = RolesCollection.Where(x => x.IsSelected).ToList().Where(x => !User.FSERoles.Exists(y => y.Guid == x.Role.Guid)).ToList(); var rolesToRemove = User.FSERoles.ToList().Where(x => !RolesCollection.Where(z => z.IsSelected).ToList().Exists(y => y.Role.Guid == x.Guid)).ToList(); @@ -250,11 +266,36 @@ namespace Tango.FSE.UsersAndRoles.ViewModels } else { + User.OrganizationGuid = Organization.Guid; User.Email = Email; User.Password = Password; await Services.OrganizationsService.InsertUser(User); + if (SendInvitation) + { + bool invitationSent = false; + task.UpdateProgress("Sending email invitation..."); + + while (!invitationSent) + { + try + { + await Services.OrganizationsService.SendNewUserInvitationEmail(Email, FirstName + " " + LastName, Password); + invitationSent = true; + } + catch (Exception ex) + { + if (!await NotificationProvider.ShowWarningQuestion($"The user was created but an error occurred while trying to send the invitation via email.{ex.Message}\nWould you like to try again?")) + { + break; + } + } + } + } + + await NotificationProvider.ShowSuccess("User created successfully!"); + IsNewUser = false; Password = null; userToLoadGuid = User.Guid; @@ -334,6 +375,7 @@ namespace Tango.FSE.UsersAndRoles.ViewModels { User = null; IsNewUser = obj.IsNewUser; + Organization = obj.Organization; if (!IsNewUser) { diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml index 98197eaac..a2ad81cf4 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml @@ -149,7 +149,7 @@ - Send invitation via email + Send invitation via email