private bool FindMissingUsersInDatabase(out List <UserPrincipal> _UsersToBePut, List <UserPrincipal> _Users, Action <string> _ErrorMessageAction) { _UsersToBePut = null; var TmpDictionary = new Dictionary <string, UserPrincipal>(); foreach (var AzureUser in _Users) { TmpDictionary.Add(AzureUser.Email + Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX, AzureUser); } if (!DatabaseService.ScanTable( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), out List <JObject> Result, _ErrorMessageAction)) { _ErrorMessageAction?.Invoke("Scan unique-users-fields operation has failed."); return(false); } foreach (var Existing in Result) { if (Existing.TryGetValue(UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL, out JToken ExistingEmailToken) && ExistingEmailToken.Type == JTokenType.String) { TmpDictionary.Remove((string)ExistingEmailToken); //TryRemove } } _UsersToBePut = TmpDictionary.Values.ToList(); return(true); }
protected override BWebServiceResponse OnRequestPP(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null) { if (_Context.Request.HttpMethod != "GET") { _ErrorMessageAction?.Invoke("ListRegisteredUserEmails: GET method is accepted. But received request method: " + _Context.Request.HttpMethod); return(BWebResponse.MethodNotAllowed("GET method is accepted. But received request method: " + _Context.Request.HttpMethod)); } if (!DatabaseService.ScanTable(UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), out List <JObject> Result, _ErrorMessageAction)) { return(BWebResponse.InternalError("ScanTable has failed.")); } if (Result == null) { return(BWebResponse.StatusOK("Ok.", new JObject() { ["emailAddresses"] = new JArray() })); } var FinalResultArray = new JArray(); foreach (var Current in Result) { if (Current != null && Current.ContainsKey(UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL) && Current.ContainsKey(UserDBEntry.KEY_NAME_USER_ID)) { FinalResultArray.Add( new JObject() { [UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL] = (string)Current[UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL], [UserDBEntry.KEY_NAME_USER_ID] = (string)Current[UserDBEntry.KEY_NAME_USER_ID] }); } } return(BWebResponse.StatusOK("Ok.", new JObject() { ["emailAddresses"] = FinalResultArray })); }
private BWebServiceResponse UpdateUserInfo(HttpListenerContext _Context, Action <string> _ErrorMessageAction) { var UpdateFieldsUserEntry = new JObject(); var UpdateFieldsAuthEntry = new JObject(); string NewEmailChange = null; string NewUserNameChange = null; using (var InputStream = _Context.Request.InputStream) { using (var ResponseReader = new StreamReader(InputStream)) { try { var ParsedBody = JObject.Parse(ResponseReader.ReadToEnd()); 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.")); } UpdateFieldsUserEntry[Child.Key] = Child.Value; } if (AuthDBEntry.UpdatableProperties.Contains(Child.Key)) { UpdateFieldsAuthEntry[Child.Key] = Child.Value; } if (Child.Key == UserDBEntry.USER_EMAIL_PROPERTY) { NewEmailChange = ((string)Child.Value).ToLower(); if (NewEmailChange.EndsWith(Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX)) { return(BWebResponse.BadRequest("Email address cannot end with " + Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX)); } } else if (Child.Key == UserDBEntry.USER_NAME_PROPERTY) { NewUserNameChange = (string)Child.Value; if (NewUserNameChange.EndsWith(Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX)) { return(BWebResponse.BadRequest("Username cannot end with " + Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX)); } } } } catch (Exception e) { _ErrorMessageAction?.Invoke("User_GetUpdateDeleteUser->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.")); } } } if (UpdateFieldsUserEntry.Count == 0) { return(BWebResponse.BadRequest("Request does not contain any matching field with the expected structure.")); } bool bNewEmailAtomicnessSet = false, bNewUsernameAtomicnessSet = false; try { if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), RequestedUserID, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } if (!DatabaseService.GetItem( UserDBEntry.DBSERVICE_USERS_TABLE(), UserDBEntry.KEY_NAME_USER_ID, new BPrimitiveType(RequestedUserID), UserDBEntry.Properties, out JObject UserObject, _ErrorMessageAction)) { return(BWebResponse.InternalError("Database fetch-user-info operation has failed.")); } if (UserObject == null) { return(BWebResponse.NotFound("User does not exist.")); } var bEmailExistInUserObject = UserObject.ContainsKey(UserDBEntry.USER_EMAIL_PROPERTY); var bUsernameExistInUserObject = UserObject.ContainsKey(UserDBEntry.USER_NAME_PROPERTY); if (NewEmailChange != null && bEmailExistInUserObject && (string)UserObject[UserDBEntry.USER_EMAIL_PROPERTY] == NewEmailChange) { NewEmailChange = null; UpdateFieldsUserEntry.Remove(UserDBEntry.USER_EMAIL_PROPERTY); UpdateFieldsAuthEntry.Remove(AuthDBEntry.USER_EMAIL_PROPERTY); } else if (NewEmailChange != null) { if (bEmailExistInUserObject && ((string)UserObject[UserDBEntry.USER_EMAIL_PROPERTY]).EndsWith(Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX)) { return(BWebResponse.BadRequest("E-mail address cannot be changed for this account type.")); } if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL + ":" + NewEmailChange, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } bNewEmailAtomicnessSet = true; if (!DatabaseService.GetItem( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL, new BPrimitiveType(NewEmailChange), UniqueUserFieldsDBEntry.Properties, out JObject ExistenceCheck, _ErrorMessageAction)) { return(BWebResponse.InternalError("Database fetch-uniqueness-info operation has failed.")); } if (ExistenceCheck != null) { return(BWebResponse.Conflict("A user with same user e-mail already exists.")); } } if (NewUserNameChange != null && UserObject.ContainsKey(UserDBEntry.USER_NAME_PROPERTY) && (string)UserObject[UserDBEntry.USER_NAME_PROPERTY] == NewUserNameChange) { NewUserNameChange = null; UpdateFieldsUserEntry.Remove(UserDBEntry.USER_NAME_PROPERTY); UpdateFieldsAuthEntry.Remove(AuthDBEntry.USER_NAME_PROPERTY); } else if (NewUserNameChange != null) { if (bUsernameExistInUserObject && ((string)UserObject[UserDBEntry.USER_NAME_PROPERTY]).EndsWith(Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX)) { return(BWebResponse.BadRequest("Username cannot be changed for this account type.")); } if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME + ":" + NewUserNameChange, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } bNewUsernameAtomicnessSet = true; if (!DatabaseService.GetItem( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME, new BPrimitiveType(NewUserNameChange), UniqueUserFieldsDBEntry.Properties, out JObject ExistenceCheck, _ErrorMessageAction)) { return(BWebResponse.InternalError("Database fetch-uniqueness-info operation has failed.")); } if (ExistenceCheck != null) { return(BWebResponse.Conflict("A user with same username already exists.")); } } return(UpdateUserInfo_Internal( _Context, NewEmailChange, NewUserNameChange, UserObject, UpdateFieldsUserEntry, UpdateFieldsAuthEntry, _ErrorMessageAction)); } finally { Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), RequestedUserID, _ErrorMessageAction); if (bNewEmailAtomicnessSet) { Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL + ":" + NewEmailChange, _ErrorMessageAction); } if (bNewUsernameAtomicnessSet) { Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME + ":" + NewUserNameChange, _ErrorMessageAction); } } }
private BWebServiceResponse OnRequest_Internal(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null) { if (_Context.Request.HttpMethod != "GET" && _Context.Request.HttpMethod != "POST" && _Context.Request.HttpMethod != "DELETE") { _ErrorMessageAction?.Invoke("User_GetUpdateDeleteUser: GET, POST and DELETE methods are accepted. But received request method: " + _Context.Request.HttpMethod); return(BWebResponse.MethodNotAllowed("GET, POST and DELETE methods are accepted. But received request method: " + _Context.Request.HttpMethod)); } RequestedUserID = RestfulUrlParameters[RestfulUrlParameter_UsersKey]; if (_Context.Request.HttpMethod == "GET") { return(GetUserInfo(_ErrorMessageAction)); } else if (_Context.Request.HttpMethod == "DELETE") { if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), RequestedUserID, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } var Result = DeleteUser(_Context, out bool bSetClearanceForApiKeys, out List <string> ApiKeys, _ErrorMessageAction); Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), RequestedUserID, _ErrorMessageAction); if (bSetClearanceForApiKeys) { foreach (var ApiKey in ApiKeys) { Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + ApiKey, _ErrorMessageAction); } } return(Result); } //Atomicness handled inside the function return(UpdateUserInfo(_Context, _ErrorMessageAction)); }
private BWebServiceResponse DeleteUser(HttpListenerContext _Context, out bool _bSetClearanceForApiKeys, out List <string> _ApiKeys, Action <string> _ErrorMessageAction) { _bSetClearanceForApiKeys = false; _ApiKeys = new List <string>(); var UserKey = new BPrimitiveType(RequestedUserID); if (!DatabaseService.GetItem( UserDBEntry.DBSERVICE_USERS_TABLE(), UserDBEntry.KEY_NAME_USER_ID, UserKey, UserDBEntry.Properties, out JObject UserObject, _ErrorMessageAction)) { return(BWebResponse.InternalError("Database fetch-user-info operation has failed.")); } if (UserObject == null) { return(BWebResponse.NotFound("User does not exist.")); } var UserData = JsonConvert.DeserializeObject <UserDBEntry>(UserObject.ToString()); if (UserData.AuthMethods != null && UserData.AuthMethods.Count > 0) { foreach (var AMethod in UserData.AuthMethods) { string OldField = null; BPrimitiveType AuthMethodKey = null; switch (AMethod.Method) { case AuthMethod.Methods.USER_EMAIL_PASSWORD_METHOD: { AuthMethodKey = new BPrimitiveType(AMethod.UserEmail + AMethod.PasswordMD5); OldField = AMethod.UserEmail; break; } case AuthMethod.Methods.USER_NAME_PASSWORD_METHOD: { AuthMethodKey = new BPrimitiveType(AMethod.UserName + AMethod.PasswordMD5); OldField = AMethod.UserName; break; } case AuthMethod.Methods.API_KEY_METHOD: { AuthMethodKey = new BPrimitiveType(AMethod.ApiKey); _bSetClearanceForApiKeys = true; _ApiKeys.Add(AMethod.ApiKey); if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + AMethod.ApiKey, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } break; } } if (AuthMethodKey != null) { Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, AuthDBEntry.DBSERVICE_AUTHMETHODS_TABLE(), AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY, AuthMethodKey); MemoryService.DeleteKey(CommonData.MemoryQueryParameters, AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY + AuthMethodKey.AsString, _ErrorMessageAction); } } } MemoryService.DeleteKey(CommonData.MemoryQueryParameters, UserBaseAccessMEntry.M_KEY_NAME_USER_ID + RequestedUserID, _ErrorMessageAction); Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, UserDBEntry.DBSERVICE_USERS_TABLE(), UserDBEntry.KEY_NAME_USER_ID, UserKey); Controller_UserActions.Get().BroadcastUserAction(new Action_UserDeleted ( RequestedUserID, UserData.UserEmail, UserData.UserName, UserData.UserModels, UserData.UserSharedModels ), _ErrorMessageAction); if (UserData.UserEmail != null && UserData.UserEmail.Length > 0) { Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL, new BPrimitiveType(UserData.UserEmail)); } if (UserData.UserName != null && UserData.UserName.Length > 0) { Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME, new BPrimitiveType(UserData.UserName)); } foreach (var ApiKey in _ApiKeys) { Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY, new BPrimitiveType(ApiKey)); } return(BWebResponse.StatusOK("User has been deleted.")); }
private BWebServiceResponse UpdateUserInfo_Internal( HttpListenerContext _Context, string _NewEmailChange, string _NewUserNameChange, JObject _UserObject, JObject _UpdateFieldsUserEntry, JObject _UpdateFieldsAuthEntry, Action <string> _ErrorMessageAction) { var UserKey = new BPrimitiveType(RequestedUserID); if (_UpdateFieldsUserEntry.Count > 0) { string OldEmail = null; string OldUserName = null; if (_NewEmailChange != null && _UserObject.ContainsKey(UserDBEntry.USER_EMAIL_PROPERTY)) { OldEmail = (string)_UserObject[UserDBEntry.USER_EMAIL_PROPERTY]; Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL, new BPrimitiveType(OldEmail)); Controller_DeliveryEnsurer.Get().DB_UpdateItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL, new BPrimitiveType(_NewEmailChange), new JObject() { [UserDBEntry.KEY_NAME_USER_ID] = RequestedUserID }); } if (_NewUserNameChange != null && _UserObject.ContainsKey(UserDBEntry.USER_NAME_PROPERTY)) { OldUserName = (string)_UserObject[UserDBEntry.USER_NAME_PROPERTY]; Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME, new BPrimitiveType(OldUserName)); Controller_DeliveryEnsurer.Get().DB_UpdateItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME, new BPrimitiveType(_NewUserNameChange), new JObject() { [UserDBEntry.KEY_NAME_USER_ID] = RequestedUserID }); } Controller_DeliveryEnsurer.Get().DB_UpdateItem_FireAndForget( _Context, UserDBEntry.DBSERVICE_USERS_TABLE(), UserDBEntry.KEY_NAME_USER_ID, UserKey, _UpdateFieldsUserEntry); var NewEmail = _NewEmailChange ?? (string)_UserObject[UserDBEntry.USER_EMAIL_PROPERTY]; var NewUserName = _NewUserNameChange ?? (string)_UserObject[UserDBEntry.USER_NAME_PROPERTY]; Controller_UserActions.Get().BroadcastUserAction(new Action_UserUpdated( RequestedUserID, OldEmail ?? NewEmail, NewEmail, OldUserName ?? NewUserName, NewUserName, _UpdateFieldsUserEntry), _ErrorMessageAction); } if (_UpdateFieldsAuthEntry.Count > 0) { var UserData = JsonConvert.DeserializeObject <UserDBEntry>(_UserObject.ToString()); if (UserData.AuthMethods != null && UserData.AuthMethods.Count > 0) { foreach (var Method in UserData.AuthMethods) { string PasswordMD5 = null; string OldField = null; BPrimitiveType AuthMethodKey = null; switch (Method.Method) { case AuthMethod.Methods.USER_EMAIL_PASSWORD_METHOD: { PasswordMD5 = Method.PasswordMD5; OldField = Method.UserEmail; AuthMethodKey = new BPrimitiveType(Method.UserEmail + PasswordMD5); break; } case AuthMethod.Methods.USER_NAME_PASSWORD_METHOD: { PasswordMD5 = Method.PasswordMD5; OldField = Method.UserName; AuthMethodKey = new BPrimitiveType(Method.UserName + PasswordMD5); break; } case AuthMethod.Methods.API_KEY_METHOD: AuthMethodKey = new BPrimitiveType(Method.ApiKey); break; } if (AuthMethodKey != null) { bool bRecreateNeed = (_NewEmailChange != null && Method.Method == AuthMethod.Methods.USER_EMAIL_PASSWORD_METHOD) || (_NewUserNameChange != null && Method.Method == AuthMethod.Methods.USER_NAME_PASSWORD_METHOD); if (bRecreateNeed) { MemoryService.DeleteKey(CommonData.MemoryQueryParameters, AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY + AuthMethodKey.AsString, _ErrorMessageAction); //No in-memory recreation for security. if (!DatabaseService.DeleteItem( AuthDBEntry.DBSERVICE_AUTHMETHODS_TABLE(), AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY, AuthMethodKey, out JObject DeletedAuthMethodObject, EBReturnItemBehaviour.ReturnAllOld, _ErrorMessageAction)) { DatabaseService.GetItem( AuthDBEntry.DBSERVICE_AUTHMETHODS_TABLE(), AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY, AuthMethodKey, AuthDBEntry.Properties, out DeletedAuthMethodObject, _ErrorMessageAction); Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, AuthDBEntry.DBSERVICE_AUTHMETHODS_TABLE(), AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY, AuthMethodKey); } if (DeletedAuthMethodObject != null) { DeletedAuthMethodObject.Merge(_UpdateFieldsAuthEntry, new JsonMergeSettings() { MergeArrayHandling = MergeArrayHandling.Replace }); _UpdateFieldsAuthEntry = DeletedAuthMethodObject; } if (_NewEmailChange != null && Method.Method == AuthMethod.Methods.USER_EMAIL_PASSWORD_METHOD) { AuthMethodKey = new BPrimitiveType(_NewEmailChange + PasswordMD5); } else if (_NewUserNameChange != null && Method.Method == AuthMethod.Methods.USER_NAME_PASSWORD_METHOD) { AuthMethodKey = new BPrimitiveType(_NewUserNameChange + PasswordMD5); } Controller_DeliveryEnsurer.Get().DB_PutItem_FireAndForget( _Context, AuthDBEntry.DBSERVICE_AUTHMETHODS_TABLE(), AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY, AuthMethodKey, _UpdateFieldsAuthEntry); } else { Controller_DeliveryEnsurer.Get().DB_UpdateItem_FireAndForget( _Context, AuthDBEntry.DBSERVICE_AUTHMETHODS_TABLE(), AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY, AuthMethodKey, _UpdateFieldsAuthEntry); } } } } } return(BWebResponse.StatusOK("User has been updated.")); }
private BWebServiceResponse CreateAccessMethodForUser(HttpListenerContext _Context, out bool _bSetClearanceForApiKey, out string _ApiKey, Action <string> _ErrorMessageAction) { _bSetClearanceForApiKey = false; _ApiKey = null; AuthMethod NewMethod = null; using (var InputStream = _Context.Request.InputStream) { using (var ResponseReader = new StreamReader(InputStream)) { try { NewMethod = JsonConvert.DeserializeObject <AuthMethod>(ResponseReader.ReadToEnd()); } catch (Exception e) { _ErrorMessageAction?.Invoke("User_CreateListAccessMethods_ForUser->CreateAccessMethodForUser: 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.")); } } } if (NewMethod == null) { return(BWebResponse.BadRequest("Request body does not contain all mandatory information or some fields are invalid.")); } BPrimitiveType AuthMethodKey = null; if (NewMethod.Method == AuthMethod.Methods.USER_EMAIL_PASSWORD_METHOD) { if (NewMethod.UserEmail == null || NewMethod.PasswordMD5 == null || NewMethod.UserEmail.Length == 0 || NewMethod.PasswordMD5.Length == 0) { return(BWebResponse.BadRequest("Request body does not contain all fields.")); } AuthMethodKey = new BPrimitiveType(NewMethod.UserEmail + NewMethod.PasswordMD5); } else if (NewMethod.Method == AuthMethod.Methods.USER_NAME_PASSWORD_METHOD) { if (NewMethod.UserName == null || NewMethod.PasswordMD5 == null || NewMethod.UserName.Length == 0 || NewMethod.PasswordMD5.Length == 0) { return(BWebResponse.BadRequest("Request body does not contain all fields.")); } AuthMethodKey = new BPrimitiveType(NewMethod.UserName + NewMethod.PasswordMD5); } else if (NewMethod.Method == AuthMethod.Methods.API_KEY_METHOD) { int ExistenceTrial = 0; while (ExistenceTrial < 3) { if (!BUtility.CalculateStringMD5(BUtility.RandomString(32, false), out NewMethod.ApiKey, _ErrorMessageAction)) { return(BWebResponse.InternalError("Hashing error.")); } NewMethod.ApiKey = NewMethod.ApiKey.ToUpper(); if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + NewMethod.ApiKey, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } if (!DatabaseService.UpdateItem( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY, new BPrimitiveType(NewMethod.ApiKey), new JObject() { [UserDBEntry.KEY_NAME_USER_ID] = RequestedUserID }, out JObject _, EBReturnItemBehaviour.DoNotReturn, DatabaseService.BuildAttributeNotExistCondition(UniqueUserFieldsDBEntry.KEY_NAME_API_KEY), _ErrorMessageAction)) { Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + NewMethod.ApiKey, _ErrorMessageAction); ExistenceTrial++; } else { _bSetClearanceForApiKey = true; _ApiKey = NewMethod.ApiKey; break; } }
private BWebServiceResponse OnRequest_Internal(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null) { if (_Context.Request.HttpMethod != "GET" && _Context.Request.HttpMethod != "PUT") { _ErrorMessageAction?.Invoke("User_CreateListAccessMethods_ForUser: GET and PUT methods are accepted. But received request method: " + _Context.Request.HttpMethod); return(BWebResponse.MethodNotAllowed("GET and PUT methods are accepted. But received request method: " + _Context.Request.HttpMethod)); } RequestedUserID = RestfulUrlParameters[RestfulUrlParameter_UsersKey]; if (_Context.Request.HttpMethod == "GET") { return(ListAccessMethodsForUser(_ErrorMessageAction)); } //else { if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), RequestedUserID, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } var Result = CreateAccessMethodForUser(_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); } }
//TODO: If SSO is enabled for user; when it loses access to the tenant, delete all rights but keep the models and user. private BWebServiceResponse DeleteAccessMethodForUser(HttpListenerContext _Context, out bool _bSetClearanceForApiKey, out string _ApiKey, Action <string> _ErrorMessageAction) { _bSetClearanceForApiKey = false; _ApiKey = null; var UserKey = new BPrimitiveType(RequestedUserID); if (!DatabaseService.GetItem( UserDBEntry.DBSERVICE_USERS_TABLE(), UserDBEntry.KEY_NAME_USER_ID, UserKey, UserDBEntry.Properties, out JObject UserObject, _ErrorMessageAction)) { return(BWebResponse.InternalError("Database fetch-user-info operation has failed.")); } if (UserObject == null) { return(BWebResponse.NotFound("User does not exist.")); } if (!UserObject.ContainsKey(UserDBEntry.AUTH_METHODS_PROPERTY)) { return(BWebResponse.NotFound("User does not have any auth method.")); } bool bFound = false; var AuthMethodsArray = (JArray)UserObject[UserDBEntry.AUTH_METHODS_PROPERTY]; for (var i = (AuthMethodsArray.Count - 1); i >= 0; i--) { var MethodObject = (JObject)AuthMethodsArray[i]; var Method = JsonConvert.DeserializeObject <AuthMethod>(MethodObject.ToString()); string AuthMethodKey = null; switch (Method.Method) { case AuthMethod.Methods.USER_EMAIL_PASSWORD_METHOD: { if (!bIsInternalCall && Method.UserEmail.EndsWith(Controller_SSOAccessToken.EMAIL_USER_NAME_POSTFIX)) { return(BWebResponse.BadRequest("This auth method cannot be deleted.")); } AuthMethodKey = Method.UserEmail + Method.PasswordMD5; break; } case AuthMethod.Methods.USER_NAME_PASSWORD_METHOD: { AuthMethodKey = Method.UserName + Method.PasswordMD5; break; } case AuthMethod.Methods.API_KEY_METHOD: { AuthMethodKey = Method.ApiKey; _bSetClearanceForApiKey = true; _ApiKey = Method.ApiKey; if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY + ":" + Method.ApiKey, _ErrorMessageAction)) { return(BWebResponse.InternalError("Atomic operation control has failed.")); } break; } } if (AuthMethodKey == RequestedAuthMethodKey) { AuthMethodsArray.RemoveAt(i); bFound = true; } } if (!bFound) { return(BWebResponse.NotFound("Auth method does not exist.")); } //Update UserDBEntry Controller_DeliveryEnsurer.Get().DB_UpdateItem_FireAndForget( _Context, UserDBEntry.DBSERVICE_USERS_TABLE(), UserDBEntry.KEY_NAME_USER_ID, UserKey, UserObject); //Delete AuthDBEntry Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, AuthDBEntry.DBSERVICE_AUTHMETHODS_TABLE(), AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY, new BPrimitiveType(RequestedAuthMethodKey)); if (_bSetClearanceForApiKey) { //Delete ApiKey from UniqueUserFields Controller_DeliveryEnsurer.Get().DB_DeleteItem_FireAndForget( _Context, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_API_KEY, new BPrimitiveType(_ApiKey)); } //Delete from cache MemoryService.DeleteKey( CommonData.MemoryQueryParameters, AuthDBEntry.KEY_NAME_AUTH_DB_ENTRY + RequestedAuthMethodKey, _ErrorMessageAction); return(BWebResponse.StatusOK("Access method has been deleted.")); }
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); }
private void Cleanup_UniqueUserFields(Action <string> _ErrorMessageAction = null) { if (!DatabaseService.ScanTable( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), out List <JObject> UniqueFieldsEntries, _ErrorMessageAction)) { _ErrorMessageAction?.Invoke("Cleanup_UniqueUserFields: Table does not exist or ScanTable operation has failed."); return; } if (UniqueFieldsEntries.Count == 0) { return; } foreach (var Current in UniqueFieldsEntries) { if (!Current.ContainsKey(UserDBEntry.KEY_NAME_USER_ID)) { continue; } var UserID = (string)Current[UserDBEntry.KEY_NAME_USER_ID]; var EntryKeyName = ""; if (Current.ContainsKey(UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL)) { EntryKeyName = UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL; } else if (Current.ContainsKey(UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME)) { EntryKeyName = UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME; } else if (Current.ContainsKey(UniqueUserFieldsDBEntry.KEY_NAME_API_KEY)) { EntryKeyName = UniqueUserFieldsDBEntry.KEY_NAME_API_KEY; } else { continue; } var EntryKeyValue = (string)Current[EntryKeyName]; var ClearanceFullEntryKey = EntryKeyName + ":" + EntryKeyValue; bool bRelease_UserEntry = false; bool bRelease_UniqueFieldEntry = false; try { if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), UserID, _ErrorMessageAction)) { continue; } bRelease_UserEntry = true; if (!Controller_AtomicDBOperation.Get().GetClearanceForDBOperation(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), ClearanceFullEntryKey, _ErrorMessageAction)) { continue; } bRelease_UniqueFieldEntry = true; bool bDeleteEntry = false; if (!DatabaseService.GetItem( UserDBEntry.DBSERVICE_USERS_TABLE(), UserDBEntry.KEY_NAME_USER_ID, new BPrimitiveType(UserID), UserDBEntry.Properties, out JObject UserObject, _ErrorMessageAction)) { continue; } if (UserObject == null) { //User does not exist bDeleteEntry = true; } else { var User = JsonConvert.DeserializeObject <UserDBEntry>(UserObject.ToString()); switch (EntryKeyName) { case UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL: bDeleteEntry = EntryKeyValue != User.UserEmail; break; case UniqueUserFieldsDBEntry.KEY_NAME_USER_NAME: bDeleteEntry = EntryKeyValue != User.UserName; break; case UniqueUserFieldsDBEntry.KEY_NAME_API_KEY: bool bFound = false; foreach (var UserAuthMethod in User.AuthMethods) { if (UserAuthMethod.Method == AuthMethod.Methods.API_KEY_METHOD) { if (UserAuthMethod.ApiKey == EntryKeyValue) { bFound = true; break; } } } if (!bFound) { bDeleteEntry = true; } break; } } if (bDeleteEntry) { DatabaseService.DeleteItem( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), EntryKeyName, new BPrimitiveType(EntryKeyValue), out JObject _, EBReturnItemBehaviour.DoNotReturn, _ErrorMessageAction); } } finally { if (bRelease_UniqueFieldEntry) { Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), ClearanceFullEntryKey, _ErrorMessageAction); } if (bRelease_UserEntry) { Controller_AtomicDBOperation.Get().SetClearanceForDBOperationForOthers(InnerProcessor, UserDBEntry.DBSERVICE_USERS_TABLE(), UserID, _ErrorMessageAction); } } } }
private bool CreateUser(out string _UserID, string _EmailWithoutPostfix, Action <string> _ErrorMessageAction, string _OptionalName = null) { _UserID = null; var Endpoint = "http://localhost:" + LocalServerPort + "/auth/users"; using var Handler = new HttpClientHandler { SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, ServerCertificateCustomValidationCallback = (a, b, c, d) => true }; using var Client = new HttpClient(Handler); Client.DefaultRequestHeaders.TryAddWithoutValidation("internal-call-secret", CommonData.INTERNAL_CALL_PRIVATE_KEY); Client.DefaultRequestHeaders.TryAddWithoutValidation("do-not-get-db-clearance", "false"); try { using var RequestContent = new StringContent(new JObject() { [UserDBEntry.USER_EMAIL_PROPERTY] = _EmailWithoutPostfix, [UserDBEntry.USER_NAME_PROPERTY] = _OptionalName != null ? _OptionalName : _EmailWithoutPostfix }.ToString(), Encoding.UTF8, "application/json"); using var RequestTask = Client.PutAsync(Endpoint, RequestContent); RequestTask.Wait(); using var Response = RequestTask.Result; using var ResponseContent = Response.Content; using var ReadResponseTask = ResponseContent.ReadAsStringAsync(); ReadResponseTask.Wait(); var ResponseString = ReadResponseTask.Result; if (!Response.IsSuccessStatusCode) { if ((int)Response.StatusCode == BWebResponse.Error_Conflict_Code) { if (!DatabaseService.GetItem( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL, new BPrimitiveType(_EmailWithoutPostfix), UniqueUserFieldsDBEntry.Properties, out JObject _ExistenceCheck, _ErrorMessageAction)) { return(false); } _UserID = (string)_ExistenceCheck[UserDBEntry.KEY_NAME_USER_ID]; return(true); } _ErrorMessageAction?.Invoke("Error: CreateTestUser->CreateUser: Request returned error. Endpoint: " + Endpoint + ", code: " + Response.StatusCode + ", message: " + ResponseString); return(false); } _UserID = (string)JObject.Parse(ResponseString)[UserDBEntry.KEY_NAME_USER_ID]; } catch (Exception e) { if (e.InnerException != null && e.InnerException != e) { _ErrorMessageAction?.Invoke("Error: CreateTestUser->CreateUser->Inner: " + e.InnerException.Message + ", Trace: " + e.InnerException.StackTrace); } if (e is AggregateException) { foreach (var Inner in (e as AggregateException).InnerExceptions) { _ErrorMessageAction?.Invoke("Error: CreateTestUser->CreateUser->Aggregate->Inner: " + Inner.Message + ", Trace: " + Inner.StackTrace); } } _ErrorMessageAction?.Invoke("Error: CreateTestUser->CreateUser: Request failed. Endpoint: " + Endpoint + ", message: " + e.Message + ", trace: " + e.StackTrace); return(false); } return(true); }
protected override BWebServiceResponse Process(HttpListenerContext _Context, Action <string> _ErrorMessageAction = null) { if (_Context.Request.HttpMethod != "POST") { _ErrorMessageAction?.Invoke("GetUserIDsFromEmailsRequest: 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)); } string RequestPayload = null; JObject ParsedBody; using (var InputStream = _Context.Request.InputStream) { using var ResponseReader = new StreamReader(InputStream); try { RequestPayload = ResponseReader.ReadToEnd(); ParsedBody = JObject.Parse(RequestPayload); } catch (Exception e) { _ErrorMessageAction?.Invoke("GetUserIDsFromEmailsRequest-> Malformed request body. Body content: " + RequestPayload + ", Exception: " + e.Message + ", Trace: " + e.StackTrace); return(BWebResponse.BadRequest("Malformed request body. Request must be a valid json form.")); } } if (!ParsedBody.ContainsKey("emailAddresses") || ParsedBody["emailAddresses"].Type != JTokenType.Array) { return(BWebResponse.BadRequest("Invalid request body.")); } var AsJArray = (JArray)ParsedBody["emailAddresses"]; var EmailAddresses = new List <string>(); foreach (var Token in AsJArray) { if (Token.Type != JTokenType.String) { return(BWebResponse.BadRequest("Invalid request body.")); } var EmailAddress = ((string)Token).ToLower(); if (!EmailAddresses.Contains(EmailAddress)) { EmailAddresses.Add(EmailAddress); } } if (EmailAddresses.Count == 0) { return(BWebResponse.BadRequest("Empty emailAddresses field.")); } var ResponseObject = new JObject(); foreach (var Email in EmailAddresses) { if (!DatabaseService.GetItem( UniqueUserFieldsDBEntry.DBSERVICE_UNIQUEUSERFIELDS_TABLE(), UniqueUserFieldsDBEntry.KEY_NAME_USER_EMAIL, new BPrimitiveType(Email), UniqueUserFieldsDBEntry.Properties, out JObject ExistenceCheck, _ErrorMessageAction)) { return(BWebResponse.InternalError("Database fetch-uniqueness-info operation has failed.")); } if (ExistenceCheck == null) { return(BWebResponse.NotFound("A user with e-mail " + Email + " does not exist.")); } ResponseObject[Email] = (string)ExistenceCheck[UserDBEntry.KEY_NAME_USER_ID]; } return(BWebResponse.StatusOK("OK.", new JObject() { ["map"] = ResponseObject })); }
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 })); }