- vars:
    task_parameters: &task_parameters
      become_user: "{{ pg_user }}"
      become: yes
      register: result
    postgresql_parameters: &parameters
      db: postgres
      name: "{{ db_user1 }}"
      login_user: "{{ pg_user }}"

  block:
  - name: 'Check that PGOPTIONS environment variable is effective (1/2)'
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      password: '{{ db_password1 }}'
    ignore_errors: true
    environment:
      PGCLIENTENCODING: 'UTF8'
      PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

  - name: 'Check that PGOPTIONS environment variable is effective (2/2)'
    assert:
      that:
          - "{{ result is failed }}"

  - name: 'Create a user (password encrypted: {{ encrypted }})'
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      password: '{{ db_password1 }}'
      encrypted: '{{ encrypted }}'
    environment:
      PGCLIENTENCODING: 'UTF8'

  - block: &changed # block is only used here in order to be able to define YAML anchor
    - name: Check that ansible reports it was created
      assert:
        that:
          - "{{ result is changed }}"

  - name: Check that it was created
    <<: *task_parameters
    shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres

  - assert:
      that:
        - "result.stdout_lines[-1] == '(1 row)'"

  - name: Check that creating user a second time does nothing
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      password: '{{ db_password1 }}'
      encrypted: '{{ encrypted }}'
    environment:
      PGCLIENTENCODING: 'UTF8'
      PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

  - block: &not_changed # block is only used here in order to be able to define YAML anchor
    - name: Check that ansible reports no change
      assert:
        that:
          - "{{ result is not changed }}"

  - name: 'Define an expiration time'
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      expires: '2025-01-01'
    environment:
      PGCLIENTENCODING: 'UTF8'

  - <<: *changed

  - name: 'Redefine the same expiration time'
    <<: *task_parameters
    postgresql_user:
      expires: '2025-01-01'
      <<: *parameters
    environment:
      PGCLIENTENCODING: 'UTF8'
      PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

  - <<: *not_changed

  - block:

    - name: 'Using MD5-hashed password: check that password not changed when using cleartext password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: '{{ db_password1 }}'
        encrypted: 'yes'
      environment:
        PGCLIENTENCODING: 'UTF8'
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: "Using MD5-hashed password: check that password not changed when using md5 hash with 'ENCRYPTED'"
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "md5{{ (db_password1 ~ db_user1) | hash('md5')}}"
        encrypted: 'yes'
      environment:
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: "Using MD5-hashed password: check that password not changed when using md5 hash with 'UNENCRYPTED'"
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "md5{{ (db_password1 ~ db_user1) | hash('md5')}}"
        encrypted: 'no'
      environment:
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Redefine the same expiration time and password (encrypted)'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        encrypted: 'yes'
        password: "md5{{ (db_password1 ~ db_user1) | hash('md5')}}"
        expires: '2025-01-01'
      environment:
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Using MD5-hashed password: check that password changed when using another cleartext password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: 'prefix{{ db_password1 }}'
        encrypted: 'yes'
      environment:
        PGCLIENTENCODING: 'UTF8'

    - <<: *changed

    - name: "Using MD5-hashed password: check that password changed when using another md5 hash with 'ENCRYPTED'"
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "md5{{ ('prefix1' ~ db_password1 ~ db_user1) | hash('md5')}}"
        encrypted: 'yes'

    - <<: *changed

    - name: "Using MD5-hashed password: check that password changed when using md5 hash with 'UNENCRYPTED'"
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "md5{{ ('prefix2' ~ db_password1 ~ db_user1) | hash('md5')}}"
        encrypted: 'no'
      register: change_pass_unencrypted
      failed_when:
      - change_pass_unencrypted is failed
      # newer version of psycopg2 no longer supported unencrypted password, we ignore the error
      - '"UNENCRYPTED PASSWORD is no longer supported" not in change_pass_unencrypted.msg'

    - <<: *changed

    - name: 'Using MD5-hashed password: check that password changed when clearing the password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: ''
        encrypted: 'yes'
      environment:
        PGCLIENTENCODING: 'UTF8'

    - <<: *changed

    - name: 'Using MD5-hashed password: check that password not changed when clearing the password again'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: ''
        encrypted: 'yes'
      environment:
        PGCLIENTENCODING: 'UTF8'
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Using cleartext password: check that password not changed when clearing the password again'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: ''
        encrypted: 'no'
      environment:
        PGCLIENTENCODING: 'UTF8'
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Using MD5-hashed password: check that password changed when using a cleartext password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: '{{ db_password1 }}'
        encrypted: 'yes'
      environment:
        PGCLIENTENCODING: 'UTF8'

    - <<: *changed

    when: encrypted == 'yes'

  - block:

    - name: 'Using cleartext password: check that password not changed when using cleartext password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "{{ db_password1 }}"
        encrypted: 'no'
      environment:
        PGCLIENTENCODING: 'UTF8'
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Redefine the same expiration time and password (not encrypted)'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "{{ db_password1 }}"
        encrypted: 'no'
        expires: '2025-01-01'
      environment:
        PGCLIENTENCODING: 'UTF8'
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Using cleartext password: check that password changed when using another cleartext password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "changed{{ db_password1 }}"
        encrypted: 'no'
      environment:
        PGCLIENTENCODING: 'UTF8'

    - <<: *changed

    - name: 'Using cleartext password: check that password changed when clearing the password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: ''
        encrypted: 'no'
      environment:
        PGCLIENTENCODING: 'UTF8'

    - <<: *changed

    - name: 'Using cleartext password: check that password not changed when clearing the password again'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: ''
        encrypted: 'no'
      environment:
        PGCLIENTENCODING: 'UTF8'
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Using MD5-hashed password: check that password not changed when clearing the password again'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: ''
        encrypted: 'yes'
      environment:
        PGCLIENTENCODING: 'UTF8'
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

    - <<: *not_changed

    - name: 'Using cleartext password: check that password changed when using cleartext password'
      <<: *task_parameters
      postgresql_user:
        <<: *parameters
        password: "{{ db_password1 }}"
        encrypted: 'no'
      environment:
        PGCLIENTENCODING: 'UTF8'

    - <<: *changed

    when: encrypted == 'no'

  - name: Remove user
    <<: *task_parameters
    postgresql_user:
      state: 'absent'
      <<: *parameters

  - <<: *changed

  - name: Check that they were removed
    <<: *task_parameters
    shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres
    environment:
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

  - assert:
      that:
        - "result.stdout_lines[-1] == '(0 rows)'"

  - name: Check that removing user a second time does nothing
    <<: *task_parameters
    postgresql_user:
      state: 'absent'
      <<: *parameters
    environment:
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

  - <<: *not_changed

  always:
  - name: Remove user
    <<: *task_parameters
    postgresql_user:
      state: 'absent'
      <<: *parameters
