aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Web/Tango.MachineService/Controllers
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2019-12-15 13:12:20 +0200
committerRoy Ben-Shabat <Roy@Twine-s.com>2019-12-15 13:12:20 +0200
commit13c57f7ccabadd3ed75ffaef195d35c15c2a8c68 (patch)
tree938bd6dd844cf2645510aa3d42f3bfbe24e52a7e /Software/Visual_Studio/Web/Tango.MachineService/Controllers
parentd1859415972bb991cba6639482c1cd2a9e19e8d8 (diff)
parent957ca86b8e899eb488626c456d9c37dd4545bd80 (diff)
downloadTango-13c57f7ccabadd3ed75ffaef195d35c15c2a8c68.tar.gz
Tango-13c57f7ccabadd3ed75ffaef195d35c15c2a8c68.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/Web/Tango.MachineService/Controllers')
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs76
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs286
2 files changed, 354 insertions, 8 deletions
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
index 2eeaa6e0e..da5ce16f7 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
{
@@ -281,7 +285,16 @@ namespace Tango.MachineService.Controllers
[HttpPost]
public LoginResponse Login(LoginRequest request)
{
- var authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password);
+ 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))
{
@@ -425,6 +438,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..77b3a180f 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<PPCPendingUpload> _pendingUploads;
private static List<PPCPendingUpdate> _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
{
@@ -322,7 +322,12 @@ namespace Tango.MachineService.Controllers
bool hasDatabaseUpdates = false;
- hasDatabaseUpdates = rmls.Exists(x => request.Rmls.Exists(y => x.Guid == y.Guid && x.LastUpdated > y.LastUpdated) || !request.Rmls.Exists(y => x.Guid == y.Guid));
+ 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)
{
@@ -398,12 +403,9 @@ namespace Tango.MachineService.Controllers
Type = DataSourceType.SQLServer,
};
- 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();
-
TangoUpdate tangoUpdate = new TangoUpdate();
- tangoUpdate.ApplicationVersion = latest_machine_version.Version;
- tangoUpdate.FirmwareVersion = latest_machine_version.FirmwareVersion;
+ tangoUpdate.ApplicationVersion = request.ApplicationVersion;
+ tangoUpdate.FirmwareVersion = request.FirmwareVersion;
tangoUpdate.MachineGuid = machine.Guid;
tangoUpdate.StartDate = DateTime.UtcNow;
tangoUpdate.UpdateStatus = TangoUpdateStatuses.DatabaseStarted;
@@ -423,6 +425,276 @@ namespace Tango.MachineService.Controllers
#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(),
+ });
+ }
+ }
+ }
+ }
+ 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;
+ }
+
+ #endregion
+
#region Version Upload
[HttpPost]