Beispiel #1
0
        private BWebServiceResponse OnRequest_Internal(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            bIsInternalCall =
                BWebUtilities.DoesContextContainHeader(out List <string> ICHVs, out string _, _Context, "internal-call-secret") &&
                BUtility.CheckAndGetFirstStringFromList(ICHVs, out string ICH) &&
                ICH == CommonData.INTERNAL_CALL_PRIVATE_KEY;

            if (_Context.Request.HttpMethod != "DELETE")
            {
                _ErrorMessageAction?.Invoke("User_DeleteUserAccessMethod_ForUser: DELETE method is accepted. But received request method:  " + _Context.Request.HttpMethod);
                return(BWebResponse.MethodNotAllowed("DELETE methods is accepted. But received request method: " + _Context.Request.HttpMethod));
            }

            RequestedUserID        = RestfulUrlParameters[RestfulUrlParameter_UsersKey];
            RequestedAuthMethodKey = WebUtility.UrlDecode(RestfulUrlParameters[RestfulUrlParameter_AccessMethodKey]);

            if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), RequestedUserID, _ErrorMessageAction))
            {
                return(BWebResponse.InternalError("Atomic operation control has failed."));
            }

            var Result = DeleteAccessMethodForUser(_Context, out bool bSetClearanceForApiKey, out string ApiKey, _ErrorMessageAction);

            Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), RequestedUserID, _ErrorMessageAction);
            if (bSetClearanceForApiKey)
            {
                Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + ApiKey, _ErrorMessageAction);
            }

            return(Result);
        }
Beispiel #2
0
        public BWebServiceResponse ProcessRequest(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            bDoNotGetDBClearance =
                BWebUtilities.DoesContextContainHeader(out List <string> DNGDBCs, out string _, _Context, "do-not-get-db-clearance") &&
                BUtility.CheckAndGetFirstStringFromList(DNGDBCs, out string DNGDBC) &&
                DNGDBC == "true";

            BTaskWrapper.Run(() =>
            {
                var Response = OnRequestCallback?.Invoke(_Context, _ErrorMessageAction);
                if (Response.HasValue)
                {
                    Responses.Enqueue(Response.Value);
                }

                try
                {
                    WaitUntilSignal.Set();
                }
                catch (Exception) { }
            });

            try
            {
                WaitUntilSignal.WaitOne();
            }
            catch (Exception) { }

            if (!Responses.TryDequeue(out BWebServiceResponse FirstResponse))
            {
                FirstResponse = BWebResponse.InternalError("Unexpected error in concurrence.");
            }
            return(FirstResponse);
        }
Beispiel #3
0
        public override BWebServiceResponse OnRequest(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            bool bIsInternalCall =
                BWebUtilities.DoesContextContainHeader(out List <string> ICHVs, out string _, _Context, "internal-call-secret") &&
                BUtility.CheckAndGetFirstStringFromList(ICHVs, out string _);

            if (bIsInternalCall)
            {
                var ErrorMessages = new JArray();

                var Result = OnRequestPP(_Context, (string _Message) =>
                {
                    _ErrorMessageAction?.Invoke(_Message);
                    ErrorMessages.Add(_Message);
                });

                try
                {
                    if (Result.ResponseContent.Type == EBStringOrStreamEnum.String)
                    {
                        var Parsed = JObject.Parse(Result.ResponseContent.String);
                        Parsed["internalCallErrorMessages"] = ErrorMessages;
                        Result = new BWebServiceResponse(Result.StatusCode, Result.Headers, new BStringOrStream(Parsed.ToString()), Result.ResponseContentType);
                    }
                }
                catch (Exception) {}

                return(Result);
            }
            return(OnRequestPP(_Context, _ErrorMessageAction));
        }
Beispiel #4
0
        private BWebServiceResponse OnRequest_Internal(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            if (_Context.Request.HttpMethod != "POST")
            {
                _ErrorMessageAction?.Invoke("SSOAzureTokenRefreshRequest: POST method is accepted. But received request method:  " + _Context.Request.HttpMethod);

                return(BWebResponse.MethodNotAllowed("POST method is accepted. But received request method:  " + _Context.Request.HttpMethod));
            }

            if (!BWebUtilities.DoesContextContainHeader(out List <string> ClientAuthorizationHeaderValues, out string _, _Context, "client-authorization") ||
                !BUtility.CheckAndGetFirstStringFromList(ClientAuthorizationHeaderValues, out string ClientAuthorization) ||
                ClientAuthorization.Length == 0)
            {
                return(BWebResponse.BadRequest("Authorization header must be set validly."));
            }

            //Check and try refresh if expired
            if (new Controller_SSOAccessToken(ClientAuthorization, DatabaseService, MemoryService, AzureAD_AppID, AzureAD_ClientSecret, SSOSuperAdmins, _ErrorMessageAction)
                .PerformCheckAndRefresh(
                    out Controller_SSOAccessToken.EPerformCheckAndRefreshSuccessStatus SuccessStatus,
                    out ClientAuthorization,
                    out string UserID,
                    out string EmailAddressWithoutPostfix) &&
                ClientAuthorization != null && ClientAuthorization.Length > 0)
            {
                return(BWebResponse.StatusOK("Success.", new JObject()
                {
                    ["token"] = ClientAuthorization,
                    ["status"] = SuccessStatus == Controller_SSOAccessToken.EPerformCheckAndRefreshSuccessStatus.Refreshed ? "Refreshed" : "AlreadyValid",
                    ["userId"] = UserID,
                    ["email"] = EmailAddressWithoutPostfix
                }));
            }

            return(BWebResponse.Unauthorized("Please re-login."));
        }
Beispiel #5
0
        public static InterServicesRequestResponse InterServicesRequest(
            InterServicesRequestRequest _Request,
            bool _bKillProcessOnAddAccessTokenForServiceExecutionFailure = true,
            Action <string> _ErrorMessageAction = null)
        {
            var             bHttpRequestSuccess            = false;
            var             HttpRequestResponseCode        = BWebResponse.Error_InternalError_Code;
            var             HttpRequestResponseContentType = "";
            BStringOrStream HttpRequestResponseContent     = null;
            Dictionary <string, IEnumerable <string> > HttpRequestResponseHeaders = null;

            var Request = (HttpWebRequest)WebRequest.Create(_Request.DestinationServiceUrl);

            Request.Method = _Request.RequestMethod;
            Request.ServerCertificateValidationCallback = (a, b, c, d) => true;
            Request.AllowAutoRedirect = false;

            if (_Request.bWithAuthToken)
            {
                //If context-headers already contain authorization; we must rename it to client-authorization to prevent override.
                if (_Request.UseContextHeaders != null &&
                    BWebUtilities.DoesContextContainHeader(out List <string> AuthorizationHeaderValues, out string CaseSensitive_FoundHeaderKey, _Request.UseContextHeaders, "authorization") &&
                    BUtility.CheckAndGetFirstStringFromList(AuthorizationHeaderValues, out string ClientAuthorization))
                {
                    _Request.UseContextHeaders.Request.Headers.Remove(CaseSensitive_FoundHeaderKey);
                    _Request.UseContextHeaders.Request.Headers.Add("client-authorization", ClientAuthorization);
                }
            }

            var ExcludeHeaderKeysForRequest = LowerContentOfStrings(_Request.ExcludeHeaderKeysForRequest);

            if (_Request.UseContextHeaders != null)
            {
                InsertHeadersFromContextInto(_Request.UseContextHeaders, (string _Key, string _Value) =>
                {
                    if (ExcludeHeaderKeysForRequest != null && ExcludeHeaderKeysForRequest.Contains(_Key.ToLower()))
                    {
                        return;
                    }

                    Request.Headers.Add(_Key, _Value);
                });
            }
            if (_Request.Headers != null)
            {
                InsertHeadersFromDictionaryInto(_Request.Headers, (string _Key, string _Value) =>
                {
                    if (ExcludeHeaderKeysForRequest != null && ExcludeHeaderKeysForRequest.Contains(_Key.ToLower()))
                    {
                        return;
                    }

                    Request.Headers.Add(_Key, _Value);
                });
            }

            try
            {
                if (_Request.RequestMethod != "GET" && /*&& _Request.RequestMethod != "DELETE"*/
                    _Request.Content != null && ((_Request.Content.Type == EBStringOrStreamEnum.Stream && _Request.Content.Stream != null) || (_Request.Content.Type == EBStringOrStreamEnum.String && _Request.Content.String != null && _Request.Content.String.Length > 0)))
                {
                    Request.ContentType = _Request.ContentType;

                    using (var OStream = Request.GetRequestStream())
                    {
                        if (_Request.Content.Type == EBStringOrStreamEnum.Stream)
                        {
                            _Request.Content.Stream.CopyTo(OStream);
                        }
                        else
                        {
                            using (var RStream = new StreamWriter(OStream))
                            {
                                RStream.Write(_Request.Content.String);
                            }
                        }
                    }
                }

                try
                {
                    using (var Response = (HttpWebResponse)Request.GetResponse())
                    {
                        AnalyzeResponse(Response, out bHttpRequestSuccess, out HttpRequestResponseCode, out HttpRequestResponseContentType, out HttpRequestResponseContent, out HttpRequestResponseHeaders, _ErrorMessageAction);
                    }
                }
                catch (Exception e)
                {
                    if (e is WebException)
                    {
                        using (var ErrorResponse = (HttpWebResponse)(e as WebException).Response)
                        {
                            AnalyzeResponse(ErrorResponse, out bHttpRequestSuccess, out HttpRequestResponseCode, out HttpRequestResponseContentType, out HttpRequestResponseContent, out HttpRequestResponseHeaders, _ErrorMessageAction);
                        }
                    }
                    else
                    {
                        _ErrorMessageAction?.Invoke("Error: InterServicesRequest: " + e.Message + ", Trace: " + e.StackTrace);
                        bHttpRequestSuccess = false;
                    }
                }
            }
            catch (Exception e)
            {
                _ErrorMessageAction?.Invoke("Error: InterServicesRequest: " + e.Message + ", Trace: " + e.StackTrace);
                bHttpRequestSuccess = false;
            }

            if (!bHttpRequestSuccess)
            {
                _ErrorMessageAction?.Invoke("Error: Request has failed due to an internal api gateway error. Service endpoint: " + _Request.DestinationServiceUrl);
                return(InterServicesRequestResponse.InternalErrorOccured("Request has failed due to an internal api gateway error."));
            }

            if (_Request.UseContextHeaders != null)
            {
                InsertHeadersFromDictionaryIntoContext(HttpRequestResponseHeaders, _Request.UseContextHeaders);
            }

            return(new InterServicesRequestResponse()
            {
                bSuccess = true,
                ResponseCode = HttpRequestResponseCode,
                ContentType = HttpRequestResponseContentType,
                ResponseHeaders = HttpRequestResponseHeaders,
                Content = HttpRequestResponseContent
            });
        }
Beispiel #6
0
        private BWebServiceResponse OnRequest_Internal(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            if (!UrlParameters.TryGetValue("redirect_url", out string RedirectUrlEncoded) || RedirectUrlEncoded.Length == 0)
            {
                RedirectUrlEncoded = DEFAULT_REDIRECT_URL_ENCODED;
            }

            if (_Context.Request.HttpMethod != "GET")
            {
                _ErrorMessageAction?.Invoke("SSOLoginRequest: GET method is accepted. But received request method:  " + _Context.Request.HttpMethod);

                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, BWebResponse.Error_BadRequest_Code, "GET method is accepted. But received request method:  " + _Context.Request.HttpMethod));
            }

            if (!UrlParameters.TryGetValue("tenant", out string TenantName) || TenantName.Length == 0)
            {
                TenantName = DEFAULT_TENANT_NAME;
            }
            else
            {
                TenantName = TenantName.ToLower();
            }

            //Existing token from header
            string ClientAuthorization = null;

            if (BWebUtilities.DoesContextContainHeader(out List <string> ClientAuthorizationHeaderValues, out string _, _Context, "client-authorization"))
            {
                BUtility.CheckAndGetFirstStringFromList(ClientAuthorizationHeaderValues, out ClientAuthorization);
                if (ClientAuthorization != null && ClientAuthorization.Length == 0)
                {
                    ClientAuthorization = null;
                }
            }

            //Existing token from url parameters
            //Note: Must be token type prepended. Example: ?existing_token=bearer%20abc123123
            if (!UrlParameters.TryGetValue("existing_token", out string ExistingToken) || ExistingToken.Length == 0)
            {
                ExistingToken = null;
            }
            else
            {
                ExistingToken = WebUtility.UrlDecode(ExistingToken);
            }

            //If both existing tokens are non-null; it is error
            if (ClientAuthorization != null && ExistingToken != null)
            {
                _ErrorMessageAction?.Invoke("Error: SSOLoginRequest: Both existing tokens from url parameters and headers are non-null.");

                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, BWebResponse.Error_BadRequest_Code, "Both existing tokens from url parameters and headers are non-null."));
            }

            //From now on, use ClientAuthorization; not ExistingToken
            if (ExistingToken != null)
            {
                ClientAuthorization = ExistingToken;
            }

            //Check and try refresh if expired
            if (ClientAuthorization != null &&
                new Controller_SSOAccessToken(ClientAuthorization, DatabaseService, MemoryService, AzureAD_AppID, AzureAD_ClientSecret, SSOSuperAdmins, _ErrorMessageAction)
                .PerformCheckAndRefresh(
                    out Controller_SSOAccessToken.EPerformCheckAndRefreshSuccessStatus _,
                    out ClientAuthorization,
                    out string UserID,
                    out string _))
            {
                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), false, 0, null, UserID, ClientAuthorization));
            }

            //Get api passthrough endpoint from internal set state
            var LocalErrorString = "";

            if (!InternalSetState.GetValueFromMemoryService(
                    out string ApiPassthroughEndpoint,
                    InternalSetState.API_PASSTHROUGH_PUBLIC_ENDPOINT_PROPERTY,
                    MemoryService,
                    (string _Message) =>
            {
                LocalErrorString = _Message;
                _ErrorMessageAction?.Invoke(_Message);
            }))
            {
                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, 500, LocalErrorString));
            }

            string ServersideRedirectUrl = WebUtility.UrlEncode(ApiPassthroughEndpoint + "/auth/login/azure/callback");

            string AzureAuthenticationEndpointBase =
                "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
                + "?client_id=" + AzureAD_AppID
                + "&response_type=id_token code"
                + "&redirect_uri=" + ServersideRedirectUrl;

            var    TrialCount = 0;
            string SSOStateUniqueID;
            BMemoryQueryParameters SSOStateUniqueID_QueryParameters;

            do
            {
                if (!BUtility.CalculateStringMD5(BUtility.RandomString(32, true), out SSOStateUniqueID, _ErrorMessageAction))
                {
                    return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, 500, "SSO State ID generation has failed."));
                }

                SSOStateUniqueID_QueryParameters = SSOStateMEntry.ID_SSO_STATE_MEMORY_SERVICE_KEY(SSOStateUniqueID);

                if (!MemoryService.SetKeyValueConditionally(
                        SSOStateUniqueID_QueryParameters,
                        new Tuple <string, BPrimitiveType>(
                            SSOStateMEntry.HASH_KEY,
                            new BPrimitiveType(JsonConvert.SerializeObject(
                                                   new SSOStateMEntry()
                {
                    ServersideRedirectUrl = ServersideRedirectUrl,
                    TenantName = TenantName,
                    Status = SSOStateMEntry.STATUS_AUTHENTICATING
                })
                                               )
                            ),
                        _ErrorMessageAction))
                {
                    SSOStateUniqueID = null;
                }
            } while (SSOStateUniqueID == null && ++TrialCount < 5);

            if (SSOStateUniqueID == null)
            {
                return(SSOCommon.MakeCallerRedirected(WebUtility.UrlDecode(RedirectUrlEncoded), true, 500, "Unique SSO State ID generation has failed."));
            }
            MemoryService.SetKeyExpireTime(SSOStateUniqueID_QueryParameters, TimeSpan.FromSeconds(120), _ErrorMessageAction);

            var AzureAuthenticationEndpoint = AzureAuthenticationEndpointBase
                                              + "&scope=" + SSOCommon.SCOPE_URL_ENCODED
                                              + "&response_mode=form_post"
                                              + "&nonce=" + SSOStateUniqueID
                                              + "&state="
                                              + WebUtility.UrlEncode(
                "redirect_url=" + RedirectUrlEncoded +
                "&tenant=" + TenantName +
                "&state=" + SSOStateUniqueID);

            return(SSOCommon.MakeCallerRedirected(AzureAuthenticationEndpoint, false, 0, null));
        }
Beispiel #7
0
        private bool AccessCheck(out BWebServiceResponse _FailureResponse, out bool _bSSOTokenRefreshed, out string _NewSSOTokenAfterRefresh, HttpListenerContext _Context, Action <string> _ErrorMessageAction = null)
        {
            _FailureResponse = new BWebServiceResponse();

            _bSSOTokenRefreshed      = false;
            _NewSSOTokenAfterRefresh = "";

            if (bAuthCheck)
            {
                //Check for authorization header
                if (!BWebUtilities.DoesContextContainHeader(out List <string> Authorization, out string _, _Context, "authorization"))
                {
                    _FailureResponse = BWebResponse.Unauthorized("Authorization header must be set.");
                    return(false);
                }

                var RequestObject = new JObject()
                {
                    ["forUrlPath"]    = _Context.Request.RawUrl,
                    ["requestMethod"] = _Context.Request.HttpMethod
                };
                if (BUtility.CheckAndGetFirstStringFromList(Authorization, out string _Authorization))
                {
                    RequestObject["authorization"] = _Authorization;
                }
                else //Zero length
                {
                    _FailureResponse = BWebResponse.Unauthorized("Authorization header must be set.");
                    return(false);
                }

                GetTracingService()?.On_FromGatewayToService_Sent(_Context, _ErrorMessageAction);
                var Result = BWebServiceExtraUtilities.InterServicesRequest(new BWebServiceExtraUtilities.InterServicesRequestRequest()
                {
                    DestinationServiceUrl = AuthServiceBaseUrl + "/auth/access_check",
                    RequestMethod         = "POST",
                    ContentType           = "application/json",
                    Content           = new BStringOrStream(RequestObject.ToString()),
                    bWithAuthToken    = true,
                    UseContextHeaders = _Context,
                },
                                                                            false,
                                                                            _ErrorMessageAction);
                GetTracingService()?.On_FromServiceToGateway_Received(_Context, _ErrorMessageAction);

                if (!Result.bSuccess || Result.ResponseCode >= 400)
                {
                    if (Result.ResponseCode == BWebResponse.Error_Unauthorized_Code ||
                        Result.ResponseCode == BWebResponse.Error_Forbidden_Code)
                    {
                        _FailureResponse = new BWebServiceResponse(Result.ResponseCode, Result.Content, Result.ContentType);
                        return(false);
                    }

                    _ErrorMessageAction?.Invoke("Access check internal call has failed: Response: " + Result.ResponseCode + " -> " + Result.Content.String + ", Request: " + RequestObject.ToString());
                    _FailureResponse = BWebResponse.InternalError("Internal access check call has failed.");
                    return(false);
                }

                var ResponseContent = Result.Content.ToString();
                try
                {
                    var Parsed = JObject.Parse(ResponseContent);
                    Authenticated_UserID        = (string)Parsed["userId"];
                    Authenticated_UserName      = (string)Parsed["userName"];
                    Authenticated_UserEmail     = (string)Parsed["userEmail"];
                    Authenticated_AuthMethodKey = (string)Parsed["authMethodKey"];
                    _bSSOTokenRefreshed         = (bool)Parsed["ssoTokenRefreshed"];
                    _NewSSOTokenAfterRefresh    = (string)Parsed["newSSOTokenAfterRefresh"];
                }
                catch (Exception e)
                {
                    _ErrorMessageAction?.Invoke("HandleRequest->AccessCheck: Error during content parse: " + ResponseContent + ", Message: " + e.Message + ", Trace: " + e.StackTrace);
                    _FailureResponse = BWebResponse.InternalError("Request has failed due to an internal api gateway error.");
                    return(false);
                }

                _Context.Request.Headers.Set("authorized-u-id", Authenticated_UserID);
                _Context.Request.Headers.Set("authorized-u-name", Authenticated_UserName);
                _Context.Request.Headers.Set("authorized-u-email", Authenticated_UserEmail);
                _Context.Request.Headers.Set("authorized-u-auth-key", Authenticated_AuthMethodKey);
            }
            return(true);
        }
Beispiel #8
0
        private BWebServiceResponse CreateUser(HttpListenerContext _Context, Action <string> _ErrorMessageAction)
        {
            var NewUserParameters = new JObject();

            bool bIsInternalCall =
                BWebUtilities.DoesContextContainHeader(out List <string> ICHVs, out string _, _Context, "internal-call-secret") &&
                BUtility.CheckAndGetFirstStringFromList(ICHVs, out string ICH) &&
                ICH == CommonData.INTERNAL_CALL_PRIVATE_KEY;

            using (var InputStream = _Context.Request.InputStream)
            {
                using (var ResponseReader = new StreamReader(InputStream))
                {
                    try
                    {
                        var ParsedBody     = JObject.Parse(ResponseReader.ReadToEnd());
                        var PropertiesList = new List <string>();
                        foreach (var Child in ParsedBody)
                        {
                            PropertiesList.Add(Child.Key);
                        }

                        foreach (var MustHaveProperty in UserDBEntry.MustHaveProperties)
                        {
                            if (!PropertiesList.Contains(MustHaveProperty))
                            {
                                return(BWebResponse.BadRequest("Request body must contain all necessary fields."));
                            }
                        }

                        foreach (var Child in ParsedBody)
                        {
                            if (UserDBEntry.UpdatableProperties.Contains(Child.Key))
                            {
                                if (!UserDBEntry.UpdatablePropertiesValidityCheck[Child.Key](Child.Value))
                                {
                                    return(BWebResponse.BadRequest("Given field " + Child.Key + " has invalid value."));
                                }
                                NewUserParameters[Child.Key] = Child.Value;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        _ErrorMessageAction?.Invoke("User_CreateListUsers->UpdateUserInfo: Read request body stage has failed. Exception: " + e.Message + ", Trace: " + e.StackTrace);
                        return(BWebResponse.BadRequest("Malformed request body. Request must be a valid json form."));
                    }
                }
            }

            int    ExistenceTrial = 0;
            string NewUserID      = null;

            while (NewUserID == null && ExistenceTrial < 3)
            {
                if (!UserDBEntry.GenerateUserID(out NewUserID, _ErrorMessageAction))
                {
                    return(BWebResponse.InternalError("User ID generation has failed."));
                }

                if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), NewUserID, _ErrorMessageAction))
                {
                    return(BWebResponse.InternalError("Atomic operation control has failed."));
                }

                if (!DatabaseService.GetItem(
                        UserDBEntry.DBSERVICE_USERS_TABLE(),
                        UserDBEntry.KEY_NAME_USER_ID,
                        new BPrimitiveType(NewUserID),
                        UserDBEntry.MustHaveProperties,
                        out JObject ExistenceCheck,
                        _ErrorMessageAction))
                {
                    return(BWebResponse.InternalError("Database existence check operation has failed."));
                }
                if (ExistenceCheck != null)
                {
                    Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), NewUserID, _ErrorMessageAction);
                    NewUserID = null;
                    ExistenceTrial++;
                }
                else
                {
                    break;
                }
            }
            if (NewUserID == null)
            {
                return(BWebResponse.InternalError("Unique ID generation operation has failed."));
            }

            //For other elements to be created without any elements
            var NewUserObject = JsonConvert.DeserializeObject <UserDBEntry>(NewUserParameters.ToString());

            bool bEmailAtomicnessSet = false, bUsernameAtomicnessSet = false;

            try
            {
                if (NewUserObject.UserEmail != null && NewUserObject.UserEmail.Length > 0)
                {
                    NewUserObject.UserEmail = NewUserObject.UserEmail.ToLower();
                    if (!bIsInternalCall && NewUserObject.UserEmail.EndsWith(Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX))
                    {
                        return(BWebResponse.BadRequest("E-mail address cannot end with " + Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX));
                    }

                    if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL + ":" + NewUserObject.UserEmail, _ErrorMessageAction))
                    {
                        return(BWebResponse.InternalError("Atomic operation control has failed."));
                    }
                    bEmailAtomicnessSet = true;

                    if (!DatabaseService.GetItem(
                            UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(),
                            UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL,
                            new BPrimitiveType(NewUserObject.UserEmail),
                            UniqueUserFieldsDBEntry.Properties,
                            out JObject _ExistenceCheck,
                            _ErrorMessageAction))
                    {
                        return(BWebResponse.InternalError("Database operation failed."));
                    }
                    if (_ExistenceCheck != null)
                    {
                        return(BWebResponse.Conflict("A user with same user e-mail already exists."));
                    }
                }
                if (NewUserObject.UserName != null && NewUserObject.UserName.Length > 0)
                {
                    if (!bIsInternalCall && NewUserObject.UserName.EndsWith(Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX))
                    {
                        return(BWebResponse.BadRequest("Username cannot end with " + Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX));
                    }

                    if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME + ":" + NewUserObject.UserName, _ErrorMessageAction))
                    {
                        return(BWebResponse.InternalError("Atomic operation control has failed."));
                    }
                    bUsernameAtomicnessSet = true;

                    if (!DatabaseService.GetItem(
                            UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(),
                            UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME,
                            new BPrimitiveType(NewUserObject.UserName),
                            UniqueUserFieldsDBEntry.Properties,
                            out JObject _ExistenceCheck,
                            _ErrorMessageAction))
                    {
                        return(BWebResponse.InternalError("Database operation failed."));
                    }
                    if (_ExistenceCheck != null)
                    {
                        return(BWebResponse.Conflict("A user with same username already exists."));
                    }
                }

                if (!Controller_Rights_Internal.Get().PerformGetRequestToGetGloballySharedModelIds(out List <string> GloballySharedModelIds, _ErrorMessageAction))
                {
                    return(BWebResponse.InternalError("Get-globally-shared-models operation failed."));
                }
                NewUserObject.UserSharedModels = GloballySharedModelIds;

                if (!DatabaseService.UpdateItem(
                        UserDBEntry.DBSERVICE_USERS_TABLE(),
                        UserDBEntry.KEY_NAME_USER_ID,
                        new BPrimitiveType(NewUserID),
                        JObject.Parse(JsonConvert.SerializeObject(NewUserObject)),
                        out JObject _, EBReturnItemBehaviour.DoNotReturn,
                        DatabaseService.BuildAttributeNotExistCondition(UserDBEntry.KEY_NAME_USER_ID),
                        _ErrorMessageAction))
                {
                    return(BWebResponse.InternalError("Database operation failed."));
                }

                if (!Controller_Rights_Internal.Get().GetUserDefaultRights(out JArray DefaultRights, NewUserID, _ErrorMessageAction))
                {
                    Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget(
                        _Context,
                        UserDBEntry.DBSERVICE_USERS_TABLE(),
                        UserDBEntry.KEY_NAME_USER_ID,
                        new BPrimitiveType(NewUserID));
                    return(BWebResponse.InternalError("Default rights obtaining operation has failed."));
                }

                if (!Controller_Rights_Internal.Get().GrantUserWithRights(true, NewUserID, DefaultRights, _ErrorMessageAction))
                {
                    Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget(
                        _Context,
                        UserDBEntry.DBSERVICE_USERS_TABLE(),
                        UserDBEntry.KEY_NAME_USER_ID,
                        new BPrimitiveType(NewUserID));
                    return(BWebResponse.InternalError("Right granting operation has failed."));
                }

                if (NewUserObject.UserEmail != null && NewUserObject.UserEmail.Length > 0)
                {
                    Controller_DeliveryEnsurer.Get().DB_UpdateItem_FireAndForget(
                        _Context,
                        UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(),
                        UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL,
                        new BPrimitiveType(NewUserObject.UserEmail),
                        new JObject()
                    {
                        [UserDBEntry.KEY_NAME_USER_ID] = NewUserID
                    });
                }
                if (NewUserObject.UserName != null && NewUserObject.UserName.Length > 0)
                {
                    Controller_DeliveryEnsurer.Get().DB_UpdateItem_FireAndForget(
                        _Context,
                        UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(),
                        UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME,
                        new BPrimitiveType(NewUserObject.UserName),
                        new JObject()
                    {
                        [UserDBEntry.KEY_NAME_USER_ID] = NewUserID
                    });
                }

                Controller_UserActions.Get().BroadcastUserAction(new Action_UserCreated(
                                                                     NewUserID,
                                                                     NewUserObject.UserEmail,
                                                                     NewUserObject.UserName
                                                                     ), _ErrorMessageAction);
            }
            finally
            {
                Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), NewUserID, _ErrorMessageAction);
                if (bEmailAtomicnessSet)
                {
                    Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL + ":" + NewUserObject.UserEmail, _ErrorMessageAction);
                }
                if (bUsernameAtomicnessSet)
                {
                    Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME + ":" + NewUserObject.UserName, _ErrorMessageAction);
                }
            }

            return(BWebResponse.StatusCreated("User has been created.", new JObject()
            {
                [UserDBEntry.KEY_NAME_USER_ID] = NewUserID
            }));
        }