aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Utils/PropertyChangedWeakEventManager.cs
blob: 9b70c8f5406d25bb85c1a7ceafb8e8c2b6811a82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)

using System;
using System.ComponentModel;

namespace Tango.Scripting.Editors.Utils
{
	/// <summary>
	/// WeakEventManager for INotifyPropertyChanged.PropertyChanged.
	/// </summary>
	public sealed class PropertyChangedWeakEventManager : WeakEventManagerBase<PropertyChangedWeakEventManager, INotifyPropertyChanged>
	{
		/// <inheritdoc/>
		protected override void StartListening(INotifyPropertyChanged source)
		{
			source.PropertyChanged += DeliverEvent;
		}
		
		/// <inheritdoc/>
		protected override void StopListening(INotifyPropertyChanged source)
		{
			source.PropertyChanged -= DeliverEvent;
		}
	}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Authentication;
using System.Threading.Tasks;
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.Logging;
using Tango.MachineService.Models;
using Tango.PPC.Common.Web;
using Tango.Web.Controllers;
using Tango.Web.Helpers;
using Tango.Web.SMO;
using Tango.Web.Storage;
using System.Data.Entity;
using Tango.Web.Security;
using Tango.Web.ActiveDirectory;
using Tango.Core.Cryptography;
using Tango.MachineService.Filters;
using Tango.BL.DTO;

namespace Tango.MachineService.Controllers
{
    public class PPCController : TangoController<PPCController.TokenObject>
    {
        private static List<PPCPendingUpload> _pendingUploads;
        private ActiveDirectoryManager _ad_manager;

        public class TokenObject
        {
            public LoginMode Mode { get; set; }
            public String UserGuid { get; set; }
            public String MachineGuid { get; set; }
        }

        #region Constructors

        static PPCController()
        {
            _pendingUploads = new List<PPCPendingUpload>();
        }

        public PPCController()
        {
            _ad_manager = new ActiveDirectoryManager();
        }

        #endregion

        #region Setup & Update

        [HttpPost]
        [JwtTokenFilter]
        public MachineSetupResponse MachineSetup(MachineSetupRequest request)
        {
            MachineSetupResponse response = new MachineSetupResponse();

            LogManager.Log("Setup request received: " + request.ToString());

            using (ObservablesContext db = ObservablesContextHelper.CreateContext())
            {
                String machine_guid = RequestToken.Object.MachineGuid;

                var machine = db.Machines.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)
                {
                    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 BlobStorageManager();
                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]
        [JwtTokenFilter]
        public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request)
        {
            DownloadUpdateResponse response = new DownloadUpdateResponse();

            using (ObservablesContext db = ObservablesContextHelper.CreateContext())
            {
                db.Configuration.LazyLoadingEnabled = false;
                String machine_guid = RequestToken.Object.MachineGuid;

                var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);

                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));

                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]
        [JwtTokenFilter]
        public CheckForUpdateResponse CheckForUpdates(CheckForUpdateRequest request)
        {
            CheckForUpdateResponse response = new CheckForUpdateResponse();

            using (ObservablesContext db = ObservablesContextHelper.CreateContext())
            {
                String machine_guid = RequestToken.Object.MachineGuid;

                var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);

                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]
        [JwtTokenFilter]
        public UpdateDBResponse UpdateDB(UpdateDBRequest request)
        {
            UpdateDBResponse response = new UpdateDBResponse();

            using (ObservablesContext db = ObservablesContextHelper.CreateContext())
            {

                String machine_guid = RequestToken.Object.MachineGuid;

                var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);

                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]
        [JwtTokenFilter]
        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_guid = RequestToken.Object.UserGuid;

                var user = new UserBuilder(db).Set(user_guid).WithRolesAndPermissions().Build();

                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();
                    var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == request.MachineVersionGuid);

                    TangoVersion latestVersion = new TangoVersion();
                    latestVersion.Version = "0.0.0.0";

                    if (versions.Count > 0)
                    {
                        latestVersion = versions.FirstOrDefault();
                    }

                    Version local_version = Version.Parse(request.Version);

                    if (local_version > Version.Parse(latestVersion.Version))
                    {
                        String newVersionFileName = $"{machine_version.Name} - Tango Version {local_version.ToString()}.tup";

                        var manager = new BlobStorageManager();
                        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));

                        PPCPendingUpload pending_upload = new PPCPendingUpload()
                        {
                            UserGuid = user.Guid,
                            Comments = request.Comments,
                            Token = response.Token,
                            Version = request.Version,
                            BlobName = blob.Name,
                            MachineVersionGuid = request.MachineVersionGuid,
                        };

                        if (request.WithInstaller)
                        {
                            String installerVersionFileName = Path.ChangeExtension(newVersionFileName, ".exe");
                            var installerBlob = container.CreateEmptyBlob(installerVersionFileName);
                            response.InstallerBlobAddress = installerBlob.GenerateWriteSignature(TimeSpan.FromMinutes(30));
                            pending_upload.InstallerBlobName = installerBlob.Name;
                        }

                        _pendingUploads.Add(pending_upload);
                    }
                    else
                    {
                        throw new ArgumentException("New version must be greater than latest version.");
                    }
                }
                else
                {
                    throw new AuthenticationException("Invalid user credentials.");
                }
            }

            return response;
        }

        [HttpPost]
        [JwtTokenFilter]
        public UploadCompletedResponse NotifyVersionUploadCompleted(UploadCompletedRequest request)
        {
            PPCPendingUpload upload = _pendingUploads.FirstOrDefault(x => x.Token == request.Token);

            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,
                        InstallerBlobName = upload.InstallerBlobName,
                        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().Select(x => MachineVersionDTO.FromObservable(x)).ToList(),
                };
            }
        }

        [HttpPost]
        public LoginResponse Login(LoginRequest request)
        {
            LoginResponse response = new LoginResponse();

            using (ObservablesContext db = ObservablesContextHelper.CreateContext())
            {
                if (request.Mode == LoginMode.User)
                {
                    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.");
                    }

                    BasicHashGenerator hash = new BasicHashGenerator();
                    String pass = hash.Encrypt(request.Password);

                    var user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower() && x.Password == pass).Build();

                    if (user == null)
                    {
                        throw new AuthenticationException("Domain user found but the database entry validation failed.");
                    }

                    response.AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
                    {
                        Mode = LoginMode.User,
                        UserGuid = user.Guid,
                    }).AccessToken;
                }
                else if (request.Mode == LoginMode.Machine)
                {
                    var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == request.SerialNumber);

                    if (machine == null)
                    {
                        throw new AuthenticationException("Invalid serial number.");
                    }

                    response.AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
                    {
                        Mode = LoginMode.Machine,
                        MachineGuid = machine.Guid,
                    }).AccessToken;
                }
            }

            return response;
        }

        #endregion
    }
}