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

  block:

  - name: Create a user with all role attributes
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      state: "present"
      role_attr_flags: "SUPERUSER,CREATEROLE,CREATEDB,INHERIT,login{{ bypassrls_supported | ternary(',BYPASSRLS', '') }}"
      no_password_changes: '{{ no_password_changes }}' # no_password_changes is ignored when user doesn't already exist

  - name: Check that the user has the requested role attributes
    <<: *task_parameters
    shell: "echo \"select 'super:'||rolsuper, 'createrole:'||rolcreaterole, 'create:'||rolcreatedb, 'inherit:'||rolinherit, 'login:'||rolcanlogin {{ bypassrls_supported | ternary(\", 'bypassrls:'||rolbypassrls\", '') }} from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"

  - assert:
      that:
        - "result.stdout_lines[-1] == '(1 row)'"
        - "'super:t' in result.stdout_lines[-2]"
        - "'createrole:t' in result.stdout_lines[-2]"
        - "'create:t' in result.stdout_lines[-2]"
        - "'inherit:t' in result.stdout_lines[-2]"
        - "'login:t' in result.stdout_lines[-2]"

  - block:
      - name: Check that the user has the requested role attribute BYPASSRLS
        <<: *task_parameters
        shell: "echo \"select 'bypassrls:'||rolbypassrls from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"

      - assert:
          that:
            - "not bypassrls_supported or 'bypassrls:t' in result.stdout_lines[-2]"
    when: bypassrls_supported

  - name: Modify a user to have no role attributes
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      state: "present"
      role_attr_flags: "NOSUPERUSER,NOCREATEROLE,NOCREATEDB,noinherit,NOLOGIN{{ bypassrls_supported | ternary(',NOBYPASSRLS', '') }}"
      no_password_changes: '{{ no_password_changes }}'

  - name: Check that ansible reports it modified the role
    assert:
      that:
        - "result.changed"

  - name: "Check that the user doesn't have any attribute"
    <<: *task_parameters
    shell: "echo \"select 'super:'||rolsuper, 'createrole:'||rolcreaterole, 'create:'||rolcreatedb, 'inherit:'||rolinherit, 'login:'||rolcanlogin from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"

  - assert:
      that:
        - "result.stdout_lines[-1] == '(1 row)'"
        - "'super:f' in result.stdout_lines[-2]"
        - "'createrole:f' in result.stdout_lines[-2]"
        - "'create:f' in result.stdout_lines[-2]"
        - "'inherit:f' in result.stdout_lines[-2]"
        - "'login:f' in result.stdout_lines[-2]"

  - block:
      - name: Check that the user has the requested role attribute BYPASSRLS
        <<: *task_parameters
        shell: "echo \"select 'bypassrls:'||rolbypassrls from pg_roles where rolname='{{ db_user1 }}';\" | psql -d postgres"

      - assert:
          that:
            - "not bypassrls_supported or 'bypassrls:f' in result.stdout_lines[-2]"
    when: bypassrls_supported

  - name: Try to add an invalid attribute
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      state: "present"
      role_attr_flags: "NOSUPERUSER,NOCREATEROLE,NOCREATEDB,noinherit,NOLOGIN{{ bypassrls_supported | ternary(',NOBYPASSRLS', '') }},INVALID"
      no_password_changes: '{{ no_password_changes }}'
    ignore_errors: True

  - name: Check that ansible reports failure
    assert:
      that:
        - "not result.changed"
        - "result.failed"
        - "result.msg == 'Invalid role_attr_flags specified: INVALID'"

  - name: Modify a single role attribute on a user
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      state: "present"
      role_attr_flags: "LOGIN"
      no_password_changes: '{{ no_password_changes }}'

  - name: Check that ansible reports it modified the role
    assert:
      that:
        - "result.changed"

  - name: Check the role attributes
    <<: *task_parameters
    shell: echo "select 'super:'||rolsuper, 'createrole:'||rolcreaterole, 'create:'||rolcreatedb, 'inherit:'||rolinherit, 'login:'||rolcanlogin from pg_roles where rolname='{{ db_user1 }}';" | psql -d postgres

  - assert:
      that:
        - "result.stdout_lines[-1] == '(1 row)'"
        - "'super:f' in result.stdout_lines[-2]"
        - "'createrole:f' in result.stdout_lines[-2]"
        - "'create:f' in result.stdout_lines[-2]"
        - "'inherit:f' in result.stdout_lines[-2]"
        - "'login:t' in result.stdout_lines[-2]"

  - block:
      - name: Check the role attribute BYPASSRLS
        <<: *task_parameters
        shell: echo "select 'bypassrls:'||rolbypassrls from pg_roles where rolname='{{ db_user1 }}';" | psql -d postgres

      - assert:
          that:
            - "( postgres_version_resp.stdout is version('9.5.0', '<')) or 'bypassrls:f' in result.stdout_lines[-2]"
    when: bypassrls_supported

  - name: Check that using same attribute a second time does nothing
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      state: "present"
      role_attr_flags: "LOGIN"
      no_password_changes: '{{ no_password_changes }}'
    environment:
        PGOPTIONS: '-c default_transaction_read_only=on' # ensure 'alter user' query isn't executed

  - name: Check there isn't any update reported
    assert:
      that:
        - "not result.changed"

  - name: Cleanup the user
    <<: *task_parameters
    postgresql_user:
      <<: *parameters
      state: 'absent'
      no_password_changes: '{{ no_password_changes }}' # user deletion: no_password_changes is ignored

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

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

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