Создадим роль:
postgres=# CREATE ROLE alice LOGIN CREATEROLE;
CREATE ROLE
В этом модуле приглашение будет показывать имя роли, от которой выполняется команда.
Алиса имеет возможность подключения (атрибут LOGIN) и создания других ролей (CREATEROLE).
Проверим это:
postgres=# \c - alice
You are now connected to database "access_roles" as user "alice".
alice=> CREATE ROLE bob LOGIN;
CREATE ROLE
Действительно, получилось и подключиться, и создать другого пользователя, Боба.
А вот Боб не сможет создать другую роль:
postgres$ psql -U bob -d access_roles
bob=> CREATE ROLE charlie LOGIN;
ERROR: permission denied to create role
Посмотреть роли, имеющиеся в кластере, можно так:
alice=> \du
List of roles Role name | Attributes | Member of -----------+------------------------------------------------------------+----------- alice | Create role | {} bob | | {} postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
Или в системном каталоге:
alice=> SELECT usename FROM pg_user;
usename ---------- postgres alice bob (3 rows)
Существующие роли можно изменять. Например, Алиса может отобрать у Боба право входа:
alice=> ALTER ROLE bob NOLOGIN;
ALTER ROLE
А у себя самой Алиса отберет CREATEROLE:
alice=> ALTER ROLE alice NOCREATEROLE;
ALTER ROLE
Такие пары, как LOGIN-NOLOGIN или CREATEROLE-NOCREATEROLE, есть и у других атрибутов.
Теперь Боб не сможет подключиться:
bob=> \c - bob
\connect: FATAL: role "bob" is not permitted to log in
А Алиса теперь не может ни создавать новые роли, ни изменять атрибуты существующих:
alice=> ALTER ROLE bob LOGIN;
ERROR: permission denied
Чтобы снова наделить Алису супервозможностями, включим ее в суперпользовательскую роль postgres:
alice=> \c - postgres
You are now connected to database "access_roles" as user "postgres".
postgres=# GRANT postgres TO alice;
GRANT ROLE
postgres=# \du
List of roles Role name | Attributes | Member of -----------+------------------------------------------------------------+------------ alice | | {postgres} bob | Cannot login | {} postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
А чтобы Алиса не злоупотребляла полномочиями, сделаем так, чтобы все ее команды попадали в журнал сообщений:
postgres=# ALTER ROLE alice SET log_min_duration_statement=0;
ALTER ROLE
Это еще один вариант установки конфигурационных параметров - он срабатывает при подключении пользователя к серверу.
Можно ограничить действие и конкретной базой данных:
postgres=# ALTER ROLE alice RESET log_min_duration_statement;
ALTER ROLE
postgres=# ALTER ROLE alice IN DATABASE postgres SET log_min_duration_statement=0;
ALTER ROLE
Алиса не получает возможности групповой роли автоматически. Она может ими воспользоваться, только если переключится на эту роль:
postgres=# \c - alice
You are now connected to database "access_roles" as user "alice".
alice=> SET ROLE postgres;
SET
alice=> ALTER ROLE bob LOGIN;
ALTER ROLE
Это напоминает команду su в ОС Unix.
Чтобы понять, кем является пользователь на самом деле, и на какую роль он переключился, есть функции:
alice=> SELECT session_user, current_user;
session_user | current_user --------------+-------------- alice | postgres (1 row)
Вернемся к прежней роли:
alice=> RESET ROLE;
RESET
alice=> SELECT session_user, current_user;
session_user | current_user --------------+-------------- alice | alice (1 row)
Когда Алиса создает какой-либо объект в БД, она становится его владельцем.
alice=> CREATE TABLE test(id integer);
CREATE TABLE
Как в этом убедиться? Владелец указан в столбце owner:
alice=> \dt test
List of relations Schema | Name | Type | Owner --------+------+-------+------- public | test | table | alice (1 row)
Удалить роль можно, если нет объектов, которыми она владеет.
alice=> \c - postgres
You are now connected to database "access_roles" as user "postgres".
postgres=# DROP ROLE alice;
ERROR: role "alice" cannot be dropped because some objects depend on it DETAIL: owner of table test
Чтобы удалить Алису, можно передать ее объекты другой роли:
postgres=# REASSIGN OWNED BY alice TO bob;
REASSIGN OWNED
postgres=# \dt test
List of relations Schema | Name | Type | Owner --------+------+-------+------- public | test | table | bob (1 row)
postgres=# DROP ROLE alice;
DROP ROLE
Другой вариант - удалить объекты.
postgres=# DROP OWNED BY bob;
DROP OWNED
postgres=# DROP ROLE bob;
DROP ROLE
Надо только иметь в виду, что роль может владеть объектами в разных базах данных.
Конец демонстрации.