aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DB/ViewModels/MachineVersionsViewVM.cs
blob: d00fd159392ea900066c2ab120a4527cc9d29e15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL.Entities;
using Tango.MachineStudio.Common.Notifications;

namespace Tango.MachineStudio.DB.ViewModels
{
    public class MachineVersionsViewVM : DbTableViewModel<MachineVersion>
    {
        public MachineVersionsViewVM(INotificationProvider notification) : base(notification)
        {
            
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Web.Http;
using Tango.BL.Builders;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core.Cryptography;
using Tango.DataStore;
using Tango.DataStore.EF;
using Tango.DataStore.Web;
using Tango.MachineService.Filters;
using Tango.Web.Controllers;
using Tango.Web.Helpers;
using Tango.Web.Security;
using static Tango.MachineService.Controllers.DataStoreController;

namespace Tango.MachineService.Controllers
{
    public class DataStoreController : TangoController<TokenObject>
    {
        public class TokenObject
        {
            public String UserGuid { get; set; }
            public List<Permissions> Permissions { get; set; }

            public TokenObject()
            {
                Permissions = new List<Permissions>();
            }
        }

        private IDataStoreManager _manager;

        public DataStoreController()
        {
            _manager = new EFDataStoreManager();
        }

        [HttpPost]
        public LoginResponse Login(LoginRequest request)
        {
            User user = null;

            IHashGenerator hash = new BasicHashGenerator();
            var password = hash.Encrypt(request.Password);

            using (var db = ObservablesContextHelper.CreateContext())
            {
                user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower() && 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.");
                }

                if (!user.HasPermission(Permissions.DataStoreRead))
                {
                    throw new AuthenticationException("You are not authorized to access the data store.");
                }

                var token = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
                {
                    UserGuid = user.Guid,
                    Permissions = user.Permissions.Select(x => (Permissions)x.Code).ToList()
                }, DateTime.UtcNow.AddDays(1));

                return new LoginResponse()
                {
                    Token = token.AccessToken,
                    ExpirationUTC = token.Expiration.Value,
                };
            }
        }

        [JwtWebApiTokenFilter]
        public List<DataStoreWebItem> Get(String sn = null, String collection = null, String key = null)
        {
            try
            {
                if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreRead))
                {
                    throw CreateHttpException(new AuthenticationException("The current user was not authorized to read from the data store."), HttpStatusCode.Unauthorized);
                }

                if (key != null && collection == null)
                {
                    throw CreateHttpException(new ArgumentException(), HttpStatusCode.BadRequest, "When specifying a key, collection must be specified.");
                }

                ValidateCollectionAndKey(collection, key);

                using (var db = ObservablesContextHelper.CreateContext())
                {
                    if (sn != null)
                    {
                        var machineGuid = db.Machines.Where(x => x.SerialNumber == sn).Select(x => x.Guid).FirstOrDefault();

                        if (machineGuid == null)
                        {
                            throw CreateHttpException(new KeyNotFoundException(), HttpStatusCode.NotFound, "The specified machine serial number could not be found.");
                        }

                        var localItems = db.DataStoreItems.Where(x => !x.IsDeleted).Where(x => x.MachineGuid == machineGuid && (collection == null || x.CollectionName == collection) && (key == null || x.Key == key)).ToList();
                        var globalItems = db.GlobalDataStoreItems.Where(x => (collection == null || x.CollectionName == collection) && (key == null || x.Key == key)).ToList();

                        if (localItems.Count == 0 && globalItems.Count == 0 && key != null)
                        {
                            throw CreateHttpException(new KeyNotFoundException(), HttpStatusCode.NotFound, "The specified key was not found on the data store.");
                        }

                        List<DataStoreWebItem> finalList = new List<DataStoreWebItem>();

                        foreach (var localItem in localItems)
                        {
                            var globalItem = globalItems.FirstOrDefault(x => x.CollectionName == localItem.CollectionName && x.Key == localItem.Key);
                            finalList.Add(localItem.ToWebItem(globalItem));
                            globalItems.Remove(globalItem);
                        }

                        finalList.AddRange(globalItems.Select(x => x.ToWebItem()));

                        return finalList;
                    }
                    else
                    {
                        var globalItems = db.GlobalDataStoreItems.Where(x => (collection == null || x.CollectionName == collection) && (key == null || x.Key == key)).ToList();

                        var finalList = globalItems.Select(x => x.ToWebItem()).ToList();

                        return finalList;
                    }
                }
            }
            catch (HttpResponseException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw CreateHttpException(ex, HttpStatusCode.InternalServerError);
            }
        }

        [JwtWebApiTokenFilter]
        public void Put([FromBody]DataStoreWebPutItem item)
        {
            try
            {
                if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreWrite))
                {
                    throw CreateHttpException(new AuthenticationException("The current user was not authorized to write to the data store."), HttpStatusCode.Unauthorized);
                }

                if (item.Collection == null || item.Key == null)
                {
                    throw CreateHttpException(new AuthenticationException("Collection and key must be specified."), HttpStatusCode.BadRequest);
                }

                ValidateCollectionAndKey(item.Collection, item.Key);

                using (var db = ObservablesContextHelper.CreateContext())
                {
                    if (item.MachineSerialNumber != null)
                    {
                        var machineGuid = db.Machines.Where(x => x.SerialNumber == item.MachineSerialNumber).Select(x => x.Guid).FirstOrDefault();

                        if (machineGuid == null)
                        {
                            throw CreateHttpException(new KeyNotFoundException("The specified machine serial number could not be found."), HttpStatusCode.NotFound);
                        }

                        DataStoreItem dbItem = db.DataStoreItems.FirstOrDefault(x => x.CollectionName == item.Collection && x.Key == item.Key);

                        if (dbItem == null)
                        {
                            if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreCreate))
                            {
                                throw CreateHttpException(new AuthenticationException("The current user was not authorized to create new items on the data store."), HttpStatusCode.Unauthorized);
                            }

                            dbItem = new DataStoreItem();
                            dbItem.Key = item.Key;
                            dbItem.CollectionName = item.Collection;
                            dbItem.MachineGuid = machineGuid;
                            db.DataStoreItems.Add(dbItem);
                        }

                        dbItem.DataType = (int)item.DataType;
                        dbItem.IsDeleted = false;
                        dbItem.IsSynchronized = false;
                        dbItem.LastUpdated = DateTime.UtcNow;
                        dbItem.Value = EFDataStoreHelper.CreateBytes(item.DataType, DataStoreHelper.ParseDataStoreValue(item.DataType, item.Value.ToStringSafe(), item.ProtoMessageType));
                    }
                    else
                    {
                        if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreCreateWriteGlobal))
                        {
                            throw CreateHttpException(new AuthenticationException("The current user was not authorized to write to the global data store."), HttpStatusCode.Unauthorized);
                        }

                        GlobalDataStoreItem dbItem = db.GlobalDataStoreItems.FirstOrDefault(x => x.CollectionName == item.Collection && x.Key == item.Key);

                        if (dbItem == null)
                        {
                            if (!RequestToken.Object.Permissions.Contains(Permissions.DataStoreCreate))
                            {
                                throw CreateHttpException(new AuthenticationException("The current user was not authorized to create new items on the data store."), HttpStatusCode.Unauthorized);
                            }

                            dbItem = new GlobalDataStoreItem();
                            dbItem.Key = item.Key;
                            dbItem.CollectionName = item.Collection;
                            db.GlobalDataStoreItems.Add(dbItem);
                        }

                        dbItem.DataType = (int)item.DataType;
                        dbItem.LastUpdated = DateTime.UtcNow;
                        dbItem.Value = EFDataStoreHelper.CreateBytes(item.DataType, DataStoreHelper.ParseDataStoreValue(item.DataType, item.Value.ToStringSafe(), item.ProtoMessageType));
                    }

                    db.SaveChanges();
                }
            }
            catch (HttpResponseException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw CreateHttpException(ex, HttpStatusCode.InternalServerError);
            }
        }

        private HttpResponseException CreateHttpException(Exception ex, HttpStatusCode code, String message = null)
        {
            return new HttpResponseException(new HttpResponseMessage(code)
            {
                Content = new StringContent(message != null ? message : ex.Message),
                ReasonPhrase = ex.FlattenMessage()
            });
        }

        private void ValidateCollectionAndKey(String collection = null, String key = null)
        {
            if (collection != null)
            {
                if (!DataStoreHelper.ValidateCollectionOrKeyName(collection))
                {
                    throw new ArgumentException("Collection name contains invalid characters.");
                }
            }

            if (key != null)
            {
                if (!DataStoreHelper.ValidateCollectionOrKeyName(key))
                {
                    throw new ArgumentException("Item key contains invalid characters.");
                }
            }
        }

    }

    #region Extension Methods

    public static class IDataStoreExtensions
    {
        public static DataStoreWebItem ToWebItem(this DataStoreItem item, GlobalDataStoreItem globalItem = null)
        {
            IDataStoreItem dsItem = item.ToDataStoreItem();
            DataStoreWebItem webItem = new DataStoreWebItem();
            webItem.Collection = item.CollectionName;
            webItem.Type = globalItem != null ? DataStoreWebItemType.Overrides : DataStoreWebItemType.Local;
            webItem.DataType = dsItem.Type;
            webItem.Date = dsItem.Date;
            webItem.Key = dsItem.Key;
            webItem.LocalValue = dsItem.Value;

            if (webItem.LocalValue is DataStoreProtoObject protoObject)
            {
                webItem.LocalValue = protoObject.Message;
                webItem.ProtoMessageType = protoObject.MessageType;
            }

            if (globalItem != null)
            {
                var dsGlobalItem = globalItem.ToDataStoreItem();

                webItem.GlobalValue = dsGlobalItem.Value;

                if (webItem.GlobalValue is DataStoreProtoObject protoObjectGlobal)
                {
                    webItem.GlobalValue = protoObjectGlobal.Message;
                    webItem.ProtoMessageType = protoObjectGlobal.MessageType;
                }
            }

            return webItem;
        }

        public static DataStoreWebItem ToWebItem(this GlobalDataStoreItem item)
        {
            IDataStoreItem dsItem = item.ToDataStoreItem();
            DataStoreWebItem webItem = new DataStoreWebItem();
            webItem.Collection = item.CollectionName;
            webItem.Type = DataStoreWebItemType.Global;
            webItem.DataType = dsItem.Type;
            webItem.Date = dsItem.Date;
            webItem.Key = dsItem.Key;
            webItem.GlobalValue = dsItem.Value;

            if (webItem.GlobalValue is DataStoreProtoObject protoObject)
            {
                webItem.GlobalValue = protoObject.Message;
                webItem.ProtoMessageType = protoObject.MessageType;
            }

            return webItem;
        }
    }
    #endregion
}