Esempio n. 1
0
        /// <summary>
        /// Execute a transaction (list of requests) from a client
        /// </summary>
        /// <param name="requestId"></param>
        /// <param name="label"></param>
        /// <param name="requests"></param>
        /// <param name="transaction"></param>
        /// <param name="notify">true if the notification must be sent to the caller</param>
        /// <returns>RequestId, Error, Record</returns>
        private JObject ExecuteTransaction(int requestId, JObject label, JObject[] requests, bool transaction, bool notify)
        {
            int index = 0;

            if (!Context.Request.User.Identity.IsAuthenticated)
            {
                // Lost the session for unconnecting period ... all changes into the client is definitively lost ... reload the page
                Error($"The user is not authenticated ... Reload the page!");
                return(MakeErrorResult("EN", "ERR_UNAUTHENTICATED"));
            }

            try
            {
                // nothing to execute => Throw an error

                if (requests == null || requests.Length == 0)
                {
                    Error("No requests to execute");
                    throw new ExceptionDefinitionRecord("ERR_REQUEST_UNKNOWN");
                }

                Info($"Executing the transaction [{requestId} - '{label.ToString(Formatting.None)}'] containing {requests.Length} requests ...");
                if (IsDebug())
                {
                    foreach (JObject request in requests)
                    {
                        Debug($"Executing the request: {request.ToString(Formatting.None)} ...");
                    }
                }

                // Check if the request is correctly formatted

                index = 0;
                foreach (JObject request in requests)
                {
                    // convert the request property

                    string table = null;
                    if (request["table"] != null &&
                        request["table"].Type == JTokenType.String)
                    {
                        table = request["table"].ToObject <string>();
                    }

                    string action = null;
                    if (request["action"] != null &&
                        request["action"].Type == JTokenType.String)
                    {
                        action = request["action"].ToObject <string>();
                    }

                    JObject identity = request["identity"] as JObject;

                    if (table == null ||
                        action == null ||
                        !(request["record"] is JObject record) ||
                        action == null)
                    {
                        Error($"The request[{index}] isn't correctly formatted!");
                        throw new ExceptionDefinitionRecord("ERR_UNAUTHORIZED");
                    }

                    index++;
                }

                // From the current user, check if the user can update database

                using (DatabaseManager requester = Syncytium.Managers.DatabaseManager.CreateDatabase(Context.ConnectionId, int.Parse(Context.Request.User.Identity.Name)))
                {
                    // Get the current connection properties

                    ConnectionRecord currentConnection = requester.Database._Connection.FirstOrDefault(c => c.ConnectionId.Equals(Context.ConnectionId) &&
                                                                                                       c.Machine.Equals(Environment.MachineName));
                    if (currentConnection == null)
                    {
                        Error($"The connection '{Context.ConnectionId}' doesn't exist!");
                        throw new ExceptionDefinitionRecord("ERR_CONNECTION");
                    }

                    // Is this connection authorized to start the dialog ?

                    if (!currentConnection.Allow || !currentConnection.Status)
                    {
                        Error("Not allowed!");
                        throw new ExceptionDefinitionRecord("ERR_UNAUTHORIZED");
                    }

                    // check if the user has the rights to execute this request

                    if (String.IsNullOrWhiteSpace(currentConnection.Area))
                    {
                        Error("No area defined for the user");
                        throw new ExceptionDefinitionRecord("ERR_UNAUTHORIZED");
                    }

                    if (ConfigurationManager.Schemas[currentConnection.Area] == null)
                    {
                        Error($"The schema of the module '{currentConnection.Area}' doesn't exist!");
                        throw new ExceptionDefinitionRecord("ERR_SCHEMA");
                    }

                    // Retrieve the last requestId of this user

                    RequestIdRecord requestIdRecord = requester.Database._RequestId.FirstOrDefault(r => r.UserId == currentConnection.UserId);
                    if (requestIdRecord == null)
                    {
                        requestIdRecord = new RequestIdRecord {
                            UserId = currentConnection.UserId, RequestId = 0, Date = DateTime.Now
                        };
                        requestIdRecord = requester.Database._RequestId.Add(requestIdRecord);
                    }

                    if (requestId < requestIdRecord.RequestId)
                    {
                        Warn($"The request '{requestId}' has already been executed!");
                        throw new ExceptionDefinitionRecord("ERR_REQUEST_ALREADY_EXECUTED");
                    }

                    if (requestId > requestIdRecord.RequestId)
                    {
                        Warn($"The request id expected is '{requestIdRecord.RequestId}' (your request id is '{requestId}')!");
                        throw new ExceptionDefinitionRecord("ERR_SYNCHRONIZED");
                    }

                    if (IsVerbose())
                    {
                        Verbose($"The request Id '{requestId}' is expected");
                    }

                    // Post the event into the event queue

                    DatabaseQueue.Instance.Produce(currentConnection, requestId, label, requests, transaction, notify);

                    // Update last connection date and the last requestId of the user

                    requestIdRecord.RequestId++;
                    currentConnection.ConnectionLast = DateTime.Now;

                    try
                    {
                        requester.Database.SaveChanges();
                    }
                    catch (System.Data.Entity.Infrastructure.DbUpdateConcurrencyException)
                    {
                        Warn("An exception occurs on saving the last connection due to the disconnection of the user ...");
                    }
                    catch (System.Data.Entity.Infrastructure.DbUpdateException)
                    {
                        Warn("An exception occurs on saving the last connection due to the concurrency update ...");
                    }

                    JObject result = null;
                    if (transaction)
                    {
                        result = new JObject
                        {
                            ["RequestId"]   = requestId,
                            ["Transaction"] = new JArray(requests)
                        };
                    }
                    else
                    {
                        result = new JObject
                        {
                            ["RequestId"] = requestId,
                            ["Record"]    = requests[0]["record"]
                        };
                    }

                    return(result);
                }
            }
            catch (ExceptionDefinitionRecord ex)
            {
                Error($"The transaction '{requestId}' can't be executed due to some errors ({JsonConvert.SerializeObject(ex.Errors)})");
                return(MakeErrorResult(requestId, ex.Errors));
            }
            catch (System.Exception ex)
            {
                Exception("An exception occurs on executing the transaction", ex);
                return(MakeErrorResult(requestId, "ERR_EXCEPTION_UNEXPECTED"));
            }
        }
Esempio n. 2
0
        /// <summary>
        /// The client starts the initialization process and has to declare its area
        /// </summary>
        /// <param name="area"></param>
        /// <param name="moduleId"></param>
        /// <returns>the database schema correspnding to the user's profile and its area:
        ///     Version         = database version
        ///     Schema          = database schema
        ///     DefaultLanguage = default language (user's language or default language of the application)
        ///     User            = user's profile
        ///     LastRequestId   = last request id of the user
        /// </returns>
        public JObject Initialize(string area, int moduleId)
        {
            string  defaultLanguage = "EN";
            int     versionDatabase = 0;
            int     lastRequestId   = 0;
            IUser   user            = null;
            IModule module          = null;

            Info($"Initializing connection within the area '{area}' ({moduleId}) ...");

            if (_userManager == null)
            {
                Error("Unable to open the connection. UserManager is undefined!");
                throw new ExceptionDefinitionRecord("ERR_CONNECTION");
            }

            // Retrieve database information

            defaultLanguage = ConfigurationManager.DefaultLanguage;
            ParameterRecord parameterVersion = Database._Parameter.FirstOrDefault(p => p.Key.Equals("Database.Version"));

            if (parameterVersion != null)
            {
                versionDatabase = int.Parse(parameterVersion.Value);
            }

            // Retrieve the current user and its language

            user = _userManager.GetById(_userId);
            if (user == null)
            {
                Warn("The user doesn't exist!");
                throw new ExceptionDefinitionRecord("ERR_CONNECTION");
            }

            module = _userManager.GetModule(user, moduleId);
            if (module == null)
            {
                Warn("The module doesn't exist!");
                throw new ExceptionDefinitionRecord("ERR_CONNECTION");
            }

            // Retrieve the connection

            ConnectionRecord currentConnection = Database._Connection.FirstOrDefault(c => c.ConnectionId.Equals(_connectionId) &&
                                                                                     c.Machine.Equals(Environment.MachineName));

            if (currentConnection == null)
            {
                Warn("The connection doesn't exist. Open the new connection!");
                throw new ExceptionDefinitionRecord("ERR_CONNECTION");
            }

            // Retrieve the database schema

            DSSchema.DSDatabase schema = ConfigurationManager.Schemas[area];
            if (schema == null)
            {
                Error("No schema available!");
                throw new ExceptionDefinitionRecord("ERR_SCHEMA");
            }

            // Is this connection authorized to start the dialog ?

            if (!currentConnection.Allow)
            {
                Error("Not allowed!");
                throw new ExceptionDefinitionRecord("ERR_UNAUTHORIZED");
            }

            // Retrieve the last requestId of this user

            RequestIdRecord requestId = Database._RequestId.FirstOrDefault(r => r.UserId == _userId);

            if (requestId != null)
            {
                lastRequestId = requestId.RequestId;
            }

            // Set the area of the connection and notify that the connection is initialized

            currentConnection.Area           = area;
            currentConnection.ModuleId       = module.Id;
            currentConnection.Profile        = module.Profile;
            currentConnection.Status         = true;
            currentConnection.ConnectionLast = DateTime.Now;
            Database.SaveChanges();
            Info($"The connection '{currentConnection}' is linked to the area '{area}'");

            // define the response

            JObject result = new JObject
            {
                ["Version"]         = versionDatabase,
                ["Schema"]          = schema.ToJSON(area, currentConnection.Profile, Database.GetCache(schema)),
                ["DefaultLanguage"] = defaultLanguage,
                ["CurrentUserId"]   = user == null ? -1 : user.Id,
                ["CurrentModuleId"] = moduleId,
                ["LastRequestId"]   = lastRequestId
            };
            JObject settings = new JObject();

            foreach (KeyValuePair <string, string> setting in ConfigurationManager.Settings)
            {
                if (!setting.Key.StartsWith("Syncytium.Client."))
                {
                    continue;
                }

                settings[setting.Key.Substring("Syncytium.Client.".Length)] = setting.Value;
            }
            result["Parameters"] = settings;

            return(result);
        }