---
### properties:
###   postgres_acls:
###     - name
###     - password
###     - trusted_cidr_entry [shared_service_network]

- name: "Updating pg_hba.conf entries for postgres admin user"
  lineinfile:
    state: present
    regex: "^hostssl[ ]+all[ ]+{{ postgres_admin_user }}"
    line: |-
      hostssl    all    {{ postgres_admin_user }}    {{ shared_service_network }} md5
    path: /etc/postgresql/{{ default_postgres_version }}/main/pg_hba.conf

- name: "Updating pg_hba.conf entries for postgres readonly user"
  lineinfile:
    state: present
    regex: "^hostssl[ ]+all[ ]+{{ pgadmin4_oidc_dev_username }}"
    line: |-
      hostssl    all    {{ pgadmin4_oidc_dev_username }}    {{ shared_service_network }} md5
    path: /etc/postgresql/{{ default_postgres_version }}/main/pg_hba.conf

- name: "Updating dynamic pg_hba.conf entries for users/nodes/schemas"
  lineinfile:
    state: "{{ database_state }}"
    regex: "^hostssl[ ]+{{ item.name }}[ ]+{{ item.name }}"
    line: |-
      hostssl    {{ item.name }}    {{ item.name }}    {{ item.trusted_cidr_entry | default(shared_service_network) }} md5
    path: /etc/postgresql/{{ default_postgres_version }}/main/pg_hba.conf
  with_items: "{{ postgres_acls }}"

- name: "Checking roles exist" # noqa command-instead-of-shell
  shell: '/usr/bin/psql -Atc "SELECT count(rolname) FROM pg_roles where rolname=''{{ item.name }}''"'
  with_items: "{{ postgres_acls }}"
  register: role_check
  changed_when: "role_check.stdout == '0'"
  become_user: "{{ postgres_admin_user }}"
  become: true

- name: "Checking roles exist"
  debug:
    msg: "{{ role_check }}"
  when:
    - debug

- name: "Creating roles if necessary"
  shell: "/usr/bin/psql -c 'CREATE ROLE {{ item.item.name }} LOGIN;'"
  with_items: "{{ role_check.results }}"
  become_user: "{{ postgres_admin_user }}"
  become: true
  when:
    - database_state == 'present'
    - item.stdout == '0'
    - server_type == 'master'

- name: "Checking database exist"
  shell: '/usr/bin/psql -Atc "SELECT count(*) FROM pg_database WHERE datname = ''{{ item.name }}''"'
  with_items: "{{ postgres_acls }}"
  register: database_check
  changed_when: "database_check.stdout == '0'"
  become_user: "{{ postgres_admin_user }}"
  become: true

- name: "Check databases exist result"
  debug:
    msg: "{{ database_check }}"
  when:
    - debug

- name: "Creating Databases if necessary"
  shell: '/usr/bin/psql -c "CREATE DATABASE {{ item.item.name }};"'
  with_items: "{{ database_check.results }}"
  become_user: "{{ postgres_admin_user }}"
  become: true
  when:
    - database_state == 'present'
    - item.stdout == '0'
    - server_type == 'master'

- name: "Deleting Databases if necessary"
  shell: '/usr/bin/psql -c "DROP DATABASE {{ item.item.name }} WITH (FORCE);"'
  with_items: "{{ database_check.results }}"
  become_user: "{{ postgres_admin_user }}"
  become: true
  when:
    - database_state == 'absent'
    - item.stdout == '1'
    - server_type == 'master'

- name: "Deleting roles if necessary"
  shell: '/usr/bin/psql -c "DROP ROLE {{ item.item.name }};"'
  with_items: "{{ role_check.results }}"
  become_user: "{{ postgres_admin_user }}"
  become: true
  when:
    - database_state == 'absent'
    - item.stdout == '1'
    - server_type == 'master'

- name: "Changing password with scram-sha-256! for users and set password"
  shell: '/usr/bin/psql -c "set password_encryption = ''scram-sha-256'';ALTER ROLE {{ item.name }} WITH PASSWORD ''{{ item.password }}'';"'
  with_items: "{{ postgres_acls }}"
  become_user: "{{ postgres_admin_user }}"
  become: true
  when:
    - database_state == 'present'
    - server_type == 'master'

- name: "Changing owners for databases"
  shell: '/usr/bin/psql -c "ALTER DATABASE {{ item.name }} OWNER TO {{ item.name }};"'
  with_items: "{{ postgres_acls }}"
  become_user: "{{ postgres_admin_user }}"
  become: true
  when:
    - database_state == 'present'
    - server_type == 'master'

- name: "Create PostgreSQL readonly group"
  community.postgresql.postgresql_user:
    name: "postgres_readonly"
    role_attr_flags: NOLOGIN,NOSUPERUSER,NOCREATEDB,NOCREATEROLE,NOREPLICATION,INHERIT
    login_user: "{{ postgres_admin_user }}"
    state: present
  become: true
  become_user: "{{ postgres_admin_user }}"
  when:
    - server_type == 'master'

- name: "Get list of all databases"
  community.postgresql.postgresql_query:
    query: "SELECT datname FROM pg_database WHERE datname LIKE '{{ stage }}_%' AND datistemplate = false"
    login_user: "{{ postgres_admin_user }}"
    db: "{{ postgres_admin_user }}"
  register: database_list
  become: true
  become_user: "{{ postgres_admin_user }}"

- name: "Grant ALL privileges on public schema to application specific roles if necessary"
  community.postgresql.postgresql_privs:
    role: "{{ item.datname }}"
    type: schema
    priv: ALL
    objs: public
    login_user: "{{ postgres_admin_user }}"
    database: "{{ item.datname }}"
    state: present
  loop: "{{ database_list.query_result }}"
  become: true
  become_user: "{{ postgres_admin_user }}"
  when:
    - server_type == 'master'

- name: "Revoke CREATE privilege on public schema for group postgres_readonly"
  community.postgresql.postgresql_privs:
    role: "postgres_readonly"
    type: schema
    priv: CREATE
    objs: public
    login_user: "{{ postgres_admin_user }}"
    database: "{{ item.datname }}"
    state: absent
  loop: "{{ database_list.query_result }}"
  become: true
  become_user: "{{ postgres_admin_user }}"
  when:
    - server_type == 'master'

- name: "Grant USAGE privilege to postgres readonly group on all public schemas"
  community.postgresql.postgresql_privs:
    role: "postgres_readonly"
    type: schema
    priv: USAGE
    objs: public
    login_user: "{{ postgres_admin_user }}"
    database: "{{ item.datname }}"
    state: present
  loop: "{{ database_list.query_result }}"
  become: true
  become_user: "{{ postgres_admin_user }}"
  when:
    - server_type == 'master'

- name: "Grant SELECT on all tables in all databases to postgres readonly group"
  community.postgresql.postgresql_privs:
    role: "postgres_readonly"
    type: table
    privs: SELECT
    schema: public
    objs: ALL_IN_SCHEMA
    login_user: "{{ postgres_admin_user }}"
    database: "{{ item.datname }}"
    state: present
  loop: "{{ database_list.query_result }}"
  become: true
  become_user: "{{ postgres_admin_user }}"
  when:
    - server_type == 'master'

- name: "Create PostgreSQL user with password"
  community.postgresql.postgresql_user:
    name: "{{ pgadmin4_oidc_dev_username }}"
    password: "{{ pgadmin4_oidc_dev_password }}"
    role_attr_flags: LOGIN,NOSUPERUSER,NOCREATEDB,NOCREATEROLE,NOREPLICATION,INHERIT
    login_user: "{{ postgres_admin_user }}"
    state: present
  become: true
  become_user: "{{ postgres_admin_user }}"
  when:
    - server_type == 'master'

- name: "Add {{ pgadmin4_oidc_dev_username }} to group 'postgres_readonly'"
  community.postgresql.postgresql_user:
    name: "{{ pgadmin4_oidc_dev_username }}"
    role_attr_flags: NOSUPERUSER,NOCREATEDB,NOCREATEROLE,NOREPLICATION,INHERIT
    groups: "postgres_readonly"
    login_user: "{{ postgres_admin_user }}"
    state: present
  become: true
  become_user: "{{ postgres_admin_user }}"
  when:
    - server_type == 'master'

- name: "Reload Postgresql configuration" # noqa no-changed-when
  become: true
  become_user: postgres
  shell: '/usr/bin/psql -c "SELECT pg_reload_conf();"'
