DROP PROCEDURE IF EXISTS p_dog_save_user; DELIMITER // CREATE PROCEDURE p_dog_save_user ( IN a_comment VARCHAR(500), IN a_guid BINARY(36), IN a_id_user INT, IN a_debug BIT ) BEGIN DECLARE v_code_type_error_bad_data VARCHAR(100); DECLARE v_id_type_error_bad_data INT; DECLARE v_id_permission_product INT; DECLARE v_id_permission_user_edit INT; DECLARE v_id_change_set INT; DECLARE v_id_access_level_edit INT; DECLARE v_is_super_user BIT; DECLARE v_can_edit_user BIT; DECLARE v_priority_access_level_admin INT; DECLARE v_priority_access_level_none INT; DECLARE v_priority_access_level_user INT; DECLARE v_time_start TIMESTAMP(6); DECLARE exit handler for SQLEXCEPTION BEGIN GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE , @errno = MYSQL_ERRNO , @text = MESSAGE_TEXT ; ROLLBACK; CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT , id_type INT , code VARCHAR(250) NOT NULL , msg TEXT NOT NULL ); INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT MET.id_type , @errno , @text FROM fetchmetrics.CORE_Msg_Error_Type MET WHERE MET.code = 'MYSQL_ERROR' ; SELECT * FROM tmp_Msg_Error; DROP TABLE IF EXISTS tmp_Msg_Error; END; SET v_time_start := CURRENT_TIMESTAMP(6); SET v_code_type_error_bad_data := 'BAD_DATA'; SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM fetchmetrics.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1); SET v_id_access_level_edit := (SELECT ACCESS_LEVEL.id_access_level FROM fetchmetrics.DOG_Access_Level ACCESS_LEVEL WHERE ACCESS_LEVEL.code = 'EDIT' LIMIT 1); SET v_id_permission_user_edit := (SELECT GROUP_CONCAT(PERMISSION.id_permission SEPARATOR ',') FROM fetchmetrics.DOG_Permission PERMISSION WHERE PERMISSION.code = 'USER_CREATE' LIMIT 1); SET v_priority_access_level_admin := (SELECT ACCESS_LEVEL.priority FROM fetchmetrics.DOG_Access_Level ACCESS_LEVEL WHERE ACCESS_LEVEL.code = 'ADMIN' LIMIT 1); SET v_priority_access_level_none := (SELECT ACCESS_LEVEL.priority FROM fetchmetrics.DOG_Access_Level ACCESS_LEVEL WHERE ACCESS_LEVEL.code = 'NONE' LIMIT 1); CALL fetchmetrics.p_core_validate_guid ( a_guid ); DROP TABLE IF EXISTS tmp_Msg_Error; DROP TABLE IF EXISTS tmp_User_Save_User; CREATE TABLE tmp_User_Save_User ( id_user INT NOT NULL , id_role INT , id_role_previous INT , id_user_auth0 VARCHAR(250) , firstname VARCHAR(250) , surname VARCHAR(250) , email VARCHAR(254) , is_email_verified BIT , is_super_user BIT , active BIT , name_error VARCHAR(1000) ); CREATE TABLE tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, id_type INT NOT NULL, code VARCHAR(250) NOT NULL, msg TEXT NOT NULL ); -- Get data from Temp table INSERT INTO tmp_User_Save_User ( id_user , id_user_auth0 , id_role , firstname , surname , email , is_email_verified , is_super_user , active ) SELECT USER_T.id_user , USER_T.id_user_auth0 , USER_T.id_role , IFNULL(USER_T.firstname, USER.firstname) AS firstname , IFNULL(USER_T.surname, USER.surname) AS surname , IFNULL(USER_T.email, USER.email) AS email , IFNULL(USER_T.is_email_verified, USER.is_email_verified) AS is_email_verified , IFNULL(USER_T.is_super_user, USER.is_super_user) AS is_super_user , COALESCE(USER_T.active, USER.active, 1) AS active FROM fetchmetrics.DOG_User_Temp USER_T LEFT JOIN fetchmetrics.DOG_User USER ON USER_T.id_user = USER.id_user WHERE USER_T.guid = a_guid ; UPDATE tmp_User_Save_User t_USER SET t_USER.name_error = IFNULL(t_USER.email, t_USER.id_user_auth0) ; -- Validation -- Missing mandatory fields -- role IF EXISTS ( SELECT * FROM tmp_User_Save_User t_USER LEFT JOIN fetchmetrics.DOG_Role ROLES ON t_USER.id_role = ROLES.id_role WHERE ISNULL(t_USER.id_role) OR ISNULL(ROLES.id_role) LIMIT 1 ) THEN INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT v_id_type_error_bad_data , v_code_type_error_bad_data , CONCAT('The following User(s) do not have a role: ', GROUP_CONCAT(t_USER.name_error SEPARATOR ', ')) AS msg FROM tmp_User_Save_User t_USER LEFT JOIN fetchmetrics.DOG_Role ROLES ON t_USER.id_role = ROLES.id_role WHERE ISNULL(t_USER.id_role) OR ISNULL(ROLES.id_role) ; END IF; -- email IF EXISTS (SELECT * FROM tmp_User_Save_User t_USER WHERE ISNULL(t_USER.email) LIMIT 1) THEN INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT v_id_type_error_bad_data , v_code_type_error_bad_data , CONCAT('The following User(s) do not have an email: ', GROUP_CONCAT(t_USER.name_error SEPARATOR ', ')) AS msg FROM tmp_User_Save_User t_USER WHERE ISNULL(t_USER.email) ; END IF; -- is_super_user IF EXISTS (SELECT * FROM tmp_User_Save_User t_USER WHERE ISNULL(t_USER.is_super_user) LIMIT 1) THEN INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT v_id_type_error_bad_data , v_code_type_error_bad_data , CONCAT('The following User(s) do not have an is super user field: ', GROUP_CONCAT(t_USER.name_error SEPARATOR ', ')) AS msg FROM tmp_User_Save_User t_USER WHERE ISNULL(t_USER.is_super_user) ; END IF; -- is_email_verified IF EXISTS (SELECT * FROM tmp_User_Save_User t_USER WHERE ISNULL(t_USER.is_email_verified) LIMIT 1) THEN INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT v_id_type_error_bad_data , v_code_type_error_bad_data , CONCAT('The following User(s) do not have an is email verified: ', GROUP_CONCAT(t_USER.name_error SEPARATOR ', ')) AS msg FROM tmp_User_Save_User t_USER WHERE ISNULL(t_USER.is_email_verified) ; END IF; -- Get old role UPDATE tmp_User_Save_User t_USER INNER JOIN fetchmetrics.DOG_User_Role_Link USER_ROLE_LINK ON t_USER.id_user = USER_ROLE_LINK.id_user AND USER_ROLE_LINK.active = 1 INNER JOIN fetchmetrics.DOG_Role ROLES ON USER_ROLE_LINK.id_role = ROLES.id_role AND ROLES.active = 1 SET t_USER.id_role_previous = USER_ROLE_LINK.id_role WHERE t_USER.id_user > 0 ; -- Permissions IF a_debug = 1 THEN SELECT a_guid -- a_guid , 0 -- get_all_user , 0 -- get_inactive_user , a_id_user -- ids_user , '' -- a_auth0_ids_user , '' -- a_names_user , '' -- a_emails_user , 1 -- a_require_all_id_search_filters_met , 1 -- a_require_any_id_search_filters_met , 0 -- a_require_all_non_id_search_filters_met , 0 -- a_require_any_non_id_search_filters_met , v_id_permission_user_edit -- ids_permission , v_id_access_level_edit -- ids_access_level , 0 -- a_show_errors , 0 -- a_debug ; END IF; CALL fetchmetrics.p_dog_calc_user_access( a_guid -- a_guid , 0 -- get_all_user , 0 -- get_inactive_user , a_id_user -- ids_user , '' -- a_auth0_ids_user , '' -- a_names_user , '' -- a_emails_user , 1 -- a_require_all_id_search_filters_met , 1 -- a_require_any_id_search_filters_met , 0 -- a_require_all_non_id_search_filters_met , 0 -- a_require_any_non_id_search_filters_met , v_id_permission_user_edit -- ids_permission , v_id_access_level_edit -- ids_access_level , 0 -- a_show_errors , 0 -- a_debug ); SELECT CASE WHEN IFNULL(CALC_USER_T.can_edit, 0) = 1 THEN 1 ELSE 0 END AS can_edit , IFNULL(CALC_USER_T.is_super_user, 0) AS is_super_user , IFNULL(CALC_USER_T.priority_access_level_user, v_priority_access_level_none) AS priority_access_level INTO v_can_edit_user , v_is_super_user , v_priority_access_level_user FROM fetchmetrics.DOG_Calc_User_Access_Temp CALC_USER_T WHERE CALC_USER_T.GUID = a_guid AND CALC_USER_T.id_user = a_id_user AND CALC_USER_T.id_permission_required = v_id_permission_user_edit ; CALL fetchmetrics.p_dog_clear_calc_user_access( a_guid, 0 ); IF ( v_is_super_user = 0 AND EXISTS ( WITH Access_User_Company AS ( SELECT USER_COMPANY_LINK.id_company FROM fetchmetrics.DOG_User_Company_Link USER_COMPANY_LINK WHERE USER_COMPANY_LINK.id_user = a_id_user ) , User_Is_In_Access_User_Company AS ( SELECT USER.id_user , CASE WHEN ACCESS_USER_COMPANY.id_company IS NULL THEN 1 ELSE 0 END AS is_user_company_link_in_access_user_company , ROW_NUMBER() OVER (PARTITION BY USER.id_user ORDER BY CASE WHEN ACCESS_USER_COMPANY.id_company IS NULL THEN 1 ELSE 0 END DESC) AS index_link_in_user FROM fetchmetrics.DOG_User USER INNER JOIN fetchmetrics.DOG_User_Company_Link USER_COMPANY_LINK ON USER.id_user = USER_COMPANY_LINK.id_user LEFT JOIN Access_User_Company ACCESS_USER_COMPANY ON USER_COMPANY_LINK.id_company = ACCESS_USER_COMPANY.id_company ) SELECT * FROM tmp_User_Save_User t_USER LEFT JOIN User_Is_In_Access_User_Company USER_IS_IN_COMPANY ON t_USER.id_user = USER_IS_IN_COMPANY.id_user /* LEFT JOIN fetchmetrics.DOG_User_Company_Link USER_COMPANY_LINK ON t_USER.id_user = USER_COMPANY_LINK.id_user LEFT JOIN User_Company USER_COMPANY ON USER_COMPANY_LINK.id_company = USER_COMPANY.id_company WHERE USER_COMPANY.id_company IS NULL */ WHERE USER_IS_IN_COMPANY.id_user IS NULL OR ( USER_IS_IN_COMPANY.index_link_in_user = 1 AND USER_IS_IN_COMPANY.is_user_company_link_in_access_user_company = 0 ) ) ) THEN DELETE FROM tmp_Msg_Error; INSERT INTO tmp_Msg_Error ( id_type , code , msg ) VALUES ( v_id_type_error_no_permission , v_code_type_error_no_permission , 'You do not have permission to edit User(s) in other Company(s).' ) ; END IF; IF ( v_is_super_user = 0 AND v_priority_access_level_user >= v_priority_access_level_admin AND EXISTS ( SELECT * FROM tmp_User_Save_User t_USER WHERE t_USER.id_user <> a_id_user ) ) THEN DELETE FROM tmp_Msg_Error; INSERT INTO tmp_Msg_Error ( id_type , code , msg ) VALUES ( v_id_type_error_no_permission , v_code_type_error_no_permission , 'You do not have permission to edit other Users.' ) ; END IF; -- Attempt to change role they can't access -- role from IF EXISTS ( SELECT * FROM tmp_User_Save_User t_USER INNER JOIN fetchmetrics.DOG_User USER ON t_USER.id_user = USER.id_user INNER JOIN fetchmetrics.DOG_User_Role_Link USER_ROLE_LINK ON t_USER.id_user = USER_ROLE_LINK.id_user INNER JOIN fetchmetrics.DOG_Role ROLES ON USER_ROLE_LINK.id_role = ROLES.id_role INNER JOIN fetchmetrics.DOG_Access_Level ACCESS_LEVEL ON ROLES.id_access_level_required = ACCESS_LEVEL.id_access_level WHERE ACCESS_LEVEL.priority < v_priority_access_level_user LIMIT 1 ) THEN INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT v_id_type_error_bad_data , v_code_type_error_bad_data , CONCAT('The following User(s) have role(s) you cannot access: ', GROUP_CONCAT(t_USER.name_error SEPARATOR ', ')) AS msg FROM tmp_User_Save_User t_USER INNER JOIN fetchmetrics.DOG_User USER ON t_USER.id_user = USER.id_user INNER JOIN fetchmetrics.DOG_User_Role_Link USER_ROLE_LINK ON t_USER.id_user = USER_ROLE_LINK.id_user INNER JOIN fetchmetrics.DOG_Role ROLES ON USER_ROLE_LINK.id_role = ROLES.id_role INNER JOIN fetchmetrics.DOG_Access_Level ACCESS_LEVEL ON ROLES.id_access_level_required = ACCESS_LEVEL.id_access_level WHERE ACCESS_LEVEL.priority < v_priority_access_level_user ; END IF; -- role to IF EXISTS ( SELECT * FROM tmp_User_Save_User t_USER INNER JOIN fetchmetrics.DOG_Role ROLES ON t_USER.id_role = ROLES.id_role INNER JOIN fetchmetrics.DOG_Access_Level ACCESS_LEVEL ON ROLES.id_access_level_required = ACCESS_LEVEL.id_access_level WHERE ACCESS_LEVEL.priority < v_priority_access_level_user LIMIT 1 ) THEN INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT v_id_type_error_bad_data , v_code_type_error_bad_data , CONCAT('The following User(s) have role(s) you cannot access: ', GROUP_CONCAT(t_USER.name_error SEPARATOR ', ')) AS msg FROM tmp_User_Save_User t_USER INNER JOIN fetchmetrics.DOG_Role ROLES ON t_USER.id_role = ROLES.id_role INNER JOIN fetchmetrics.DOG_Access_Level ACCESS_LEVEL ON ROLES.id_access_level_required = ACCESS_LEVEL.id_access_level WHERE ACCESS_LEVEL.priority < v_priority_access_level_user ; END IF; -- Attempt to change id, is_super_user, or created_on without admin permission IF EXISTS ( SELECT * FROM tmp_User_Save_User t_USER LEFT JOIN fetchmetrics.DOG_User USER ON t_USER.id_user = USER.id_user WHERE USER.id_user IS NULL OR USER.id_user_auth0 <> t_USER.id_user_auth0 OR USER.id_user <> t_USER.id_user OR USER.id_user <> t_USER.id_user OR USER.id_user <> t_USER.id_user OR USER.id_user <> t_USER.id_user LIMIT 1 ) THEN INSERT INTO tmp_Msg_Error ( id_type , code , msg ) SELECT v_id_type_error_bad_data , v_code_type_error_bad_data , CONCAT('The following User(s) have role(s) you cannot access: ', GROUP_CONCAT(t_USER.name_error SEPARATOR ', ')) AS msg FROM tmp_User_Save_User t_USER INNER JOIN fetchmetrics.DOG_User USER ON t_USER.id_user = USER.id_user INNER JOIN fetchmetrics.DOG_User_Role_Link USER_ROLE_LINK ON t_USER.id_user = USER_ROLE_LINK.id_user INNER JOIN fetchmetrics.DOG_Role ROLES ON USER_ROLE_LINK.id_role = ROLES.id_role INNER JOIN fetchmetrics.DOG_Access_Level ACCESS_LEVEL ON ROLES.id_access_level_required = ACCESS_LEVEL.id_access_level WHERE ACCESS_LEVEL.priority < v_priority_access_level_user ; END IF; IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN START TRANSACTION; INSERT INTO fetchmetrics.DOG_User_Change_Set ( comment ) VALUES ( a_comment ) ; SET v_id_change_set := LAST_INSERT_ID(); UPDATE fetchmetrics.DOG_User USER INNER JOIN tmp_User_Save_User t_USER ON USER.id_user = t_USER.id_user SET USER.id_user_auth0 = t_USER.id_user_auth0 , USER.firstname = t_USER.firstname , USER.surname = t_USER.surname , USER.email = t_USER.email , USER.is_email_verified = t_USER.is_email_verified , USER.is_super_user = t_USER.is_super_user , USER.active = t_USER.active , USER.id_change_set = v_id_change_set ; IF EXISTS ( SELECT * FROM tmp_User_Save_User t_USER WHERE t_USER.id_role IS NOT NULL AND t_USER.id_role_previous IS NULL LIMIT 1 ) THEN INSERT INTO fetchmetrics.DOG_User_Role_Link ( id_user , id_role , active , id_user_created_by ) SELECT t_USER.id_user , t_USER.id_role , t_USER.active , a_id_user AS id_user_created_by FROM tmp_User_Save_User t_USER WHERE t_USER.id_role IS NOT NULL AND t_USER.id_role_previous IS NULL ; END IF; IF EXISTS (SELECT * FROM tmp_User_Save_User t_USER WHERE t_USER.id_role <> t_USER.id_role_previous LIMIT 1) THEN UPDATE fetchmetrics.DOG_User_Role_Link USER_ROLE_LINK INNER JOIN tmp_User_Save_User t_USER ON USER_ROLE_LINK.id_user = t_USER.id_user SET USER_ROLE_LINK.id_role = t_USER.id_role , USER_ROLE_LINK.id_change_set = v_id_change_set ; END IF; COMMIT; END IF; START TRANSACTION; DELETE FROM fetchmetrics.DOG_User_Temp WHERE GUID = a_guid; COMMIT; # Errors SELECT * FROM tmp_Msg_Error t_ME INNER JOIN fetchmetrics.CORE_Msg_Error_Type MET ON t_ME.id_type = MET.id_type ; IF a_debug = 1 THEN SELECT * from tmp_User_Save_User; END IF; DROP TABLE IF EXISTS tmp_Msg_Error; DROP TABLE IF EXISTS tmp_User_Save_User; IF a_debug = 1 THEN CALL fetchmetrics.p_debug_timing_reporting ( v_time_start ); END IF; END // DELIMITER ; /* CALL fetchmetrics.p_dog_clear_calc_user_access( 'greensgreensgreensgreensgreensgreens' -- guid , 0 -- debug ); CALL fetchmetrics.p_dog_calc_user_access( 'greensgreensgreensgreensgreensgreens' -- a_guid , 0 -- get_all_user , 0 -- get_inactive_user , 1 -- ids_user , '' -- a_auth0_ids_user , '' -- a_names_user , '' -- a_emails_user , 1 -- a_require_all_id_search_filters_met , 1 -- a_require_any_id_search_filters_met , 0 -- a_require_all_non_id_search_filters_met , 0 -- a_require_any_non_id_search_filters_met , 15 -- ids_permission , 2 -- ids_access_level , 0 -- a_show_errors , 0 -- a_debug ); SELECT * FROM fetchmetrics.DOG_Calc_User_Access_Temp; CALL fetchmetrics.p_dog_clear_calc_user_access( 'greensgreensgreensgreensgreensgreens' -- guid , 0 -- debug ); SELECT * FROM fetchmetrics.DOG_Calc_User_Access_Temp; CALL fetchmetrics.p_dog_save_user ( 'Test' -- comment , 'greensgreensgreensgreensgreensgreens' -- guid , 1 -- id_user , 1 -- debug ); CALL fetchmetrics.p_dog_clear_calc_user_access( 'greensgreensgreensgreensgreensgreens' -- guid , 0 -- debug ); select * from fetchmetrics.DOG_User_Change_Set ; select * from fetchmetrics.DOG_Role ; select * from fetchmetrics.DOG_Permission ; -- INSERT INTO fetchmetrics.DOG_User_Change_Set (comment ) VALUES ( 'Client role permissions' ); UPDATE fetchmetrics.DOG_Role_Permission_Link ROLE_PERMISSION_LINK SET ROLE_PERMISSION_LINK.id_change_set = (SELECT UCS.id_change_set FROM fetchmetrics.DOG_User_Change_Set UCS ORDER BY UCS.id_change_set DESC LIMIT 1) , ROLE_PERMISSION_LINK.id_access_level = 2 WHERE ROLE_PERMISSION_LINK.id_permission = 15 AND ROLE_PERMISSION_LINK.id_role <> 1 ; SELECT USERS.email , ROLE.name , PERMISSION.name , ACCESS_LEVEL.name FROM fetchmetrics.DOG_User USERS INNER JOIN fetchmetrics.DOG_User_Role_Link URL ON USERS.id_user = URL.id_user INNER JOIN fetchmetrics.DOG_Role ROLE ON URL.id_role = ROLE.id_role INNER JOIN fetchmetrics.DOG_Role_Permission_Link RPL ON URL.id_role = RPL.id_role INNER JOIN fetchmetrics.DOG_Permission PERMISSION ON RPL.id_permission = PERMISSION.id_permission INNER JOIN fetchmetrics.DOG_Access_Level ACCESS_LEVEL ON RPL.id_access_level = ACCESS_LEVEL.id_access_level ; */