
    Vhs                         d dl mZmZmZ eZdZdZdZd dl	m
Z
mZmZmZmZ d dlmZ d dlmZ d dlmZ d d	lZd
 Zd Zd Zedk(  r e        y	y	)    )absolute_importdivisionprint_functiona!  
module: keycloak_userprofile

short_description: Allows managing Keycloak User Profiles

description:
  - This module allows you to create, update, or delete Keycloak User Profiles using the Keycloak API. You can also customize
    the "Unmanaged Attributes" with it.
  - The names of module options are snake_cased versions of the camelCase ones found in the Keycloak API and its documentation
    at U(https://www.keycloak.org/docs-api/24.0.5/rest-api/index.html). For compatibility reasons, the module also accepts
    the camelCase versions of the options.
version_added: "9.4.0"

attributes:
  check_mode:
    support: full
  diff_mode:
    support: full
  action_group:
    version_added: 10.2.0

options:
  state:
    description:
      - State of the User Profile provider.
      - On V(present), the User Profile provider will be created if it does not yet exist, or updated with the parameters
        you provide.
      - On V(absent), the User Profile provider will be removed if it exists.
    default: 'present'
    type: str
    choices:
      - present
      - absent

  parent_id:
    description:
      - The parent ID of the realm key. In practice the ID (name) of the realm.
    aliases:
      - parentId
      - realm
    type: str
    required: true

  provider_id:
    description:
      - The name of the provider ID for the key (supported value is V(declarative-user-profile)).
    aliases:
      - providerId
    choices: ['declarative-user-profile']
    default: 'declarative-user-profile'
    type: str

  provider_type:
    description:
      - Component type for User Profile (only supported value is V(org.keycloak.userprofile.UserProfileProvider)).
    aliases:
      - providerType
    choices: ['org.keycloak.userprofile.UserProfileProvider']
    default: org.keycloak.userprofile.UserProfileProvider
    type: str

  config:
    description:
      - The configuration of the User Profile Provider.
    type: dict
    required: false
    suboptions:
      kc_user_profile_config:
        description:
          - Define a declarative User Profile. See EXAMPLES for more context.
        aliases:
          - kcUserProfileConfig
        type: list
        elements: dict
        suboptions:
          attributes:
            description:
              - A list of attributes to be included in the User Profile.
            type: list
            elements: dict
            suboptions:
              name:
                description:
                  - The name of the attribute.
                type: str
                required: true

              display_name:
                description:
                  - The display name of the attribute.
                aliases:
                  - displayName
                type: str
                required: true

              validations:
                description:
                  - The validations to be applied to the attribute.
                type: dict
                suboptions:
                  length:
                    description:
                      - The length validation for the attribute.
                    type: dict
                    suboptions:
                      min:
                        description:
                          - The minimum length of the attribute.
                        type: int
                      max:
                        description:
                          - The maximum length of the attribute.
                        type: int
                        required: true

                  email:
                    description:
                      - The email validation for the attribute.
                    type: dict

                  username_prohibited_characters:
                    description:
                      - The prohibited characters validation for the username attribute.
                    type: dict
                    aliases:
                      - usernameProhibitedCharacters

                  up_username_not_idn_homograph:
                    description:
                      - The validation to prevent IDN homograph attacks in usernames.
                    type: dict
                    aliases:
                      - upUsernameNotIdnHomograph

                  person_name_prohibited_characters:
                    description:
                      - The prohibited characters validation for person name attributes.
                    type: dict
                    aliases:
                      - personNameProhibitedCharacters

                  uri:
                    description:
                      - The URI validation for the attribute.
                    type: dict

                  pattern:
                    description:
                      - The pattern validation for the attribute using regular expressions.
                    type: dict

                  options:
                    description:
                      - Validation to ensure the attribute matches one of the provided options.
                    type: dict

              annotations:
                description:
                  - Annotations for the attribute.
                type: dict

              group:
                description:
                  - Specifies the User Profile group where this attribute will be added.
                type: str

              permissions:
                description:
                  - The permissions for viewing and editing the attribute.
                type: dict
                suboptions:
                  view:
                    description:
                      - The roles that can view the attribute.
                      - Supported values are V(admin) and V(user).
                    type: list
                    elements: str
                    default:
                      - admin
                      - user

                  edit:
                    description:
                      - The roles that can edit the attribute.
                      - Supported values are V(admin) and V(user).
                    type: list
                    elements: str
                    default:
                      - admin
                      - user

              multivalued:
                description:
                  - Whether the attribute can have multiple values.
                type: bool
                default: false

              required:
                description:
                  - The roles that require this attribute.
                type: dict
                suboptions:
                  roles:
                    description:
                      - The roles for which this attribute is required.
                      - Supported values are V(admin) and V(user).
                    type: list
                    elements: str
                    default:
                      - user

          groups:
            description:
              - A list of attribute groups to be included in the User Profile.
            type: list
            elements: dict
            suboptions:
              name:
                description:
                  - The name of the group.
                type: str
                required: true

              display_header:
                description:
                  - The display header for the group.
                aliases:
                  - displayHeader
                type: str
                required: true

              display_description:
                description:
                  - The display description for the group.
                aliases:
                  - displayDescription
                type: str
                required: false

              annotations:
                description:
                  - The annotations included in the group.
                type: dict
                required: false

          unmanaged_attribute_policy:
            description:
              - Policy for unmanaged attributes.
            aliases:
              - unmanagedAttributePolicy
            type: str
            choices:
              - ENABLED
              - ADMIN_EDIT
              - ADMIN_VIEW

notes:
  - Currently, only a single V(declarative-user-profile) entry is supported for O(provider_id) (design of the Keyckoak API).
    However, there can be multiple O(config.kc_user_profile_config[].attributes[]) entries.
extends_documentation_fragment:
  - community.general.keycloak
  - community.general.keycloak.actiongroup_keycloak
  - community.general.attributes

author:
  - Eike Waldt (@yeoldegrove)
a  
- name: Create a Declarative User Profile with default settings
  community.general.keycloak_userprofile:
    state: present
    parent_id: master
    config:
      kc_user_profile_config:
        - attributes:
            - name: username
              displayName: ${username}
              validations:
                length:
                  min: 3
                  max: 255
                username_prohibited_characters: {}
                up_username_not_idn_homograph: {}
              annotations: {}
              permissions:
                view:
                  - admin
                  - user
                edit: []
              multivalued: false
            - name: email
              displayName: ${email}
              validations:
                email: {}
                length:
                  max: 255
              annotations: {}
              required:
                roles:
                  - user
              permissions:
                view:
                  - admin
                  - user
                edit: []
              multivalued: false
            - name: firstName
              displayName: ${firstName}
              validations:
                length:
                  max: 255
                person_name_prohibited_characters: {}
              annotations: {}
              required:
                roles:
                  - user
              permissions:
                view:
                  - admin
                  - user
                edit: []
              multivalued: false
            - name: lastName
              displayName: ${lastName}
              validations:
                length:
                  max: 255
                person_name_prohibited_characters: {}
              annotations: {}
              required:
                roles:
                  - user
              permissions:
                view:
                  - admin
                  - user
                edit: []
              multivalued: false
          groups:
            - name: user-metadata
              displayHeader: User metadata
              displayDescription: Attributes, which refer to user metadata
              annotations: {}

- name: Delete a Keycloak User Profile Provider
  keycloak_userprofile:
    state: absent
    parent_id: master

# Unmanaged attributes are user attributes not explicitly defined in the User Profile
# configuration. By default, unmanaged attributes are "Disabled" and are not
# available from any context such as registration, account, and the
# administration console. By setting "Enabled", unmanaged attributes are fully
# recognized by the server and accessible through all contexts, useful if you are
# starting migrating an existing realm to the declarative User Profile
# and you don't have yet all user attributes defined in the User Profile configuration.
- name: Enable Unmanaged Attributes
  community.general.keycloak_userprofile:
    state: present
    parent_id: master
    config:
      kc_user_profile_config:
        - unmanagedAttributePolicy: ENABLED

# By setting "Only administrators can write", unmanaged attributes can be managed
# only through the administration console and API, useful if you have already
# defined any custom attribute that can be managed by users but you are unsure
# about adding other attributes that should only be managed by administrators.
- name: Enable ADMIN_EDIT on Unmanaged Attributes
  community.general.keycloak_userprofile:
    state: present
    parent_id: master
    config:
      kc_user_profile_config:
        - unmanagedAttributePolicy: ADMIN_EDIT

# By setting `Only administrators can view`, unmanaged attributes are read-only
# and only available through the administration console and API.
- name: Enable ADMIN_VIEW on Unmanaged Attributes
  community.general.keycloak_userprofile:
    state: present
    parent_id: master
    config:
      kc_user_profile_config:
        - unmanagedAttributePolicy: ADMIN_VIEW
a  
msg:
  description: The output message generated by the module.
  returned: always
  type: str
  sample: UserProfileProvider created successfully
data:
  description: The data returned by the Keycloak API.
  returned: when state is present
  type: dict
  sample: {'...': '...'}
)KeycloakAPIcamelkeycloak_argument_spec	get_tokenKeycloakError)AnsibleModule)	urlencode)deepcopyNc                     t        | t              r0| j                         D ci c]  \  }}|	|t        |       c}}S t        | t              r| D cg c]  }|t        |       c}S | S c c}}w c c}w N)
isinstancedictitemsremove_null_valueslistdatakvitems       z/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/keycloak_userprofile.pyr   r     so    $59ZZ\STQQ]%a((SS	D$	59NTT=M"4(NN  T Os   
A/A/A5A5c                     t        | t              r6| j                         D ci c]  \  }}t        |      t	        |       c}}S t        | t
              r| D cg c]  }t	        |       c}S | S c c}}w c c}w r   )r   r   r   r   camel_recursiver   r   s       r   r   r     sg    $9=FAa/!,,FF	D$	267$%77  G 8s   A2A8c            %         t               } t        t        dddgd      t        dddgd      t        dd	gd
d
g      t        ddgddg      t        dddt        ddgdt        dddt        dd      t        ddgd      t        dt        dt        dd      t        dd      d      t        dd      t        ddgd      t        ddgd      t        ddgd      t        dd      t        dd      t        dd      d      t        d      t        d      t        dt        ddddg      t        ddddg      d       t        d!d"      t        dd#t        dddg      i      d$%      t        ddt        dd      t        dd&gd      t        dd'gd      t        dd      d()      t        dd*gg d+d,      d-.      i/      0      }| j                  |       t        | dg d1gg d2gd3d4i5      }t        dd6i t        i i 7      8      }i }i |d9<   	 t	        |j
                        }t        |      }t        t               j                               d;gz   }|j
                  D 	cg c]#  }	|	|vr|j
                  j                  |	      |	% }
}	i }|j
                  j                  d9      }i |d9<   |
D ]  }|dk(  s|d<k(  r1|j
                  j                  |      |d<<   |j                  |d        ?|d9k(  rz|D ]r  }|d=v r|}d>}t        ||         }g |t        |         |<   t!        |      d?kD  s:t#        |      }d@|d?   v rv|d?   d@   D ]k  }dA|v sd|dA   v r|dA   j                  d      |dA   dB<   d|dA   v r|dA   j                  d      |dA   dC<   d|dA   v sR|dA   j                  d      |dA   dD<   m |t        |         |   j%                  |d?          g |t        |         t        |      <   |j
                  j                  |      |   }t'        |t(              rt        |      j+                         }n|}|t        |         t        |         j%                  |       u |j
                  j                  |      }||t        |      <    |j
                  j                  d;      }|j
                  j                  dE      }|j
                  j                  d<      }|j
                  j                  dF      }|j
                  j                  dG      }t-        |      }|j/                  t1        t        |            |      }d }d6}d|dH<   |D ]  }|d
k(  s	|dI   }||dI<   ||dI<   d9|v r.d>|d9   v r't3        j4                  |d9   d>   d?         |d9   d>   d?<   |j7                         D ]8  \  }}||   ||<   ||   ||   k7  s|d9k7  s ||dJ||   dK||   dLz  }d|dH<   : |d9   j7                         D ]E  \  } }!|d9   |    |d9   | <   |d9   |    |d9   |    k7  s&|dM| dJ|d9   |    dK|d9   |    dLz  }d|dH<   G  d9|v r.d>|d9   v r't3        j8                  |d9   d>   d?         |d9   d>   d?<   |r|dk(  r|dH   rp|j:                  rt        ||7      |dN<   |j<                  rdO|dP|j?                  dL      |dQ<   n5|jA                  ||       dO|dR|j?                  dL      |dQ<   ndS|z  |dQ<   ||dT<   n|r`|dk(  r[|j:                  rt        |i 7      |dN<   |j<                  rd|dH<   dU|z  |dQ<   n|jC                  ||       d|dH<   dV|z  |dQ<   i |dT<   n{|s`|dk(  r[|j:                  rt        i |7      |dN<   |j<                  rd|dH<   dW|z  |dQ<   n|jE                  ||       d|dH<   dX|z  |dQ<   ||dT<   n|s|dk(  rd|dH<   dY|z  |dQ<   i |dT<    |jF                  dZi | y # t        $ r&}|j                  t        |      :       Y d }~d }~ww xY wc c}	w )[Nstrpresentabsent)typechoicesdefaultparentIdrealmT)r!   aliasesrequired
providerIdzdeclarative-user-profile)r!   r&   r#   r"   providerTypez,org.keycloak.userprofile.UserProfileProviderr   Fkc_user_profile_configr   kcUserProfileConfig)r!   r'   displayNameint)minmax)r!   optionsusernameProhibitedCharactersupUsernameNotIdnHomographpersonNameProhibitedCharacters)lengthemailusername_prohibited_charactersup_username_not_idn_homograph!person_name_prohibited_charactersuripatternr0   )r!   adminuser)r!   elementsr#   )vieweditbool)r!   r#   roles)namedisplay_namevalidationsannotationsgrouppermissionsmultivaluedr'   )r!   r=   r'   r0   displayHeaderdisplayDescription)rB   display_headerdisplay_descriptionrE   )r!   r=   r0   unmanagedAttributePolicy)ENABLED
ADMIN_EDIT
ADMIN_VIEW)r!   r&   r"   r'   )
attributesgroupsunmanaged_attribute_policy)r!   r&   r=   r0   )r!   r'   r0   )state	parent_idprovider_idprovider_typeconfig)token
auth_realmauth_usernameauth_password)rZ   r[   r\   refresh_tokenrZ   )argument_specsupports_check_moderequired_one_ofrequired_togetherrequired_by )beforeafter)changedmsg	end_statediffrX   )rg   rT   rU   )r+   r*   zkc.user.profile.configr   rQ   rD   zusername-prohibited-characterszup-username-not-idn-homographz!person-name-prohibited-charactersenabledrW   rV   rf   idz: z -> z, zconfig.ri   zUserprofile z would be changed: rg   z
 changed: zUserprofile %s was in syncrh   zUserprofile %s would be deletedzUserprofile %s deletedzUserprofile %s would be createdzUserprofile %s createdzUserprofile %s not present )$r   r   updater   r	   paramsr
   	fail_jsonr   r   r   keysgetpopr   r   lenr   appendr   r@   lowerr   get_componentsr   jsonloadsr   dumps_diff
check_modestripupdate_componentdelete_componentcreate_component	exit_json)"r^   	meta_argsmoduleresultbefore_realm_userprofileconnection_headerekcparams_to_ignorexcomponent_params	changesetrX   component_paramconfig_paramconfig_param_orgr*   	attribute	raw_valuevaluenew_param_valuerT   rj   rU   rW   rV   changeset_copyrealm_userprofilesuserprofile_idchangesuserprofileparampr   s"                                     r   mainr     s 
   *,M	8'<iPEJ+@4Pel^E_  kE  jF  G#$BCD	
 ($23#&*!'%+%*(,%$(G04%-cg0h/3)/26177;QV7W7;QU7V5.3* 266E1RJNTZ  fD  eE  PU  KVIMSYd  dA  LQ  JRMQW]  iI  hJ  UZ  N[/3%/P37Ve3T37Ve3T-&0"& 04/@)-5)9/3)/04&5[bdjZk0l04&5[bdjZk0l-&0" 04/O,0)/(/6E\b[c1d-&-"A&%	+'X #'!'%+(,%$(G26EOK\gk2l7;QePfqv7w/3%/P	%	# 7;!&%?$@$K%*	7o=	B+DH
SIj #/3-f,g/_.`(7'F	F %R2DRT<UVF  ")+X&%%fmm4 
V.	/B2499;<yH
 $$):):1)=)I 	
  I ]]x(FIh , 0@g%K)G%+]]%6%6%GIk"MM/40( & %Y#TT'3$#;L-?GW@X-Y*FHIeO45lC12Q61@AW1X.'+A!+DD-CA-F|-T *	#0I#='ES`Ia'a,5m,D,H,HIg,h )2-(@Aa(b (CiP]F^'^,5m,D,H,HId,e )2-(@A`(a (H9UbKc'c,5m,D,H,HIi,j )2-(@Ad(e* "%"89,GNNOefgOhi NPIeO45eL6IJ & 1 1/ B< PI!)T2 #I 4 4 6 )eO45eL6IJQQRWXK%YP %mm//@O0?IeO,-a0@f MMg&Emm	*G!!+.IMM%%o6M--##M2K i(N **9T}5M+NPYZ N G F9
 * -44(.N,IdO#1N4  ;&+C{S[G\+\EIZZP[\dPef~P  AB  QC  FDH%&>?B !* 1 -u2=e2D(/!%(K,>>5HCT5+e:Ln]bNcddG(,F9%- 'x0668 -18CH8Ma8P(215!(+A.+h2G2JJ![=RST=UWefnWopqWrssG(,F9%	-'-< 9!9Yx=P!P;?::iPXFYZrFstuFv;w	(45a8%9,)||!%-E^!\v  ITV]VcVcdhVi ju##Iy9@KW]][_M` au8KHF5M,{	EX-<<!)ALF6N $F9=MF5M	: $F94DF5M { 2<<!>BF6N $F9=MF5M	95 $F94DF5M,{ 1!y4Du {Fvo  %SV$$%s   -` (a	a	#aa	__main__)
__future__r   r   r   r!   __metaclass__DOCUMENTATIONEXAMPLESRETURNUansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloakr   r   r   r	   r
   ansible.module_utils.basicr   +ansible.module_utils.six.moves.urllib.parser   copyr   rw   r   r   r   __name__rl       r   <module>r      sg    A @JXvp
5 5 4 A  		dN	 zF r   