@@ -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,107 @@ 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+ const result = [ ] ;
621+ let index = 1 ;
622+ let check_key = base_key . replace ( '{index}' , String ( index ) ) ;
623+
624+ while ( body [ check_key ] !== undefined ) {
625+ result . push ( mapper ? mapper ( body , index ) : body [ check_key ] ) ;
626+ index += 1 ;
627+ check_key = base_key . replace ( '{index}' , String ( index ) ) ;
628+ }
629+ return result ;
630+ }
631+
632+ /**
633+ * parse_tags_from_request_body parses tags from request body
634+ * converts AWS encoded indexed members to array of tag objects
635+ * example input: { tags_member_1_key: 'env', tags_member_1_value: 'prod', tags_member_2_key: 'team', tags_member_2_value: 'backend' }
636+ * example output: [{ key: 'env', value: 'prod' }, { key: 'team', value: 'backend' }]
637+ * @param {object } body - request body
638+ * @returns {Array<{key: string, value: string}> } array of tag objects
639+ */
640+ function parse_tags_from_request_body ( body ) {
641+ return parse_indexed_members (
642+ body ,
643+ 'tags_member_{index}_key' ,
644+ ( req_body , index ) => ( {
645+ key : req_body [ `tags_member_${ index } _key` ] ,
646+ value : req_body [ `tags_member_${ index } _value` ] || ''
647+ } )
648+ ) ;
649+ }
650+
651+ /**
652+ * parse_tag_keys_from_request_body parses tag keys from request body
653+ * converts AWS encoded indexed members to array
654+ * example input: { tag_keys_member_1: 'env', tag_keys_member_2: 'team' }
655+ * example output: ['env', 'team']
656+ * @param {object } body - request body
657+ * @returns {Array<string> } array of tag keys
658+ */
659+ function parse_tag_keys_from_request_body ( body ) {
660+ return parse_indexed_members ( body , 'tag_keys_member_{index}' ) ;
661+ }
662+
663+ /**
664+ * validate_tag_user_params checks the params for tag_user action
665+ * @param {object } params
666+ */
667+ function validate_tag_user_params ( params ) {
668+ try {
669+ check_required_username ( params ) ;
670+ validation_utils . validate_username ( params . username , iam_constants . IAM_PARAMETER_NAME . USERNAME ) ;
671+ validation_utils . validate_iam_tags ( params . tags ) ;
672+ } catch ( err ) {
673+ translate_rpc_error ( err ) ;
674+ }
675+ }
676+
677+ /**
678+ * validate_untag_user_params checks the params for untag_user action
679+ * @param {object } params
680+ */
681+ function validate_untag_user_params ( params ) {
682+ try {
683+ check_required_username ( params ) ;
684+ validation_utils . validate_username ( params . username , iam_constants . IAM_PARAMETER_NAME . USERNAME ) ;
685+ validation_utils . validate_iam_tag_keys ( params . tag_keys ) ;
686+ } catch ( err ) {
687+ translate_rpc_error ( err ) ;
688+ }
689+ }
690+
691+ /**
692+ * validate_list_user_tags_params checks the params for list_user_tags action
693+ * @param {object } params
694+ */
695+ function validate_list_user_tags_params ( params ) {
696+ try {
697+ check_required_username ( params ) ;
698+ validation_utils . validate_username ( params . username , iam_constants . IAM_PARAMETER_NAME . USERNAME ) ;
699+ validate_marker ( params . marker ) ;
700+ validate_max_items ( params . max_items ) ;
701+ } catch ( err ) {
702+ translate_rpc_error ( err ) ;
703+ }
704+ }
705+
584706// EXPORTS
585707exports . format_iam_xml_date = format_iam_xml_date ;
586708exports . create_arn_for_user = create_arn_for_user ;
@@ -593,4 +715,10 @@ exports.validate_iam_path = validate_iam_path;
593715exports . validate_marker = validate_marker ;
594716exports . validate_access_key_id = validate_access_key_id ;
595717exports . validate_status = validate_status ;
718+ exports . parse_indexed_members = parse_indexed_members ;
719+ exports . parse_tags_from_request_body = parse_tags_from_request_body ;
720+ exports . parse_tag_keys_from_request_body = parse_tag_keys_from_request_body ;
721+ exports . validate_tag_user_params = validate_tag_user_params ;
722+ exports . validate_untag_user_params = validate_untag_user_params ;
723+ exports . validate_list_user_tags_params = validate_list_user_tags_params ;
596724
0 commit comments