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); }
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); }
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)); }
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.")); }
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 }); }
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)); }
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); }
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 })); }