524 lines
17 KiB
SQL
524 lines
17 KiB
SQL
|
|
|
|
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_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_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
|
|
;
|
|
|
|
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;
|
|
|
|
CALL fetchmetrics.p_dog_clear_calc_user_access( a_guid, 0 );
|
|
|
|
|
|
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
|
|
);
|
|
|
|
*/
|
|
|