Repository navigation
Add ReadOnlyDatabaseRole model - #260
Draft
kiwitcms-bot wants to merge 1 commit into
Draft
kiwitcms-bot wants to merge 1 commit into
kiwitcms-bot wants to merge 1 commit into
Conversation
Keeps track of a read-only DB role for an existing tenant schema. The role has SELECT privileges on all tables in the tenant schema and is valid for as long as the customer's subscription renews. The actual DB role is created via raw SQL where identifiers and values are escaped via psycopg's Identifier/Literal wrappers to prevent SQL injection. All statements are sent in a single cursor.execute() call and the model row + DB role are created inside one transaction.atomic() block so a failure leaves nothing behind.
atodorov
marked this pull request as draft
October 6, 2026 16:37
kiwitcms-bot
force-pushed
the
read-only-database-role-model
branch
from
October 6, 2026 16:38
37782c8 to
7a681ff
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a new
ReadOnlyDatabaseRolemodel (standalone; the integration that creates the role for tenants comes in a follow-up PR).Fields:
name,created_at,valid_until,password.ReadOnlyDatabaseRole.create_for_schema(schema_name, valid_until):name=ro_for_<schema_name>(READ_ONLY_ROLE_PREFIXis a class attribute)password= random UUIDcreated_at= nowvalid_until= passed in by the callerIt stores the model record and creates an actual PostgreSQL role via raw SQL, escaping identifiers and values with psycopg's
sql.Identifier/sql.Literal(no string interpolation), so user supplied values can't be used for SQL injection.The role is created with
LOGIN+ENCRYPTED PASSWORD+VALID UNTIL, getsUSAGEon the tenant schema,SELECTon all tables in it, andALTER DEFAULT PRIVILEGES ... GRANT SELECT ON TABLESso tables created later are covered too. No write privileges are granted.All statements are sent in a single
cursor.execute()call (PostgreSQL runs a multi-statement simple query in one implicit transaction), and the model row + DB role are created inside onetransaction.atomic()block, so a failure leaves neither a stale row nor a partially-granted role.update_valid_until()updates the model and the DB role in one transaction.Tests
tests/test_read_only_database_role.py: the record is stored, the actual DB role exists withrolvaliduntil, andhas_table_privilege()reportsSELECTbut notINSERT/UPDATE/DELETE; plusupdate_valid_until().black,flake8andpylint(10.00/10) are clean;makemigrations --checkreports no pending changes.