aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Web/Tango.MachineService/Controllers
diff options
context:
space:
mode:
authorShlomo Hecht <shlomo@twine-s.com>2020-01-27 09:19:11 +0200
committerShlomo Hecht <shlomo@twine-s.com>2020-01-27 09:19:11 +0200
commitddda6089bff56e80703c8d2dce297919edc58bf1 (patch)
tree7702c5cf169124d522eacc7f1a9e0878373baedd /Software/Visual_Studio/Web/Tango.MachineService/Controllers
parent1d4d327571d4c0c9f4e17411551bd4dae1e2aed0 (diff)
parentbf2f3245339b9fd9148a2ad25b5ba3320e970cc1 (diff)
downloadTango-ddda6089bff56e80703c8d2dce297919edc58bf1.tar.gz
Tango-ddda6089bff56e80703c8d2dce297919edc58bf1.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/Tango/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/Web/Tango.MachineService/Controllers')
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs260
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs477
2 files changed, 679 insertions, 58 deletions
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
index b718887af..7d105f0bd 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
@@ -22,6 +22,11 @@ using Tango.Web.Security;
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
{
@@ -98,6 +103,11 @@ namespace Tango.MachineService.Controllers
response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60));
+ if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT))
+ {
+ response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath;
+ }
+
response.IsUpdateAvailable = true;
response.Version = latestVersion.Version;
response.Comments = latestVersion.Comments;
@@ -132,6 +142,11 @@ namespace Tango.MachineService.Controllers
var container = manager.GetContainer(MachineServiceConfig.MACHINE_STUDIO_VERSIONS_CONTAINER);
var blob = container.GetBlockBlobReference(latestVersion.BlobName);
+ if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT))
+ {
+ response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath;
+ }
+
response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60));
response.Version = latestVersion.Version;
}
@@ -270,12 +285,10 @@ namespace Tango.MachineService.Controllers
[HttpPost]
public LoginResponse Login(LoginRequest request)
{
- var authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password);
-
- if (!_ad_manager.CanUserAccessCurrentEnvironment(request.Email))
- {
- throw new AuthenticationException($"You do not have permissions to access the {MachineServiceConfig.DEPLOYMENT_SLOT.ToDescription()} environment.");
- }
+ AuthenticationResult authResult = null;
+ User user = null;
+ DataSource dataSource = null;
+ IHashGenerator hash = new BasicHashGenerator();
Version client_version;
@@ -286,65 +299,136 @@ 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 UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower()).WithRolesAndPermissions().WithDeleted().Build();
+
+ if (user == null)
{
- User = new_user,
- Role = db.Roles.Single(x => (Roles)x.Code == Roles.User),
- });
+ 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,
+ };
- db.UsersRoles.Add(new UsersRole()
+ 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
{
- User = new_user,
- Role = db.Roles.Single(x => (Roles)x.Code == Roles.MachineStudioUser),
- });
+ if (user.Deleted)
+ {
+ throw new AuthenticationException("Your account has been disabled. Please contact your administrator.");
+ }
+ }
- new_user.LastLogin = DateTime.UtcNow;
- db.Users.Add(new_user);
+ user.LastLogin = DateTime.UtcNow;
+
+ db.SaveChanges();
}
- else
+
+ 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);
+
+ using (var db = ObservablesContextHelper.CreateContext())
+ {
+ user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower() && (isPasswordOK || x.Password == password)).WithRolesAndPermissions().WithDeleted().Build();
+
+ if (user == null)
+ {
+ throw new AuthenticationException("Invalid email or password.");
+ }
+
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();
+ SQLServerManager sqlServer = new SQLServerManager();
+ var accessToken = sqlServer.GetAccessToken();
- if (MachineServiceConfig.ENFORCE_MACHINE_STUDIO_VERSION)
+ dataSource = new DataSource()
+ {
+ Address = MachineServiceConfig.DB_ADDRESS,
+ Catalog = MachineServiceConfig.DB_CATALOG,
+ Type = Core.DataSourceType.AccessToken,
+ IntegratedSecurity = false,
+ AccessToken = accessToken.AccessToken,
+ AccessTokenExpiration = accessToken.ExpiresOn.UtcDateTime
+ };
+ }
+
+ //Enforce Machine Studio Version ?
+ if (MachineServiceConfig.ENFORCE_MACHINE_STUDIO_VERSION)
+ {
+ using (var db = ObservablesContextHelper.CreateContext())
{
var latest_version = db.MachineStudioVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
@@ -356,27 +440,97 @@ namespace Tango.MachineService.Controllers
}
}
+ //Return data source
return new LoginResponse()
{
- DataSource = new Core.DataSource()
- {
- Address = MachineServiceConfig.DB_ADDRESS,
- Catalog = MachineServiceConfig.DB_CATALOG,
- Type = Core.DataSourceType.Azure,
- IntegratedSecurity = false,
- UserName = request.Email,
- Password = request.Password,
- },
-
+ DataSource = dataSource,
AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
{
UserGuid = user.Guid,
}, DateTime.UtcNow.AddDays(1)).AccessToken,
VersionChangeRequired = versionChangeRequired,
RequiredVersion = requiredVersion,
+ PasswordChangeRequired = request.Method == LoginMethod.StandardUser && user.PasswordChangeRequired
};
}
+ [JwtTokenFilter]
+ public RefreshTokenResponse RefreshToken(RefreshTokenRequest request)
+ {
+ SQLServerManager sqlServer = new SQLServerManager();
+ var accessToken = sqlServer.GetAccessToken();
+
+ //TokenManager tokenManager = new TokenManager();
+ //tokenManager.UpdateToken(request.AccessToken, accessToken.AccessToken, accessToken.ExpiresOn.UtcDateTime);
+
+ return new RefreshTokenResponse()
+ {
+ AccessToken = accessToken.AccessToken,
+ Expiration = accessToken.ExpiresOn.UtcDateTime,
+ };
+ }
+
+ [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 6f5eed749..6ac2e3657 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
@@ -30,7 +30,9 @@ namespace Tango.MachineService.Controllers
public class PPCController : TangoController<PPCController.TokenObject>
{
private static List<PPCPendingUpload> _pendingUploads;
+ private static List<PPCPendingUpdate> _pendingUpdates;
private ActiveDirectoryManager _ad_manager;
+ public const int SQL_TEMP_CREDENTIALS_EXP_MINUTS = 20;
public class TokenObject
{
@@ -44,6 +46,7 @@ namespace Tango.MachineService.Controllers
static PPCController()
{
_pendingUploads = new List<PPCPendingUpload>();
+ _pendingUpdates = new List<PPCPendingUpdate>();
}
public PPCController()
@@ -60,6 +63,7 @@ namespace Tango.MachineService.Controllers
public MachineSetupResponse MachineSetup(MachineSetupRequest request)
{
MachineSetupResponse response = new MachineSetupResponse();
+ response.NotifyCompletedToken = Guid.NewGuid().ToString();
LogManager.Log("Setup request received: " + request.ToString());
@@ -67,23 +71,43 @@ namespace Tango.MachineService.Controllers
{
String machine_guid = RequestToken.Object.MachineGuid;
- var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
+ var machine = db.Machines.Include(x => x.Organization).SingleOrDefault(x => x.Guid == machine_guid);
if (machine == null)
{
throw new AuthenticationException("The specified serial number could not be found.");
}
- if (machine.SetupActivation && machine.OsKey == null)
+ if (machine.SetupActivation && String.IsNullOrWhiteSpace(machine.OsKey))
{
throw new InvalidDataException("The specified machine is configured to perform an OS activation but is not associated with an OS activation key.");
}
+ if (String.IsNullOrWhiteSpace(request.DeviceID))
+ {
+ throw new InvalidDataException("Device id not set.");
+ }
+
+ if (String.IsNullOrWhiteSpace(request.DeviceName))
+ {
+ throw new InvalidDataException("Device name not set.");
+ }
+
+ if (machine.IsDeviceRegistered && machine.DeviceId != request.DeviceID)
+ {
+ throw new InvalidDataException("The specified machine is already registered and device id is invalid.");
+ }
+
+ machine.DeviceName = request.DeviceName;
+ machine.DeviceId = request.DeviceID;
+ machine.IsDeviceRegistered = true;
+
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;
+ response.FirmwareVersion = latest_machine_version.FirmwareVersion;
var manager = new BlobStorageManager();
var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER);
@@ -91,13 +115,18 @@ namespace Tango.MachineService.Controllers
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(10)).ContinueWith((x) =>
+ Task.Delay(TimeSpan.FromMinutes(SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) =>
{
using (SmoManager m = new SmoManager())
{
@@ -122,7 +151,25 @@ namespace Tango.MachineService.Controllers
response.SetupUWF = machine.SetupUwf;
response.SetupFirmware = machine.SetupFirmware;
response.IsDemo = machine.IsDemo;
+ response.Organization = machine.Organization.Name;
+ TangoUpdate tangoUpdate = new TangoUpdate();
+ tangoUpdate.ApplicationVersion = latest_machine_version.Version;
+ tangoUpdate.FirmwareVersion = latest_machine_version.FirmwareVersion;
+ tangoUpdate.MachineGuid = machine.Guid;
+ tangoUpdate.StartDate = DateTime.UtcNow;
+ tangoUpdate.UpdateStatus = TangoUpdateStatuses.SetupStarted;
+ db.TangoUpdates.Add(tangoUpdate);
+
+ machine.ProductionDate = DateTime.UtcNow;
+
+ db.SaveChanges();
+
+ _pendingUpdates.Add(new PPCPendingUpdate()
+ {
+ Token = response.NotifyCompletedToken,
+ TangoUpdateGuid = tangoUpdate.Guid,
+ });
}
return response;
@@ -133,6 +180,7 @@ namespace Tango.MachineService.Controllers
public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request)
{
DownloadUpdateResponse response = new DownloadUpdateResponse();
+ response.NotifyCompletedToken = Guid.NewGuid().ToString();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
@@ -151,6 +199,7 @@ namespace Tango.MachineService.Controllers
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;
+ response.FirmwareVersion = latest_machine_version.FirmwareVersion;
var manager = new BlobStorageManager();
var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER);
@@ -158,13 +207,18 @@ namespace Tango.MachineService.Controllers
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(10)).ContinueWith((x) =>
+ Task.Delay(TimeSpan.FromMinutes(SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) =>
{
using (SmoManager m = new SmoManager())
{
@@ -182,6 +236,22 @@ namespace Tango.MachineService.Controllers
IntegratedSecurity = false,
Type = DataSourceType.SQLServer,
};
+
+ TangoUpdate tangoUpdate = new TangoUpdate();
+ tangoUpdate.ApplicationVersion = latest_machine_version.Version;
+ tangoUpdate.FirmwareVersion = latest_machine_version.FirmwareVersion;
+ tangoUpdate.MachineGuid = machine.Guid;
+ tangoUpdate.StartDate = DateTime.UtcNow;
+ tangoUpdate.UpdateStatus = TangoUpdateStatuses.UpdateStarted;
+ db.TangoUpdates.Add(tangoUpdate);
+
+ db.SaveChanges();
+
+ _pendingUpdates.Add(new PPCPendingUpdate()
+ {
+ Token = response.NotifyCompletedToken,
+ TangoUpdateGuid = tangoUpdate.Guid,
+ });
}
return response;
@@ -189,6 +259,40 @@ namespace Tango.MachineService.Controllers
[HttpPost]
[JwtTokenFilter]
+ public MachineUpdateCompletedResponse NotifyUpdateCompleted(MachineUpdateCompletedRequest request)
+ {
+ var pendingUpdate = _pendingUpdates.SingleOrDefault(x => x.Token == request.Token);
+ if (pendingUpdate != null)
+ {
+ _pendingUpdates.Remove(pendingUpdate);
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var tangoUpdate = db.TangoUpdates.SingleOrDefault(x => x.Guid == pendingUpdate.TangoUpdateGuid);
+
+ if (tangoUpdate != null)
+ {
+ tangoUpdate.LastUpdated = DateTime.UtcNow;
+ tangoUpdate.UpdateStatus = request.Status;
+ tangoUpdate.EndDate = DateTime.UtcNow;
+ tangoUpdate.FailedReason = request.FailedReason;
+ tangoUpdate.FailedLog = request.FailedLog;
+
+ if (request.ReportsAboutDbCheckNoDifferences)
+ {
+ db.TangoUpdates.Remove(tangoUpdate);
+ }
+
+ db.SaveChanges();
+ }
+ }
+ }
+
+ return new MachineUpdateCompletedResponse();
+ }
+
+ [HttpPost]
+ [JwtTokenFilter]
public CheckForUpdateResponse CheckForUpdates(CheckForUpdateRequest request)
{
CheckForUpdateResponse response = new CheckForUpdateResponse();
@@ -204,6 +308,9 @@ namespace Tango.MachineService.Controllers
throw new AuthenticationException("The specified serial number could not be found.");
}
+ response.SetupFirmware = machine.SetupFirmware;
+ response.SetupFPGA = machine.SetupFpga;
+
if (!machine.SuspendVersionUpdate)
{
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid);
@@ -216,6 +323,49 @@ namespace Tango.MachineService.Controllers
}
response.Version = latest_machine_version.Version;
+ response.FirmwareVersion = latest_machine_version.FirmwareVersion;
+
+ //Compare database
+
+ var rmls = db.Rmls.Select(x => new { x.Guid, x.LastUpdated }).ToList();
+ var hardwareVersions = db.HardwareVersions.Select(x => new { x.Guid, x.LastUpdated }).ToList();
+ var catalogs = db.ColorCatalogs.Select(x => new { x.Guid, x.LastUpdated }).ToList();
+
+ var arr = request.UsedRmlsGuids.ToArray();
+ var existingRml = db.Rmls.Where(x => arr.Contains(x.Guid)).Select(x => x.Guid).Distinct().ToList();
+ response.UsedNotExistingRmlsGuids = arr.Where(x => !existingRml.Exists(y => y == x)).ToList();
+
+ bool hasDatabaseUpdates = false;
+
+ hasDatabaseUpdates = machine.LastUpdated > request.MachineLastUpdated;
+
+ if (!hasDatabaseUpdates)
+ {
+ hasDatabaseUpdates = rmls.Exists(x => request.Rmls.Exists(y => x.Guid == y.Guid && x.LastUpdated > y.LastUpdated) || !request.Rmls.Exists(y => x.Guid == y.Guid));
+ }
+
+ if (!hasDatabaseUpdates)
+ {
+ hasDatabaseUpdates = hardwareVersions.Exists(x => request.HardwareVersions.Exists(y => x.Guid == y.Guid && x.LastUpdated > y.LastUpdated) || !request.HardwareVersions.Exists(y => x.Guid == y.Guid));
+ }
+
+ if (!hasDatabaseUpdates)
+ {
+ hasDatabaseUpdates = catalogs.Exists(x => request.Catalogs.Exists(y => x.Guid == y.Guid && x.LastUpdated > y.LastUpdated) || !request.Catalogs.Exists(y => x.Guid == y.Guid));
+ }
+
+ if (hasDatabaseUpdates)
+ {
+ response.IsDatabaseUpdateAvailable = true;
+ response.UpdateDBResponse = UpdateDB(new UpdateDBRequest() { SerialNumber = request.SerialNumber });
+ }
+
+ //Compare database
+
+ if (machine.ForceVersionUpdate)
+ {
+ response.IsUpdateAvailable = true;
+ }
}
}
@@ -227,6 +377,7 @@ namespace Tango.MachineService.Controllers
public UpdateDBResponse UpdateDB(UpdateDBRequest request)
{
UpdateDBResponse response = new UpdateDBResponse();
+ response.NotifyCompletedToken = Guid.NewGuid().ToString();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
@@ -248,7 +399,7 @@ namespace Tango.MachineService.Controllers
{
credentials = manager.CreateRandomLoginAndUser();
- Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) =>
+ Task.Delay(TimeSpan.FromMinutes(SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) =>
{
using (SmoManager m = new SmoManager())
{
@@ -266,6 +417,320 @@ namespace Tango.MachineService.Controllers
IntegratedSecurity = false,
Type = DataSourceType.SQLServer,
};
+
+ TangoUpdate tangoUpdate = new TangoUpdate();
+ tangoUpdate.ApplicationVersion = request.ApplicationVersion;
+ tangoUpdate.FirmwareVersion = request.FirmwareVersion;
+ tangoUpdate.MachineGuid = machine.Guid;
+ tangoUpdate.StartDate = DateTime.UtcNow;
+ tangoUpdate.UpdateStatus = TangoUpdateStatuses.DatabaseStarted;
+ db.TangoUpdates.Add(tangoUpdate);
+
+ db.SaveChanges();
+
+ _pendingUpdates.Add(new PPCPendingUpdate()
+ {
+ Token = response.NotifyCompletedToken,
+ TangoUpdateGuid = tangoUpdate.Guid,
+ });
+ }
+
+ return response;
+ }
+
+ #endregion
+
+ #region Synchronization
+
+ [HttpPost]
+ [JwtTokenFilter]
+ public UploadMachineDataResponse UploadMachineData(UploadMachineDataRequest request)
+ {
+ UploadMachineDataResponse response = new UploadMachineDataResponse();
+ response.NotifyCompletedToken = Guid.NewGuid().ToString();
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
+
+ if (machine == null)
+ {
+ throw new AuthenticationException("The specified machine could not be found.");
+ }
+
+ TangoUpdate tangoUpdate = new TangoUpdate();
+ tangoUpdate.ApplicationVersion = request.ApplicationVersion;
+ tangoUpdate.FirmwareVersion = request.FirmwareVersion;
+ tangoUpdate.MachineGuid = machine.Guid;
+ tangoUpdate.StartDate = DateTime.UtcNow;
+ tangoUpdate.UpdateStatus = TangoUpdateStatuses.SynchronizationStarted;
+ db.TangoUpdates.Add(tangoUpdate);
+ db.SaveChanges();
+
+ _pendingUpdates.Add(new PPCPendingUpdate()
+ {
+ Token = response.NotifyCompletedToken,
+ TangoUpdateGuid = tangoUpdate.Guid,
+ });
+ }
+
+ User machineUser = null;
+
+ try
+ {
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
+
+ if (machine == null)
+ {
+ throw new AuthenticationException("The specified machine could not be found.");
+ }
+
+ machineUser = db.Users.Include(x => x.Contact).SingleOrDefault(x => x.Contact.FirstName == machine.Name);
+
+ if (machineUser == null)
+ {
+ //No machine user then create one.
+ machineUser = new User();
+ machineUser.Email = machine.SerialNumber + "@twine-s.com";
+ machineUser.Password = machine.SerialNumber;
+ machineUser.OrganizationGuid = machine.OrganizationGuid;
+ machineUser.Contact = new Contact();
+ machineUser.Contact.Email = machineUser.Email;
+ machineUser.Contact.FirstName = machine.Name;
+ machineUser.Contact.LastName = machine.Name;
+ machineUser.Contact.FullName = machine.Name;
+ machineUser.Address = new Address();
+
+ db.Users.Add(machineUser);
+ db.SaveChanges();
+ }
+ }
+
+ //Insert/Replace Jobs.
+ foreach (var dto in request.Jobs)
+ {
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ try
+ {
+ var job = dto.ToObservable();
+
+ job.ID = 0;
+ job.UserGuid = machineUser.Guid;
+ job.CustomerGuid = null;
+ job.IsSynchronized = true;
+
+ var existingJob = db.Jobs.SingleOrDefault(x => x.Guid == job.Guid);
+
+ if (existingJob == null)
+ {
+ db.Jobs.Add(job);
+ db.SaveChanges();
+ }
+ else if (job.LastUpdated > existingJob.LastUpdated)
+ {
+ existingJob.Delete(db);
+ db.Jobs.Add(job);
+ db.SaveChanges();
+ }
+ }
+ catch (Exception ex)
+ {
+ response.FailedJobs.Add(new SynchronizationFailedEntity()
+ {
+ Guid = dto.Guid,
+ Reason = ex.FlattenMessage(),
+ });
+ }
+ }
+ }
+
+ //Insert JobRuns.
+ foreach (var dto in request.JobRuns)
+ {
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ try
+ {
+ var run = dto.ToObservable();
+ run.ID = 0;
+ run.IsSynchronized = true;
+
+ if (db.JobRuns.SingleOrDefault(x => x.Guid == run.Guid) == null)
+ {
+ db.JobRuns.Add(run);
+ db.SaveChanges();
+ }
+ }
+ catch (Exception ex)
+ {
+ response.FailedJobRuns.Add(new SynchronizationFailedEntity()
+ {
+ Guid = dto.Guid,
+ Reason = ex.FlattenMessage(),
+ });
+ }
+ }
+ }
+
+ //Insert MachineEvents.
+ foreach (var dto in request.MachineEvents)
+ {
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ try
+ {
+ var ev = dto.ToObservable();
+ ev.ID = 0;
+ ev.UserGuid = machineUser.Guid;
+ ev.IsSynchronized = true;
+
+ if (db.MachinesEvents.SingleOrDefault(x => x.Guid == ev.Guid) == null)
+ {
+ db.MachinesEvents.Add(ev);
+ db.SaveChanges();
+ }
+ }
+ catch (Exception ex)
+ {
+ response.FailedMachineEvents.Add(new SynchronizationFailedEntity()
+ {
+ Guid = dto.Guid,
+ Reason = ex.FlattenMessage(),
+ });
+ }
+ }
+ }
+
+ //Insert TangoUpdates.
+ foreach (var dto in request.OfflineUpdates)
+ {
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ try
+ {
+ var update = dto.ToObservable();
+ update.ID = 0;
+ update.IsSynchronized = true;
+
+ if (db.TangoUpdates.SingleOrDefault(x => x.Guid == update.Guid) == null)
+ {
+ db.TangoUpdates.Add(update);
+ db.SaveChanges();
+ }
+ }
+ catch (Exception ex)
+ {
+ response.FailedOfflineUpdates.Add(new SynchronizationFailedEntity()
+ {
+ Guid = dto.Guid,
+ Reason = ex.FlattenMessage(),
+ });
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
+ {
+ Status = TangoUpdateStatuses.SynchronizationFailed,
+ FailedReason = ex.FlattenMessage(),
+ FailedLog = ex.FlattenException(),
+ Token = response.NotifyCompletedToken,
+ });
+ throw ex;
+ }
+
+ return response;
+ }
+
+ [HttpPost]
+ [JwtTokenFilter]
+ public DownloadMachineDataResponse DownloadMachineData(DownloadMachineDataRequest request)
+ {
+ DownloadMachineDataResponse response = new DownloadMachineDataResponse();
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
+
+ if (machine == null)
+ {
+ throw new AuthenticationException("The specified machine could not be found.");
+ }
+
+ //Send Jobs
+ if (request.RequestJobs)
+ {
+ var jobs = new JobsCollectionBuilder(db).Set(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).WithSegments().WithBrushStops().Query(x => x.Take(request.MaxJobs).OrderByDescending(z => z.LastUpdated)).BuildList();
+
+ foreach (var job in jobs)
+ {
+ JobDTO dto = JobDTO.FromObservable(job);
+ response.Jobs.Add(dto);
+ }
+ }
+
+ //Send Job Runs
+ if (request.RequestJobRuns)
+ {
+ var jobRuns = db.JobRuns.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxJobRuns).OrderByDescending(x => x.LastUpdated).ToList();
+
+ foreach (var jobRun in jobRuns)
+ {
+ JobRunDTO dto = JobRunDTO.FromObservable(jobRun);
+ response.JobRuns.Add(dto);
+ }
+ }
+
+ //Send Machine Events
+ if (request.RequestMachineEvents)
+ {
+ var machineEvents = db.MachinesEvents.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxMachinesEvents).OrderByDescending(x => x.LastUpdated).ToList();
+
+ foreach (var machineEvent in machineEvents)
+ {
+ MachinesEventDTO dto = MachinesEventDTO.FromObservable(machineEvent);
+ response.MachineEvents.Add(dto);
+ }
+ }
+ }
+
+ return response;
+ }
+
+ [HttpPost]
+ [JwtTokenFilter]
+ public NotifyMachineDataDownloadCompletedResponse NotifyMachineDataDownloadCompleted(NotifyMachineDataDownloadCompletedRequest request)
+ {
+ var response = new NotifyMachineDataDownloadCompletedResponse();
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
+
+ if (machine == null)
+ {
+ throw new AuthenticationException("The specified machine could not be found.");
+ }
+
+ if (request.SynchronizedJobs.Count > 0)
+ {
+ db.Database.ExecuteSqlCommand($"UPDATE JOBS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedJobs.Select(x => "'" + x + "'"))});");
+ }
+
+ if (request.SynchronizedJobRuns.Count > 0)
+ {
+ db.Database.ExecuteSqlCommand($"UPDATE JOB_RUNS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedJobRuns.Select(x => "'" + x + "'"))});");
+ }
+
+ if (request.SynchronizedMachineEvents.Count > 0)
+ {
+ db.Database.ExecuteSqlCommand($"UPDATE MACHINES_EVENTS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedMachineEvents.Select(x => "'" + x + "'"))});");
+ }
}
return response;
@@ -350,6 +815,7 @@ namespace Tango.MachineService.Controllers
Version = request.Version,
BlobName = blob.Name,
MachineVersionGuid = request.MachineVersionGuid,
+ FirmwareVersion = request.FirmwareVersion,
};
if (request.WithInstaller)
@@ -396,6 +862,7 @@ namespace Tango.MachineService.Controllers
UserGuid = upload.UserGuid,
Version = upload.Version,
MachineVersionGuid = upload.MachineVersionGuid,
+ FirmwareVersion = upload.FirmwareVersion,
});
db.SaveChanges();