55from django .contrib .auth .models import Group , Permission
66from django .core .management .base import BaseCommand
77
8+ # All custom Conference permissions for granting to the organizer group.
9+ _ALL_CONFERENCE_PERMS = [
10+ "view_dashboard" ,
11+ "manage_conference_settings" ,
12+ "view_program" ,
13+ "change_program" ,
14+ "view_registration" ,
15+ "change_registration" ,
16+ "view_commerce" ,
17+ "change_commerce" ,
18+ "view_badges" ,
19+ "change_badges" ,
20+ "view_sponsors" ,
21+ "change_sponsors" ,
22+ "view_bulk_purchases" ,
23+ "change_bulk_purchases" ,
24+ "view_finance" ,
25+ "change_finance" ,
26+ "view_reports" ,
27+ "export_reports" ,
28+ "view_checkin" ,
29+ "use_terminal" ,
30+ "view_overrides" ,
31+ "change_overrides" ,
32+ ]
33+
34+ _ALL_VIEW_CONFERENCE_PERMS = [
35+ p for p in _ALL_CONFERENCE_PERMS if (p .startswith ("view_" ) or p == "export_reports" ) and p != "view_checkin"
36+ ]
37+
838# Mapping of group name -> list of (app_label, codename) permissions.
9- # Uses the app labels defined in each app's AppConfig (program_conference, etc.).
1039_GROUP_PERMISSIONS : dict [str , list [tuple [str , str ]]] = {
11- "Program: Conference Organizers " : [
12- # Full access to conference and section management
40+ "Conference Organizer " : [
41+ # Django CRUD on Conference model
1342 ("program_conference" , "add_conference" ),
1443 ("program_conference" , "change_conference" ),
1544 ("program_conference" , "delete_conference" ),
1645 ("program_conference" , "view_conference" ),
17- ("program_conference" , "add_section" ),
18- ("program_conference" , "change_section" ),
19- ("program_conference" , "delete_section" ),
20- ("program_conference" , "view_section" ),
21- # Full access to ticket types and add-ons
22- ("program_registration" , "add_tickettype" ),
23- ("program_registration" , "change_tickettype" ),
24- ("program_registration" , "delete_tickettype" ),
25- ("program_registration" , "view_tickettype" ),
26- ("program_registration" , "add_addon" ),
27- ("program_registration" , "change_addon" ),
28- ("program_registration" , "delete_addon" ),
29- ("program_registration" , "view_addon" ),
30- # Voucher management
31- ("program_registration" , "add_voucher" ),
32- ("program_registration" , "change_voucher" ),
33- ("program_registration" , "delete_voucher" ),
34- ("program_registration" , "view_voucher" ),
35- # View orders and carts (read-only for operational awareness)
36- ("program_registration" , "view_order" ),
37- ("program_registration" , "view_orderlineitem" ),
38- ("program_registration" , "view_cart" ),
39- ("program_registration" , "view_cartitem" ),
40- ("program_registration" , "view_payment" ),
41- ("program_registration" , "view_credit" ),
42- # Activity signup management
46+ # All custom Conference permissions
47+ * [("program_conference" , p ) for p in _ALL_CONFERENCE_PERMS ],
48+ # Programs app
49+ ("program_programs" , "view_activity" ),
4350 ("program_programs" , "manage_activity" ),
51+ ("program_programs" , "view_travel_grant" ),
52+ ("program_programs" , "review_travel_grant" ),
53+ ("program_programs" , "disburse_travel_grant" ),
54+ ("program_programs" , "review_receipt" ),
4455 ],
45- "Program: Registration & Ticket Support" : [
46- # View conference context
56+ "Program Committee" : [
4757 ("program_conference" , "view_conference" ),
48- ("program_conference" , "view_section" ),
49- # View and manage tickets/add-ons
50- ("program_registration" , "view_tickettype" ),
51- ("program_registration" , "change_tickettype" ),
52- ("program_registration" , "view_addon" ),
53- ("program_registration" , "change_addon" ),
54- # Voucher management (issue comps, apply discounts)
55- ("program_registration" , "add_voucher" ),
56- ("program_registration" , "change_voucher" ),
57- ("program_registration" , "view_voucher" ),
58- # Cart and order support
59- ("program_registration" , "view_cart" ),
60- ("program_registration" , "view_cartitem" ),
61- ("program_registration" , "view_order" ),
62- ("program_registration" , "change_order" ),
63- ("program_registration" , "view_orderlineitem" ),
64- ("program_registration" , "view_payment" ),
65- ("program_registration" , "view_credit" ),
58+ ("program_conference" , "view_dashboard" ),
59+ ("program_conference" , "view_program" ),
60+ ("program_conference" , "change_program" ),
61+ ("program_conference" , "view_overrides" ),
62+ ("program_conference" , "change_overrides" ),
6663 ],
67- "Program: Finance & Accounting" : [
68- # Read-only conference context
64+ "Registration Manager" : [
6965 ("program_conference" , "view_conference" ),
70- # Full access to financial records
71- ("program_registration" , "view_order" ),
72- ("program_registration" , "change_order" ),
73- ("program_registration" , "view_orderlineitem" ),
74- ("program_registration" , "view_payment" ),
75- ("program_registration" , "add_payment" ),
76- ("program_registration" , "change_payment" ),
77- ("program_registration" , "view_credit" ),
78- ("program_registration" , "add_credit" ),
79- ("program_registration" , "change_credit" ),
80- # View vouchers for audit trail
81- ("program_registration" , "view_voucher" ),
82- # View tickets for revenue reporting
83- ("program_registration" , "view_tickettype" ),
84- ("program_registration" , "view_addon" ),
66+ ("program_conference" , "view_dashboard" ),
67+ ("program_conference" , "view_registration" ),
68+ ("program_conference" , "change_registration" ),
69+ ("program_conference" , "view_commerce" ),
70+ ("program_conference" , "change_commerce" ),
71+ ("program_conference" , "view_badges" ),
72+ ("program_conference" , "change_badges" ),
73+ ("program_conference" , "view_checkin" ),
74+ ("program_conference" , "use_terminal" ),
75+ ("program_conference" , "view_bulk_purchases" ),
76+ ("program_conference" , "change_bulk_purchases" ),
8577 ],
86- "Program: Activity Organizers " : [
78+ "Finance Team " : [
8779 ("program_conference" , "view_conference" ),
88- ("program_programs" , "manage_activity" ),
80+ ("program_conference" , "view_dashboard" ),
81+ ("program_conference" , "view_finance" ),
82+ ("program_conference" , "change_finance" ),
83+ ("program_conference" , "view_reports" ),
84+ ("program_conference" , "export_reports" ),
85+ ("program_conference" , "view_registration" ),
86+ ("program_conference" , "view_commerce" ),
87+ ],
88+ "Travel Grant Reviewer" : [
89+ ("program_conference" , "view_conference" ),
90+ ("program_conference" , "view_dashboard" ),
91+ ("program_programs" , "view_travel_grant" ),
92+ ("program_programs" , "review_travel_grant" ),
93+ ("program_programs" , "review_receipt" ),
94+ ],
95+ "Sponsor Manager" : [
96+ ("program_conference" , "view_conference" ),
97+ ("program_conference" , "view_dashboard" ),
98+ ("program_conference" , "view_sponsors" ),
99+ ("program_conference" , "change_sponsors" ),
100+ ("program_conference" , "view_bulk_purchases" ),
101+ ("program_conference" , "change_bulk_purchases" ),
102+ ],
103+ "Check-in Staff" : [
104+ ("program_conference" , "view_conference" ),
105+ ("program_conference" , "view_dashboard" ),
106+ ("program_conference" , "view_checkin" ),
107+ ],
108+ "Activity Organizer" : [
109+ ("program_conference" , "view_conference" ),
110+ ("program_conference" , "view_dashboard" ),
89111 ("program_programs" , "view_activity" ),
90- ("program_programs" , "view_activitysignup " ),
112+ ("program_programs" , "manage_activity " ),
91113 ],
92- "Program: Reports" : [
93- # Read-only access for report dashboards
114+ "Reports Viewer" : [
94115 ("program_conference" , "view_conference" ),
95- ("program_registration" , "view_tickettype" ),
96- ("program_registration" , "view_addon" ),
97- ("program_registration" , "view_voucher" ),
98- ("program_registration" , "view_order" ),
99- ("program_registration" , "view_orderlineitem" ),
100- ("program_registration" , "view_payment" ),
101- ("program_registration" , "view_credit" ),
116+ ("program_conference" , "view_dashboard" ),
117+ ("program_conference" , "view_reports" ),
102118 ],
103- "Program: Read-Only Staff" : [
119+ "Read-Only Staff" : [
104120 ("program_conference" , "view_conference" ),
105- ("program_conference" , "view_section" ),
106- ("program_registration" , "view_tickettype" ),
107- ("program_registration" , "view_addon" ),
108- ("program_registration" , "view_voucher" ),
109- ("program_registration" , "view_cart" ),
110- ("program_registration" , "view_cartitem" ),
111- ("program_registration" , "view_order" ),
112- ("program_registration" , "view_orderlineitem" ),
113- ("program_registration" , "view_payment" ),
114- ("program_registration" , "view_credit" ),
121+ * [("program_conference" , p ) for p in _ALL_VIEW_CONFERENCE_PERMS ],
122+ ("program_programs" , "view_activity" ),
123+ ("program_programs" , "view_travel_grant" ),
115124 ],
116125}
117126
118127
119128class Command (BaseCommand ):
120129 """Create default permission groups for conference staff roles.
121130
122- Creates six groups with appropriate permissions:
131+ Creates ten groups with granular permissions:
123132
124- * **Conference Organizers** -- full conference, ticket, voucher, and activity management
125- * **Registration & Ticket Support** -- ticket ops, voucher issuing, order support
126- * **Finance & Accounting** -- orders, payments, credits, and revenue visibility
127- * **Reports** -- read-only access to report dashboards and underlying data
128- * **Activity Organizers** -- per-activity signup management
129- * **Read-Only Staff** -- view-only access to all registration models
133+ * **Conference Organizer** -- full access to all conference management
134+ * **Program Committee** -- program content and Pretalx overrides
135+ * **Registration Manager** -- attendees, orders, commerce, badges, check-in
136+ * **Finance Team** -- financial dashboard, expenses, reports, read-only commerce
137+ * **Travel Grant Reviewer** -- travel grant review and receipt approval
138+ * **Sponsor Manager** -- sponsor and bulk purchase management
139+ * **Check-in Staff** -- check-in dashboard access only
140+ * **Activity Organizer** -- activity and signup management
141+ * **Reports Viewer** -- read-only access to reports dashboard
142+ * **Read-Only Staff** -- view-only access to all sections
130143
131144 Safe to run multiple times; existing groups are updated with the defined
132145 permission set.
@@ -147,12 +160,19 @@ def handle(self, *args: Any, **options: Any) -> None:
147160 group , created = Group .objects .get_or_create (name = group_name )
148161 verb = "Created" if created else "Updated"
149162
163+ perm_set = set (perm_specs )
164+ app_labels = {app for app , _ in perm_set }
150165 permissions = Permission .objects .filter (
151- content_type__app_label__in = { app for app , _ in perm_specs } ,
166+ content_type__app_label__in = app_labels ,
152167 )
153- matched = [p for p in permissions if (p .content_type .app_label , p .codename ) in perm_specs ]
168+ matched = [p for p in permissions if (p .content_type .app_label , p .codename ) in perm_set ]
169+ missing = perm_set - {(p .content_type .app_label , p .codename ) for p in matched }
154170 group .permissions .set (matched )
155171
172+ if missing and verbosity > 0 :
173+ labels = ", " .join (f"{ app } .{ code } " for app , code in sorted (missing ))
174+ self .stdout .write (self .style .WARNING (f" Warning: { group_name } missing permissions: { labels } " ))
175+
156176 if verbosity > 0 :
157177 self .stdout .write (self .style .SUCCESS (f" { verb } group '{ group_name } ' with { len (matched )} permissions" ))
158178
0 commit comments