# LogicTest: local

query T colnames
SHOW ROLES
----
role_name
admin

statement error a role named admin already exists
CREATE ROLE admin

statement error a user named root already exists
CREATE ROLE root

statement error a user named root already exists
CREATE ROLE IF NOT EXISTS root

statement ok
CREATE ROLE IF NOT EXISTS admin

statement error pq: cannot drop user or role admin: grants still exist on .*
DROP ROLE admin

statement error pq: cannot drop user or role root: grants still exist on .*
DROP ROLE root

statement error pq: cannot drop users or roles admin, root: grants still exist on .*
DROP ROLE admin, root

statement ok
CREATE ROLE myrole

query T colnames
SHOW ROLES
----
role_name
admin
myrole

statement error a role named myrole already exists
CREATE ROLE myrole

statement ok
CREATE ROLE IF NOT EXISTS myrole

statement error a role named myrole already exists
CREATE USER myrole

statement error a role named myrole already exists
CREATE USER IF NOT EXISTS myrole

statement error pq: user myrole does not exist
DROP USER myrole

statement ok
DROP USER IF EXISTS myrole

statement error pq: cannot drop users or roles admin, myrole: grants still exist on .*
DROP ROLE admin, myrole

query T colnames
SHOW ROLES
----
role_name
admin
myrole

statement ok
DROP ROLE myrole

query T colnames
SHOW ROLES
----
role_name
admin

statement error pq: role myrole does not exist
DROP ROLE myrole

statement ok
DROP ROLE IF EXISTS myrole

statement ok
CREATE ROLE rolea

statement ok
CREATE ROLE roleb

statement ok
CREATE ROLE rolec

statement ok
CREATE ROLE roled

statement error pq: role rolee does not exist
DROP ROLE rolea, roleb, rolec, roled, rolee

statement ok
DROP ROLE IF EXISTS rolec, roled, rolee

statement ok
DROP ROLE rolea, roleb

query T colnames
SHOW ROLES
----
role_name
admin

statement ok
CREATE USER testuser2

statement ok
CREATE ROLE testrole

query TTB colnames
SHOW GRANTS ON ROLE
----
role_name  member  is_admin
admin      root    true

query TTT colnames,rowsort
SELECT * FROM information_schema.administrable_role_authorizations
----
grantee  role_name  is_grantable
root     admin      YES

query TTT colnames,rowsort
SELECT * FROM information_schema.applicable_roles
----
grantee  role_name  is_grantable
root     admin      YES

query T colnames,rowsort
SELECT * FROM information_schema.enabled_roles
----
role_name
admin
root

# Test that only roles are grantable.
statement error pq: role testuser does not exist
GRANT testuser TO testrole

statement error pq: user or role unknownuser does not exist
GRANT testrole TO unknownuser

statement error pq: role unknownrole does not exist
GRANT unknownrole TO testuser

# Test role "grant" and WITH ADMIN option.
user testuser

statement error pq: testuser is not a superuser or role admin for role testrole
GRANT testrole TO testuser2

user root

statement ok
GRANT testrole TO testuser

query TTB colnames
SELECT * FROM system.role_members
----
role      member    isAdmin
admin     root      true
testrole  testuser  false

query TTB colnames
SHOW GRANTS ON ROLE
----
role_name  member    is_admin
admin      root      true
testrole   testuser  false

user testuser

statement error pq: testuser is not a superuser or role admin for role testrole
GRANT testrole TO testuser2

user root

statement ok
GRANT testrole TO testuser WITH ADMIN OPTION

query TTB colnames
SELECT * FROM system.role_members
----
role      member    isAdmin
admin     root      true
testrole  testuser  true

user testuser

statement ok
GRANT testrole TO testuser2 WITH ADMIN OPTION

query TTT colnames,rowsort
SELECT * FROM information_schema.administrable_role_authorizations
----
grantee   role_name  is_grantable
testuser  testrole   YES

query TTT colnames,rowsort
SELECT * FROM information_schema.applicable_roles
----
grantee   role_name  is_grantable
testuser  testrole   YES

query T colnames,rowsort
SELECT * FROM information_schema.enabled_roles
----
role_name
testrole
testuser

user root

statement ok
GRANT admin TO testuser

# Dropping users/roles deletes all their memberships.
query TTB colnames
SELECT * FROM system.role_members
----
role      member     isAdmin
admin     root       true
admin     testuser   false
testrole  testuser   true
testrole  testuser2  true

query TTB colnames
SHOW GRANTS ON ROLE
----
role_name  member     is_admin
admin      root       true
admin      testuser   false
testrole   testuser   true
testrole   testuser2  true

query TTB colnames
SHOW GRANTS ON ROLE admin
----
role_name  member    is_admin
admin      root      true
admin      testuser  false

query TTB colnames
SHOW GRANTS ON ROLE FOR testuser
----
role_name  member    is_admin
admin      testuser  false
testrole   testuser  true

query TTB colnames
SHOW GRANTS ON ROLE testrole FOR testuser2
----
role_name  member     is_admin
testrole   testuser2  true

query TTB colnames
SHOW GRANTS ON ROLE foo,testrole
----
role_name  member     is_admin
testrole   testuser   true
testrole   testuser2  true

query TTB colnames
SHOW GRANTS ON ROLE FOR testuser, testuser2
----
role_name  member     is_admin
admin      testuser   false
testrole   testuser   true
testrole   testuser2  true

query TTB colnames
SHOW GRANTS ON ROLE admin, testrole FOR root, testuser2
----
role_name  member     is_admin
admin      root       true
testrole   testuser2  true

statement ok
DROP USER testuser

statement ok
CREATE USER testuser

query TTB colnames
SELECT * FROM system.role_members
----
role      member     isAdmin
admin     root       true
testrole  testuser2  true

statement ok
DROP ROLE testrole

query TTB colnames
SELECT * FROM system.role_members
----
role      member     isAdmin
admin     root       true

# Test cycle detection.
statement error pq: admin cannot be a member of itself
GRANT admin TO admin

statement ok
CREATE ROLE rolea

statement ok
CREATE ROLE roleb

statement ok
CREATE ROLE rolec

statement ok
CREATE ROLE roled

statement ok
GRANT rolea TO roleb

statement error pq: making rolea a member of roleb would create a cycle
GRANT roleb TO rolea

statement ok
GRANT roleb TO rolec

statement ok
GRANT rolec TO roled

statement error pq: rolea cannot be a member of itself
GRANT rolea TO rolea

statement error pq: making rolea a member of roleb would create a cycle
GRANT roleb TO rolea

statement error pq: making rolea a member of rolec would create a cycle
GRANT rolec TO rolea

statement error pq: making rolea a member of roled would create a cycle
GRANT roled TO rolea

statement ok
CREATE ROLE rolee

# Test inherited ADMIN OPTION.
statement ok
GRANT roled TO testuser

statement ok
GRANT rolea TO roleb WITH ADMIN OPTION

user testuser

query TTT colnames,rowsort
SELECT * FROM information_schema.administrable_role_authorizations
----
grantee   role_name  is_grantable
testuser  rolea      YES

query TTT colnames,rowsort
SELECT * FROM information_schema.applicable_roles
----
grantee   role_name  is_grantable
testuser  roled      NO
testuser  rolec      NO
testuser  roleb      NO
testuser  rolea      YES

query T colnames,rowsort
SELECT * FROM information_schema.enabled_roles
----
role_name
rolea
roleb
rolec
roled
testuser

statement error pq: testuser is not a superuser or role admin for role roled
GRANT roled TO rolee

statement error pq: testuser is not a superuser or role admin for role rolec
GRANT rolec TO rolee

statement error pq: testuser is not a superuser or role admin for role roleb
GRANT roleb TO rolee

statement ok
GRANT rolea TO rolee

query TTT colnames,rowsort
SELECT * FROM information_schema.administrable_role_authorizations
----
grantee   role_name  is_grantable
testuser  rolea      YES

query TTT colnames,rowsort
SELECT * FROM information_schema.applicable_roles
----
grantee   role_name  is_grantable
testuser  rolec      NO
testuser  roleb      NO
testuser  rolea      YES
testuser  roled      NO

query T colnames,rowsort
SELECT * FROM information_schema.enabled_roles
----
role_name
rolea
roleb
rolec
roled
testuser

user root

query TTB colnames
SELECT * FROM system.role_members
----
role   member    isAdmin
admin  root      true
rolea  roleb     true
rolea  rolee     false
roleb  rolec     false
rolec  roled     false
roled  testuser  false

statement ok
DROP ROLE rolea

statement ok
DROP ROLE rolec

query TTB colnames
SELECT * FROM system.role_members
----
role   member    isAdmin
admin  root      true
roled  testuser false

query T
SHOW ROLES
----
admin
roleb
roled
rolee

statement ok
DROP ROLE roleb

statement ok
DROP ROLE roled

statement ok
DROP ROLE rolee

statement error pq: user root cannot be removed from role admin or lose the ADMIN OPTION
REVOKE admin FROM root

statement error pq: user root cannot be removed from role admin or lose the ADMIN OPTION
REVOKE ADMIN OPTION FOR admin FROM root

statement error pq: user or role unknownuser does not exist
REVOKE ADMIN OPTION FOR admin FROM unknownuser

statement error pq: role unknownrole does not exist
REVOKE ADMIN OPTION FOR unknownrole FROM root

statement ok
CREATE ROLE rolea

statement ok
CREATE ROLE roleb

statement ok
GRANT rolea,roleb TO testuser WITH ADMIN OPTION

query TTB colnames
SELECT * FROM system.role_members
----
role   member    isAdmin
admin  root      true
rolea  testuser  true
roleb  testuser  true

user testuser

statement ok
GRANT rolea,roleb TO root WITH ADMIN OPTION

user root

query TTB colnames
SELECT * FROM system.role_members
----
role   member    isAdmin
admin  root      true
rolea  root      true
rolea  testuser  true
roleb  root      true
roleb  testuser  true

query TTT colnames,rowsort
SELECT * FROM information_schema.administrable_role_authorizations
----
grantee  role_name  is_grantable
root     admin      YES
root     rolea      YES
root     roleb      YES

query TTT colnames,rowsort
SELECT * FROM information_schema.applicable_roles
----
grantee  role_name  is_grantable
root     admin      YES
root     rolea      YES
root     roleb      YES

query T colnames,rowsort
SELECT * FROM information_schema.enabled_roles
----
role_name
admin
rolea
roleb
root

user testuser

query TTT colnames,rowsort
SELECT * FROM information_schema.administrable_role_authorizations
----
grantee   role_name  is_grantable
testuser  rolea      YES
testuser  roleb      YES

query TTT colnames,rowsort
SELECT * FROM information_schema.applicable_roles
----
grantee   role_name  is_grantable
testuser  rolea      YES
testuser  roleb      YES

query T colnames,rowsort
SELECT * FROM information_schema.enabled_roles
----
role_name
rolea
roleb
testuser

statement ok
REVOKE ADMIN OPTION FOR rolea FROM testuser

statement error pq: testuser is not a superuser or role admin for role rolea
REVOKE ADMIN OPTION FOR rolea FROM root

statement ok
REVOKE roleb FROM root

user root

query TTB colnames
SELECT * FROM system.role_members
----
role   member    isAdmin
admin  root      true
rolea  root      true
rolea  testuser  false
roleb  testuser  true

statement ok
REVOKE rolea, roleb FROM testuser, root

query TTB colnames
SELECT * FROM system.role_members
----
role   member    isAdmin
admin  root      true

# Test privilege checks.

statement ok
CREATE DATABASE db1

user testuser

statement error only superusers are allowed to CREATE DATABASE
CREATE DATABASE db2

statement error user testuser does not have DROP privilege on database db1
DROP DATABASE db1

statement error testuser is not a superuser or role admin for role admin
GRANT admin TO testuser

user root

statement ok
CREATE ROLE newgroup

statement ok
GRANT newgroup TO testuser

statement ok
GRANT admin TO newgroup

user testuser

query TTB colnames
SELECT * FROM system.role_members
----
role      member    isAdmin
admin     newgroup  false
admin     root      true
newgroup  testuser  false

statement ok
CREATE DATABASE db2

statement ok
DROP DATABASE db1

# Revoke admin privileges. 'newgroup' does not have any privileges.
statement ok
REVOKE admin FROM newgroup

statement error user testuser does not have SELECT privilege on relation role_members
SELECT * FROM system.role_members

statement error user testuser does not have CREATE privilege on database db2
CREATE TABLE db2.foo (k int);

user root

query TTB colnames
SELECT * FROM system.role_members
----
role      member    isAdmin
admin     root      true
newgroup  testuser  false

statement ok
GRANT ALL ON DATABASE db2 TO newgroup

user testuser

query TTTT colnames
SHOW GRANTS ON DATABASE db2
----
database_name  schema_name         grantee   privilege_type
db2            crdb_internal       admin     ALL
db2            crdb_internal       newgroup  ALL
db2            crdb_internal       root      ALL
db2            information_schema  admin     ALL
db2            information_schema  newgroup  ALL
db2            information_schema  root      ALL
db2            pg_catalog          admin     ALL
db2            pg_catalog          newgroup  ALL
db2            pg_catalog          root      ALL
db2            public              admin     ALL
db2            public              newgroup  ALL
db2            public              root      ALL

statement ok
CREATE TABLE db2.foo (k int);

statement ok
INSERT INTO db2.foo VALUES (1),(2),(3);

statement ok
SELECT * FROM db2.foo

# We may be in the 'newgroup', but we don't have the admin option.
statement error testuser is not a superuser or role admin for role newgroup
GRANT newgroup TO testuser2

statement error testuser is not a superuser or role admin for role newgroup
REVOKE newgroup FROM testuser

statement error testuser is not a superuser or role admin for role newgroup
GRANT newgroup TO testuser WITH ADMIN OPTION

user root

# The user does not have direct privileges on anything, so we can drop it.
statement ok
DROP USER testuser

query TTB colnames
SELECT * FROM system.role_members
----
role      member    isAdmin
admin     root      true

statement error cannot drop user or role newgroup: grants still exist on db2, db2.public.foo
DROP ROLE newgroup

statement ok
REVOKE ALL ON db2.* FROM newgroup

statement ok
REVOKE ALL ON DATABASE db2 FROM newgroup

statement ok
DROP ROLE newgroup

# Test the "public" pseudo-role.

statement error role name "public" is reserved
CREATE USER public

statement error role name "public" is reserved
CREATE ROLE public

statement error cannot drop user or role public: grants still exist on system.public.comments
DROP USER public

statement error cannot drop user or role public: grants still exist on system.public.comments
DROP ROLE public

statement error role public does not exist
GRANT public TO testuser

statement error user or role public does not exist
GRANT admin TO public

statement error role public does not exist
REVOKE public FROM testuser

statement error user or role public does not exist
REVOKE admin FROM public
