aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Web/Tango.MachineService/Controllers/DataStoreController.cs
blob: 383a59850b279d4513c96b4897596759dff13830 (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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Logging;
using Tango.MachineStudio.Common.Navigation;
using Tango.MachineStudio.Logging.Views;

namespace Tango.MachineStudio.Logging.Navigation
{
    public class LoggingNavigationManager
    {
        private LogManager LogManager = LogManager.Default;

        public void NavigateTo(LoggingNavigationView view)
        {
            LogManager.Log(String.Format("Navigating to view {0}...", view.ToString()));
            MainView.Instance.TransitionControl.NavigateTo(view.ToString());
        }
    }
}
a> 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
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
}