SET PATH *LIBL ; CREATE OR REPLACE FUNCTION SAILPOINT.ES_V2_CHANGE_USER_PROFILE ( AUTHORIZATIONNAME VARCHAR(10) , TEXTDESCRIPTION VARCHAR(50) DEFAULT NULL , USERCLASSNAME VARCHAR(10) DEFAULT NULL , STATUS VARCHAR(10) DEFAULT NULL , SETPASSWORDTOEXPIRE VARCHAR(10) DEFAULT NULL , USEROWNER VARCHAR(10) DEFAULT NULL , GROUPPROFILENAME VARCHAR(10) DEFAULT NULL , ACCOUNTINGCODE VARCHAR(20) DEFAULT NULL , JOBDESCRIPTIONNAME VARCHAR(10) DEFAULT NULL , OUTPUTQUEUENAME VARCHAR(21) DEFAULT NULL , MESSAGEQUEUENAME VARCHAR(21) DEFAULT NULL , LIMITCAPABILITIES VARCHAR(10) DEFAULT NULL , SPECIALAUTHORITIESJSON VARCHAR(1024) DEFAULT NULL , HOMEDIRECTORY VARCHAR(255) DEFAULT NULL ) RETURNS CLOB(2147483647) LANGUAGE SQL SPECIFIC SAILPOINT.V2_ESCHGUSR NOT DETERMINISTIC MODIFIES SQL DATA CALLED ON NULL INPUT NOT FENCED SET OPTION ALWBLK = *ALLREAD , ALWCPYDTA = *OPTIMIZE , COMMIT = *NONE , DBGVIEW = *SOURCE , DECRESULT = (31, 31, 00) , DLYPRP = *NO , DYNDFTCOL = *NO , DYNUSRPRF = *OWNER , SRTSEQ = *HEX BEGIN DECLARE CMD_OUTPUT CLOB ( 64 K ) DEFAULT '' ; DECLARE CMD_STMT VARCHAR ( 2048 ) DEFAULT '' ; DECLARE ERROR_RESPONSE CLOB ( 2 G ) DEFAULT '' ; DECLARE SPECIALAUTHS VARCHAR ( 1000 ) ; -- Uniform error handler - returns pre-built error JSON DECLARE CONTINUE HANDLER FOR SQLSTATE '38001' RETURN ERROR_RESPONSE ; -- Handle QCMD exception (38501 = external routine error) DECLARE EXIT HANDLER FOR SQLSTATE '38501' RETURN JSON_OBJECT ( 'data' : JSON_ARRAY ( ) , 'errors' : JSON_ARRAY ( JSON_OBJECT ( 'status' : 404 , 'message' : 'User profile not found or command failed' ) ) ) ; -- Convert JSON array to space-separated list IF SPECIALAUTHORITIESJSON IS NOT NULL THEN SET SPECIALAUTHS = ( SELECT LISTAGG ( TRIM ( FRAGMENT ) , ' ' ) FROM TABLE ( CISTOOLS . SPLIT_STRING ( REGEXP_REPLACE ( CAST ( SPECIALAUTHORITIESJSON AS VARCHAR ( 1000 ) CCSID 37 ) , '[\[|\]|\{|\}|\""|\,|\s+]' , ' ' ) , ' ' ) ) WHERE FRAGMENT <> '' AND FRAGMENT IS NOT NULL ) ; END IF ; -- Build the command SET CMD_STMT = 'CHGUSRPRF USRPRF(' || TRIM ( AUTHORIZATIONNAME ) || ')' ; IF TEXTDESCRIPTION IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' TEXT(' || CISTOOLS . GET_QUOTED ( TEXTDESCRIPTION ) || ')' ; END IF ; IF USERCLASSNAME IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' USRCLS(' || USERCLASSNAME || ')' ; END IF ; IF STATUS IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' STATUS(' || STATUS || ')' ; END IF ; IF SETPASSWORDTOEXPIRE IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' PWDEXP(' || SETPASSWORDTOEXPIRE || ')' ; END IF ; IF USEROWNER IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' OWNER(' || USEROWNER || ')' ; END IF ; IF GROUPPROFILENAME IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' GRPPRF(' || GROUPPROFILENAME || ')' ; END IF ; IF ACCOUNTINGCODE IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' ACGCDE(' || ACCOUNTINGCODE || ')' ; END IF ; IF JOBDESCRIPTIONNAME IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' JOBD(' || JOBDESCRIPTIONNAME || ')' ; END IF ; IF OUTPUTQUEUENAME IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' OUTQ(' || OUTPUTQUEUENAME || ')' ; END IF ; IF MESSAGEQUEUENAME IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' MSGQ(' || MESSAGEQUEUENAME || ')' ; END IF ; IF LIMITCAPABILITIES IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' LMTCPB(' || LIMITCAPABILITIES || ')' ; END IF ; IF HOMEDIRECTORY IS NOT NULL THEN SET CMD_STMT = CMD_STMT || ' HOMEDIR(' || CISTOOLS . GET_QUOTED ( HOMEDIRECTORY ) || ')' ; END IF ; IF SPECIALAUTHS IS NOT NULL AND LENGTH ( TRIM ( SPECIALAUTHS ) ) > 0 THEN SET CMD_STMT = CMD_STMT || ' SPCAUT(' || SPECIALAUTHS || ')' ; END IF ; -- Execute via QCMD and capture output SET CMD_OUTPUT = CISTOOLS . QCMD ( CMD_STMT ) ; -- Check if any CPF/CPD errors exist (CPF=failure, CPD=diagnostic, CPC=completio--n/success) IF CMD_OUTPUT LIKE '%CPF%' OR CMD_OUTPUT LIKE '%CPD%' THEN -- Build errors array from all error lines in output SET ERROR_RESPONSE = ( SELECT JSON_OBJECT ( 'data' : JSON_ARRAY ( ) , 'errors' : JSON_ARRAYAGG ( JSON_OBJECT ( 'status' : CASE WHEN FRAGMENT LIKE '%CPF2204%' THEN 404 WHEN FRAGMENT LIKE '%CPF2213%' THEN 403 WHEN FRAGMENT LIKE '%CPF2217%' THEN 423 WHEN FRAGMENT LIKE '%CPF2225%' THEN 403 WHEN FRAGMENT LIKE '%CPF2203%' THEN 404 WHEN FRAGMENT LIKE '%CPF2209%' THEN 404 WHEN FRAGMENT LIKE '%CPF2292%' THEN 403 ELSE 500 END , 'message' : CASE WHEN FRAGMENT LIKE '%CPF2204%' THEN 'User profile not found' WHEN FRAGMENT LIKE '%CPF2213%' THEN 'Not authorized to change user profile' WHEN FRAGMENT LIKE '%CPF2217%' THEN 'Not able to allocate user profile' WHEN FRAGMENT LIKE '%CPF2225%' THEN '*SECADM required to create or change user profiles' WHEN FRAGMENT LIKE '%CPF2203%' THEN 'Group profile not found' WHEN FRAGMENT LIKE '%CPF2209%' THEN 'Library not found' WHEN FRAGMENT LIKE '%CPF2292%' THEN 'User profile does not have all special authorities being granted' ELSE TRIM ( FRAGMENT ) END ) ) ) FROM TABLE ( CISTOOLS . SPLIT_STRING ( CMD_OUTPUT , X'25' ) ) AS T WHERE FRAGMENT LIKE '%CPF%' OR FRAGMENT LIKE '%CPD%' ) ; SIGNAL SQLSTATE '38001' ; END IF ; -- Success - return user info with specialAuthorities as array RETURN ( SELECT JSON_OBJECT ( 'data' : JSON_ARRAY ( JSON_OBJECT ( 'authorizationName' VALUE AUTHORIZATION_NAME , 'textDescription' VALUE TEXT_DESCRIPTION , 'userClassName' VALUE USER_CLASS_NAME , 'status' VALUE STATUS , 'groupProfileName' VALUE GROUP_PROFILE_NAME , 'homeDirectory' VALUE HOME_DIRECTORY , 'specialAuthorities' VALUE ( SELECT JSON_ARRAYAGG ( TRIM ( FRAGMENT ) ) FROM TABLE ( CISTOOLS . SPLIT_STRING ( TRIM ( CAST ( A . SPECIAL_AUTHORITIES AS VARCHAR ( 528 ) CCSID 37 ) ) , ' ' ) ) WHERE TRIM ( FRAGMENT ) <> '' ) , 'lastUsedTimestamp' VALUE LAST_USED_TIMESTAMP ) ) , 'errors' : JSON_ARRAY ( ) ) FROM QSYS2 . USER_INFO A WHERE AUTHORIZATION_NAME = UPPER ( AUTHORIZATIONNAME ) ) ; END ; GRANT ALTER , EXECUTE ON SPECIFIC FUNCTION SAILPOINT.V2_ESCHGUSR TO AMAPICS WITH GRANT OPTION ; GRANT EXECUTE ON SPECIFIC FUNCTION SAILPOINT.V2_ESCHGUSR TO PUBLIC ;