11import logging
2+ import re
23from collections import defaultdict
34
45from django .apps import apps as global_apps
@@ -42,6 +43,30 @@ def create_dab_permissions(app_config, verbosity=2, interactive=True, using=DEFA
4243 sync_DAB_permissions (verbosity = verbosity , using = using , apps = global_apps )
4344
4445
46+ def is_safe_identifier (name : str ) -> bool :
47+ """Returns True or False, name is a valid identifier in postgres, just for safety"""
48+ return re .match (r'^[A-Za-z_][A-Za-z0-9_]*$' , name ) is not None
49+
50+
51+ def reset_ct_sequence (ct_cls ):
52+ table = ct_cls ._meta .db_table
53+ pk_column = ct_cls ._meta .pk .column
54+ # This case should never be hit, but for database safety we have this
55+ if not is_safe_identifier (table ) or not is_safe_identifier (pk_column ):
56+ raise ValueError (f"Unsafe identifier: { table } .{ pk_column } " )
57+
58+ logger .info ('Updating the serial sequence of DABContentType model' )
59+ with connection .cursor () as cursor :
60+ cursor .execute (
61+ f"""
62+ SELECT setval(
63+ pg_get_serial_sequence(%s, %s),
64+ (SELECT MAX({ pk_column } ) FROM { table } )
65+ )""" ,
66+ [table , pk_column ],
67+ )
68+
69+
4570def sync_DAB_permissions (verbosity = 2 , using = DEFAULT_DB_ALIAS , apps = global_apps ):
4671 """Idepotent method to set database types and permissions for DAB RBAC
4772
@@ -51,7 +76,7 @@ def sync_DAB_permissions(verbosity=2, using=DEFAULT_DB_ALIAS, apps=global_apps):
5176 DABContentType = apps .get_model ("dab_rbac" , "DABContentType" )
5277 Permission = apps .get_model ("dab_rbac" , "DABPermission" )
5378
54- create_DAB_contenttypes (verbosity = verbosity , using = using , apps = apps )
79+ new_cts = create_DAB_contenttypes (verbosity = verbosity , using = using , apps = apps )
5580
5681 # This will hold the permissions we're looking for as (content_type, (codename, name))
5782 searched_perms = []
@@ -106,15 +131,5 @@ def sync_DAB_permissions(verbosity=2, using=DEFAULT_DB_ALIAS, apps=global_apps):
106131
107132 # Reset the sequence to avoid PK collision later
108133 if connection .vendor == 'postgresql' :
109- table = DABContentType ._meta .db_table
110- pk_column = DABContentType ._meta .pk .column
111- with connection .cursor () as cursor :
112- cursor .execute (
113- f"""
114- SELECT setval(
115- pg_get_serial_sequence(%s, %s),
116- (SELECT MAX({ pk_column } ) FROM { table } )
117- )
118- """ ,
119- [table , pk_column ],
120- )
134+ if new_cts :
135+ reset_ct_sequence (DABContentType )
0 commit comments