using Google.Protobuf; 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.Threading.Tasks; using System.Web.Hosting; using System.Web.Http; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Entities; 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.Synchronization.Local; using Tango.Synchronization.Remote; namespace Tango.MachineService.Controllers { public class SynchronizationController : ApiController { private LogManager logManager = LogManager.Default; /// /// Expects a DB synchronization request from a remote machine and returns the synchronized version of the machine database. /// /// The request. /// [HttpPost] public SynchronizeDBResponse Synchronize(SynchronizeDBRequest request) { var tempFolder = TemporaryManager.Default.CreateFolder(); try { //File path for the reflected remote data base SQLite. String masterSQLiteFile = Path.Combine(tempFolder, "Remote.db"); //File path for the received machine SQLite db. String slaveSQLiteFile = Path.Combine(tempFolder, "Local.db"); //Save the machine db to file. File.WriteAllBytes(slaveSQLiteFile, request.LocalDB.ToByteArray()); //Copy an SQLite db template. File.Copy(HostingEnvironment.MapPath(@"~/App_Data/Tango.db"), masterSQLiteFile); //Synchronize the SQL Server db with the new SQLite template. (Overwrite basically) RemoteDBSynchronizer.Synchronize(masterSQLiteFile, request.SerialNumber, true); //Synchronize the received machine db with the filled template. LocalDBSynchronizer.Synchronize(masterSQLiteFile, slaveSQLiteFile); //Send the synchronized machine db to the machine to the machine. SynchronizeDBResponse response = new SynchronizeDBResponse(); response.RemoteDB = ByteString.CopyFrom(File.ReadAllBytes(slaveSQLiteFile)); return response; } catch (Exception) { throw; } finally { //Remove all temporary files and folder. tempFolder.Delete(); } } [HttpPost] public MachineSetupResponse MachineSetup(MachineSetupRequest request) { MachineSetupResponse response = new MachineSetupResponse(); logManager.Log("Setup request received: " + request.ToString()); try { using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress())) { db.Configuration.LazyLoadingEnabled = false; String serial_number = request.SerialNumber; var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number); if (machine == null) { ThrowError(HttpStatusCode.NotFound, "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; response.FtpAddress = GetFtpAddress(); response.FtpFilePath = latest_machine_version.FtpFilePath; response.FtpUserName = GetFtpUserName(); response.FtpPassword = GetFtpPassword(); DbCredentials credentials = new DbCredentials(); using (DbManager manager = DbManager.FromAddressAndName(GetDbAddress(), "Tango")) { credentials = manager.CreateRandomLoginAndUser("Tango"); Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) => { using (DbManager m = DbManager.FromAddressAndName(GetDbAddress(), "Tango")) { m.DeleteLoginAndUser(credentials.UserName, "Tango"); } }); } response.DbAddress = GetDbAddress(); response.DbUserName = credentials.UserName; response.DbPassword = credentials.Password; } } catch (Exception ex) { logManager.Log(ex); throw; } return response; } [HttpPost] public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request) { DownloadUpdateResponse response = new DownloadUpdateResponse(); try { using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress())) { db.Configuration.LazyLoadingEnabled = false; String serial_number = request.SerialNumber; var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number); if (machine == null) { OnError(HttpStatusCode.NotFound, "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; response.FtpAddress = GetFtpAddress(); response.FtpFilePath = latest_machine_version.FtpFilePath; response.FtpUserName = GetFtpUserName(); response.FtpPassword = GetFtpPassword(); DbCredentials credentials = new DbCredentials(); using (DbManager manager = DbManager.FromAddressAndName(GetDbAddress(), "Tango")) { credentials = manager.CreateRandomLoginAndUser("Tango"); Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) => { using (DbManager m = DbManager.FromAddressAndName(GetDbAddress(), "Tango")) { m.DeleteLoginAndUser(credentials.UserName, "Tango"); } }); } response.DbAddress = GetDbAddress(); response.DbUserName = credentials.UserName; response.DbPassword = credentials.Password; } } catch (Exception ex) { OnError(HttpStatusCode.InternalServerError, ex.Message); } return response; } [HttpPost] public CheckForUpdateResponse CheckForUpdate(CheckForUpdateRequest request) { CheckForUpdateResponse response = new CheckForUpdateResponse(); try { using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress())) { db.Configuration.LazyLoadingEnabled = false; var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == request.SerialNumber); if (machine == null) { OnError(HttpStatusCode.NotFound, "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; } } catch (Exception ex) { OnError(HttpStatusCode.InternalServerError, ex.Message); } return response; } [HttpPost] public UpdateDBResponse UpdateDB(UpdateDBRequest request) { UpdateDBResponse response = new UpdateDBResponse(); try { using (ObservablesContext db = ObservablesContext.CreateDefault(GetLocalServerAddress())) { db.Configuration.LazyLoadingEnabled = false; String serial_number = request.SerialNumber; var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == serial_number); if (machine == null) { OnError(HttpStatusCode.NotFound, "The specified serial number could not be found."); } DbCredentials credentials = new DbCredentials(); using (DbManager manager = DbManager.FromAddressAndName(GetDbAddress(), "Tango")) { credentials = manager.CreateRandomLoginAndUser("Tango"); Task.Delay(TimeSpan.FromMinutes(10)).ContinueWith((x) => { using (DbManager m = DbManager.FromAddressAndName(GetDbAddress(), "Tango")) { m.DeleteLoginAndUser(credentials.UserName, "Tango"); } }); } response.DbAddress = GetDbAddress(); response.DbUserName = credentials.UserName; response.DbPassword = credentials.Password; } } catch (Exception ex) { OnError(HttpStatusCode.InternalServerError, ex.Message); } return response; } [HttpPost] public Machine PersonTest(Person p) { using (var db = ObservablesContext.CreateDefault(GetLocalServerAddress())) { var machine = new MachineBuilder(db) .Set(x => x.SerialNumber == "1111") .WithOrganization() .WithConfiguration().Build(); return machine; } } #region Helpers private void ThrowError(HttpStatusCode code, String message) { throw new WebApiException(code, message); } private void OnError(HttpStatusCode code, String message) { throw new HttpResponseException(Request.CreateErrorResponse(code, message)); } private String GetLocalServerAddress() { return ConfigurationManager.AppSettings["LocalServerAddress"].ToString(); } private String GetDbAddress() { return ConfigurationManager.AppSettings["DbAddress"].ToString(); } private String GetFtpAddress() { return ConfigurationManager.AppSettings["FtpAddress"].ToString(); } private String GetFtpUserName() { return ConfigurationManager.AppSettings["FtpUserName"].ToString(); } private String GetFtpPassword() { return ConfigurationManager.AppSettings["FtpPassword"].ToString(); } #endregion } }