@@ -81,12 +81,15 @@ function parse_max_items(input_max_items) {
8181}
8282
8383/**
84- * validate_params will call the aquivalent function in user or access key
84+ * validate_params will call the equivalent function (for example: user, access key, tagging, etc.)
85+ * Note: The order of conditions matters - check 'tag' before 'user' to avoid misrouting
8586 * @param {string } action
8687 * @param {object } params
8788 */
8889function validate_params ( action , params ) {
89- if ( action . includes ( 'policy' ) || action . includes ( 'policies' ) ) {
90+ if ( action . includes ( 'tag' ) ) {
91+ validate_tagging_params ( action , params ) ;
92+ } else if ( action . includes ( 'policy' ) || action . includes ( 'policies' ) ) {
9093 validate_policy_params ( action , params ) ;
9194 } else if ( action . includes ( 'user' ) ) {
9295 validate_user_params ( action , params ) ;
@@ -151,6 +154,27 @@ function validate_access_keys_params(action, params) {
151154 }
152155}
153156
157+ /**
158+ * validate_tagging_params will call the equivalent function for each action in tagging API
159+ * @param {string } action
160+ * @param {object } params
161+ */
162+ function validate_tagging_params ( action , params ) {
163+ switch ( action ) {
164+ case iam_constants . IAM_ACTIONS . TAG_USER :
165+ validate_tag_user_params ( params ) ;
166+ break ;
167+ case iam_constants . IAM_ACTIONS . UNTAG_USER :
168+ validate_untag_user_params ( params ) ;
169+ break ;
170+ case iam_constants . IAM_ACTIONS . LIST_USER_TAGS :
171+ validate_list_user_tags_params ( params ) ;
172+ break ;
173+ default :
174+ throw new RpcError ( 'INTERNAL_ERROR' , `${ action } is not supported` ) ;
175+ }
176+ }
177+
154178/**
155179 * validate_policy_params will call the aquivalent function for each action in user policy API
156180 * @param {string } action
@@ -578,9 +602,111 @@ function translate_rpc_error(err) {
578602 const { code, http_code, type } = IamError . ValidationError ;
579603 throw new IamError ( { code, message : err . message , http_code, type } ) ;
580604 }
605+ if ( err . rpc_code === 'INVALID_INPUT' ) {
606+ const { code, http_code, type } = IamError . InvalidInput ;
607+ throw new IamError ( { code, message : err . message , http_code, type } ) ;
608+ }
581609 throw err ;
582610}
583611
612+ /**
613+ * parse_indexed_members parses indexed array members
614+ * generic parser for AWS-style indexed request parameters
615+ * @param {object } body - request body
616+ * @param {string } base_key - the base key pattern (e.g., 'tags_member_{index}_key)
617+ * @param {Function } [mapper] - optional function to convert each item
618+ */
619+ function parse_indexed_members ( body , base_key , mapper ) {
620+ try {
621+ const result = [ ] ;
622+ let index = 1 ;
623+ let check_key = base_key . replace ( '{index}' , String ( index ) ) ;
624+
625+ while ( body [ check_key ] !== undefined ) {
626+ result . push ( mapper ? mapper ( body , index ) : body [ check_key ] ) ;
627+ index += 1 ;
628+ check_key = base_key . replace ( '{index}' , String ( index ) ) ;
629+ }
630+ return result ;
631+ } catch ( err ) {
632+ throw new RpcError ( 'INVALID_INPUT' , `Error parsing request parameters: ${ err . message } ` ) ;
633+ }
634+ }
635+
636+ /**
637+ * parse_tags_from_request_body parses tags from request body
638+ * converts AWS encoded indexed members to array of tag objects
639+ * example input: { tags_member_1_key: 'env', tags_member_1_value: 'prod', tags_member_2_key: 'team', tags_member_2_value: 'backend' }
640+ * example output: [{ key: 'env', value: 'prod' }, { key: 'team', value: 'backend' }]
641+ * @param {object } body - request body
642+ * @returns {Array<{key: string, value: string}> } array of tag objects
643+ */
644+ function parse_tags_from_request_body ( body ) {
645+ return parse_indexed_members (
646+ body ,
647+ 'tags_member_{index}_key' ,
648+ ( req_body , index ) => ( {
649+ key : req_body [ `tags_member_${ index } _key` ] ,
650+ value : req_body [ `tags_member_${ index } _value` ] || ''
651+ } )
652+ ) ;
653+ }
654+
655+ /**
656+ * parse_tag_keys_from_request_body parses tag keys from request body
657+ * converts AWS encoded indexed members to array
658+ * example input: { tag_keys_member_1: 'env', tag_keys_member_2: 'team' }
659+ * example output: ['env', 'team']
660+ * @param {object } body - request body
661+ * @returns {Array<string> } array of tag keys
662+ */
663+ function parse_tag_keys_from_request_body ( body ) {
664+ return parse_indexed_members ( body , 'tag_keys_member_{index}' ) ;
665+ }
666+
667+ /**
668+ * validate_tag_user_params checks the params for tag_user action
669+ * @param {object } params
670+ */
671+ function validate_tag_user_params ( params ) {
672+ try {
673+ check_required_username ( params ) ;
674+ validation_utils . validate_username ( params . username , iam_constants . IAM_PARAMETER_NAME . USERNAME ) ;
675+ validation_utils . validate_iam_tags ( params . tags ) ;
676+ } catch ( err ) {
677+ translate_rpc_error ( err ) ;
678+ }
679+ }
680+
681+ /**
682+ * validate_untag_user_params checks the params for untag_user action
683+ * @param {object } params
684+ */
685+ function validate_untag_user_params ( params ) {
686+ try {
687+ check_required_username ( params ) ;
688+ validation_utils . validate_username ( params . username , iam_constants . IAM_PARAMETER_NAME . USERNAME ) ;
689+ validation_utils . validate_iam_tag_keys ( params . tag_keys ) ;
690+ } catch ( err ) {
691+ translate_rpc_error ( err ) ;
692+ }
693+ }
694+
695+ /**
696+ * validate_list_user_tags_params checks the params for list_user_tags action
697+ * @param {object } params
698+ */
699+ function validate_list_user_tags_params ( params ) {
700+ try {
701+ check_required_username ( params ) ;
702+ validation_utils . validate_username ( params . username , iam_constants . IAM_PARAMETER_NAME . USERNAME ) ;
703+ validate_marker ( params . marker ) ;
704+ validate_max_items ( params . max_items ) ;
705+ } catch ( err ) {
706+ translate_rpc_error ( err ) ;
707+ }
708+ }
709+
584710// EXPORTS
585711exports . format_iam_xml_date = format_iam_xml_date ;
586712exports . create_arn_for_user = create_arn_for_user ;
@@ -593,4 +719,10 @@ exports.validate_iam_path = validate_iam_path;
593719exports . validate_marker = validate_marker ;
594720exports . validate_access_key_id = validate_access_key_id ;
595721exports . validate_status = validate_status ;
722+ exports . parse_indexed_members = parse_indexed_members ;
723+ exports . parse_tags_from_request_body = parse_tags_from_request_body ;
724+ exports . parse_tag_keys_from_request_body = parse_tag_keys_from_request_body ;
725+ exports . validate_tag_user_params = validate_tag_user_params ;
726+ exports . validate_untag_user_params = validate_untag_user_params ;
727+ exports . validate_list_user_tags_params = validate_list_user_tags_params ;
596728
0 commit comments