using Google.Protobuf; using Microsoft.Azure; using Microsoft.Azure.Management.Sql; using Microsoft.SqlServer.Management.Smo; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Authentication; using System.Threading.Tasks; using System.Web.Hosting; using System.Web.Http; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.Core; using Tango.Core.DB; using Tango.Core.Helpers; using Tango.Core.IO; using Tango.Logging; using Tango.MachineService.Models; using Tango.PMR.Stubs; using Tango.PMR.Synchronization; using Tango.PPC.Common.MachineSetup; using Tango.PPC.Common.MachineUpdate; using Tango.PPC.Common.Update; using Tango.Synchronization.Local; using Tango.Synchronization.Remote; using Tango.Web.Controllers; using Tango.Web.Helpers; using Tango.Web.SMO; using Tango.Web.Storage; namespace Tango.MachineService.Controllers { public class PPCController : JsonController { private static List _pendingUploads; #region Constructors static PPCController() { _pendingUploads = new List(); } #endregion #region Setup & Update [HttpPost] public MachineSetupResponse MachineSetup(MachineSetupRequest request) { MachineSetupResponse response = new MachineSetupResponse(); LogManager.Log("Setup request received: " + request.ToString()); using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { db.Configuration.LazyLoadingEnabled = false; String serial_number = request.SerialNumber; var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number); if (machine == null) { throw new AuthenticationException("The specified serial number could not be found."); } if (machine.SetupActivation && machine.OsKey == null) { throw new InvalidDataException("The specified machine is configured to perform an OS activation but is not associated with an OS activation key."); } 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 StorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); var blob = container.GetBlockBlobReference(latest_machine_version.BlobName); response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60)); DbCredentials credentials = new DbCredentials(); using (SmoManager smo = new SmoManager()) { credentials = smo.CreateRandomLoginAndUser(); Task.Delay(TimeSpan.FromMinutes(10)).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, }; response.OSKey = machine.OsKey; response.SetupActivation = machine.SetupActivation; response.SetupRemoteAssistance = machine.SetupRemoteAssistance; response.SetupUWF = machine.SetupUwf; response.SetupFirmware = machine.SetupFirmware; response.IsDemo = machine.IsDemo; } return response; } [HttpPost] public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request) { DownloadUpdateResponse response = new DownloadUpdateResponse(); using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { db.Configuration.LazyLoadingEnabled = false; String serial_number = request.SerialNumber; var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number); 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 StorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); var blob = container.GetBlockBlobReference(latest_machine_version.BlobName); response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60)); DbCredentials credentials = new DbCredentials(); using (SmoManager smo = new SmoManager()) { credentials = smo.CreateRandomLoginAndUser(); Task.Delay(TimeSpan.FromMinutes(10)).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; } [HttpPost] public CheckForUpdateResponse CheckForUpdate(CheckForUpdateRequest request) { CheckForUpdateResponse response = new CheckForUpdateResponse(); using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { db.Configuration.LazyLoadingEnabled = false; 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(); if (Version.Parse(latest_machine_version.Version) > Version.Parse(request.Version)) { response.IsUpdateAvailable = true; } response.Version = latest_machine_version.Version; } return response; } [HttpPost] public UpdateDBResponse UpdateDB(UpdateDBRequest request) { UpdateDBResponse response = new UpdateDBResponse(); using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { db.Configuration.LazyLoadingEnabled = false; String serial_number = request.SerialNumber; var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number); if (machine == null) { throw new AuthenticationException("The specified serial number could not be found."); } DbCredentials credentials = new DbCredentials(); using (SmoManager manager = new SmoManager()) { credentials = manager.CreateRandomLoginAndUser(); Task.Delay(TimeSpan.FromMinutes(10)).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 #region Version Upload [HttpPost] public LatestVersionResponse GetLatestVersion(LatestVersionRequest request) { LatestVersionResponse response = new LatestVersionResponse(); using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { var versions = db.TangoVersions.Where(x => x.MachineVersionGuid == request.MachineVersionGuid).ToList(); if (versions.Count == 0) { return new LatestVersionResponse() { Version = "0.0.0.0", }; } response.Version = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault().Version; } return response; } [HttpPost] public UploadVersionResponse UploadVersion(UploadVersionRequest request) { UploadVersionResponse response = new UploadVersionResponse(); using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { //Load relations first... db.Roles.ToList(); db.Permissions.ToList(); db.UsersRoles.ToList(); db.RolesPermissions.ToList(); var user = db.Users.SingleOrDefault(x => x.Email.ToLower() == request.Email.ToLower() && x.Password == request.Password); if (user != null && user.HasPermission(Permissions.PublishPPCVersions)) { var versions = db.TangoVersions.ToList().Where(x => x.MachineVersionGuid == request.MachineVersionGuid).OrderByDescending(x => Version.Parse(x.Version)).ToList(); TangoVersion latestVersion = new TangoVersion(); latestVersion.Version = "0.0.0.0"; if (versions.Count > 0) { latestVersion = versions.FirstOrDefault(); } Version currentVersion = Version.Parse(request.Version); if (currentVersion > Version.Parse(latestVersion.Version)) { String newVersionFileName = "Tango Version" + " " + currentVersion.ToString() + ".zip"; var manager = new StorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); var blob = container.CreateEmptyBlob(newVersionFileName); response.Token = Guid.NewGuid().ToString(); response.BlobAddress = blob.GenerateWriteSignature(TimeSpan.FromMinutes(30)); _pendingUploads.Add(new PPCPendingUpload() { UserGuid = user.Guid, Comments = request.Comments, Token = response.Token, Version = request.Version, BlobName = blob.Name, MachineVersionGuid = request.MachineVersionGuid, }); } else { throw new ArgumentException("New version must be greater than latest version."); } } else { throw new AuthenticationException("Invalid user credentials."); } } return response; } [HttpPost] public UploadCompletedResponse NotifyUploadCompleted(UploadCompletedRequest request) { PPCPendingUpload upload = _pendingUploads.FirstOrDefault(x => x.Token == request.AccessToken); if (upload != null) { _pendingUploads.RemoveAll(x => x.Token == upload.Token); using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { db.TangoVersions.Add(new TangoVersion() { Comments = upload.Comments, BlobName = upload.BlobName, UserGuid = upload.UserGuid, Version = upload.Version, MachineVersionGuid = upload.MachineVersionGuid }); db.SaveChanges(); } return new UploadCompletedResponse(); } else { throw new AuthenticationException("Invalid upload token."); } } [HttpPost] public MachineVersionsResponse GetMachineVersions(MachineVersionsRequest request) { using (var db = ObservablesContextHelper.CreateContext()) { return new MachineVersionsResponse() { MachineVersions = db.MachineVersions.ToList(), }; } } #endregion [HttpPost] public Machine PersonTest(Person p) { using (var db = ObservablesContextHelper.CreateContext()) { var machine = new MachineBuilder(db) .Set(x => x.SerialNumber == "1111") .WithOrganization() .WithConfiguration().Build(); return machine; } } } }