- name: Verify password_hash throws on weird salt_size type
  set_fact:
    foo: '{{"hey"|password_hash(salt_size=[999])}}'
  ignore_errors: yes
  register: password_hash_1

- name: Verify password_hash throws on weird hashtype
  set_fact:
    foo: '{{"hey"|password_hash(hashtype="supersecurehashtype")}}'
  ignore_errors: yes
  register: password_hash_2

- name: Debug the output for the next assert
  debug:
    msg: "{{ 'what in the WORLD is up?'|password_hash }}"

- name: Verify password_hash
  assert:
    that:
      - "'what in the WORLD is up?'|password_hash|length in [crypt_len, passlib_len]"
      - password_hash_1 is failed
      - password_hash_2 is failed
      - "'is not in the list of supported' in password_hash_2.msg or 'does not support' in password_hash_2.msg"
  vars:
    # omitted rounds
    crypt_len: 106
    # included $rounds=656000
    passlib_len: 120

- name: test using an unsupported hash type
  set_fact:
    foo: '{{"hey"|password_hash("msdcc")}}'
  ignore_errors: yes
  register: unsupported_hash_type

- assert:
    that:
      - "'is not in the list of supported' in unsupported_hash_type.msg or 'does not support' in unsupported_hash_type.msg"

- name: Test if yescrypt is available
  set_fact:
    yescrypt_test: "{{ 'test' | password_hash('yescrypt') }}"
  ignore_errors: yes
  register: yescrypt_available

- name: Determine if yescrypt is supported
  set_fact:
    yescrypt_supported: "{{ yescrypt_available is not failed }}"

- name: Fail if libxcrypt was installed but yescrypt is not supported
  when: expect_libxcrypt | default(false)
  assert:
    that:
      - yescrypt_supported
    fail_msg: "libxcrypt was installed but yescrypt is not supported"

- name: Test yescrypt hashing
  when:
    - is_crypt|default(false)
    - yescrypt_supported
  block:
    - name: Generate yescrypt hash with default cost
      set_fact:
        yescrypt_hash: "{{ 'test_password' | password_hash('yescrypt') }}"

    - name: Verify yescrypt hash format
      assert:
        that:
          - yescrypt_hash.startswith('$y$')
          - yescrypt_hash | length > 60

    - name: Generate yescrypt hash with custom cost
      set_fact:
        yescrypt_hash_cost7: "{{ 'test_password' | password_hash('yescrypt', rounds=7) }}"

    - name: Verify yescrypt hash with custom cost
      assert:
        that:
          - yescrypt_hash_cost7.startswith('$y$jBT$')
          - yescrypt_hash_cost7 | length > 60

    - name: Generate yescrypt hash with custom salt
      set_fact:
        yescrypt_hash_salt: "{{ 'test_password' | password_hash('yescrypt', salt='abcdefghijklmnop') }}"

    - name: Verify yescrypt hash with custom salt
      assert:
        that:
          - yescrypt_hash_salt == '$y$j9T$V7qMYJaNbVKOeh4PhtqPk/$x7rTqZ.RpI07.dkBSxcg.jLM8ODUfx25rCN0cFsAUg0'

    - name: Test salt with invalid character
      set_fact:
        md5_hash: "{{ 'test' | password_hash('md5_crypt', salt='123^') }}"
      ignore_errors: yes
      register: bad_salt_result

    - name: Determine if bad salt character was recognized
      assert:
        that: bad_salt_result.msg is contains 'invalid characters in salt'

    - name: Test supplying invalid salt size with algo needing exact size
      set_fact:
        bcrypt_hash: "{{ 'test' | password_hash('bcrypt', salt='12345', salt_size=5) }}"
      ignore_errors: yes
      register: bad_salt_result

    - name: Determine if salt size mismatch caught
      assert:
        that: bad_salt_result.msg is contains 'invalid salt size supplied (5), expected 22'

    - name: Test salt with exact size mismatch
      set_fact:
        bcrypt_hash: "{{ 'test' | password_hash('bcrypt', salt='123') }}"
      ignore_errors: yes
      register: bad_salt_result

    - name: Determine if salt size mismatch caught
      assert:
        that: bad_salt_result.msg is contains 'invalid salt size supplied (3), expected 22'

    - name: Test supplying too big salt
      set_fact:
        bcrypt_hash: "{{ 'test' | password_hash('md5_crypt', salt='1234567890') }}"
      ignore_errors: yes
      register: bad_salt_result

    - name: Determine if too big salt caught
      assert:
        that: bad_salt_result.msg is contains 'invalid salt size supplied (10), expected at most 8'

    - name: Test supplying too big salt size
      set_fact:
        bcrypt_hash: "{{ 'test' | password_hash('md5_crypt', salt='1234567890', salt_size=10) }}"
      ignore_errors: yes
      register: bad_salt_result

    - name: Determine if too big salt size caught
      assert:
        that: bad_salt_result.msg is contains 'invalid salt size supplied (10), expected at most 8'
