Skip to content

Commit 83cd1d6

Browse files
fix(lint): annotate justified sudo() calls and fix ruff-format
Add nosemgrep annotations for legitimate sudo() usage in non-demo modules (sequence generation, SLA breach handling, mail templates, portal ticket creation, CEL rule counters). Fix redirect nosemgrep prefix and ruff-format in generate_cases.py.
1 parent cd896b3 commit 83cd1d6

File tree

7 files changed

+38
-19
lines changed

7 files changed

+38
-19
lines changed

spp_case_base/models/case.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ class Case(models.Model):
277277
@api.model
278278
def _get_next_case_number(self):
279279
"""Generate next case number."""
280+
# nosemgrep: semgrep.odoo-sudo-without-context -- sequence generation requires sudo
280281
sequence = self.env["ir.sequence"].sudo()
281282
# Try to get existing sequence, create if doesn't exist
282283
seq = sequence.search([("code", "=", "spp.case")], limit=1)

spp_case_cel/models/case_assignment_rule.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ def apply_assignment(self, case):
244244
vals,
245245
)
246246

247+
# nosemgrep: semgrep.odoo-sudo-without-context -- counter update needs sudo
247248
rule.sudo().write({"match_count": rule.match_count + 1})
248249
return True
249250

spp_case_cel/models/case_triage_rule.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ def apply_triage(self, case):
234234
if rule.add_vulnerability_ids:
235235
case.write({"vulnerability_ids": [(4, v.id) for v in rule.add_vulnerability_ids]})
236236

237+
# nosemgrep: semgrep.odoo-sudo-without-context -- counter update needs sudo
237238
rule.sudo().write({"match_count": rule.match_count + 1})
238239
return True
239240

spp_case_demo/models/generate_cases.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ def _process_case_journey(self, case, journey, fake):
218218
action_date = fields.Date.today() - timedelta(days=days_back)
219219

220220
if action == "create_plan":
221-
current_plan = Plan.sudo().create( {
221+
current_plan = Plan.sudo().create(
222+
{
222223
"case_id": case.id,
223224
"name": step.get("plan_name", f"Plan for {case.partner_id.name}"),
224225
"is_current": True,
@@ -229,7 +230,8 @@ def _process_case_journey(self, case, journey, fake):
229230
)
230231

231232
elif action == "add_intervention" and current_plan:
232-
Intervention.sudo().create( {
233+
Intervention.sudo().create(
234+
{
233235
"plan_id": current_plan.id,
234236
"name": step.get("intervention", "Intervention"),
235237
"description": fake.sentence(),
@@ -250,7 +252,8 @@ def _process_case_journey(self, case, journey, fake):
250252
intervention.sudo().write({"state": "completed"})
251253
elif action in ("home_visit", "office_visit", "final_visit"):
252254
visit_type = "home" if action != "office_visit" else "office"
253-
Visit.sudo().create( {
255+
Visit.sudo().create(
256+
{
254257
"case_id": case.id,
255258
"visit_type": visit_type,
256259
"purpose": step.get("purpose", "Check-in visit"),
@@ -260,7 +263,8 @@ def _process_case_journey(self, case, journey, fake):
260263
)
261264

262265
elif action == "progress_note":
263-
Note.sudo().create( {
266+
Note.sudo().create(
267+
{
264268
"case_id": case.id,
265269
"note_type": "progress",
266270
"content": step.get("note", fake.paragraph()),
@@ -269,7 +273,8 @@ def _process_case_journey(self, case, journey, fake):
269273
)
270274

271275
elif action in ("assessment", "emergency_assessment", "safety_assessment"):
272-
Note.sudo().create( {
276+
Note.sudo().create(
277+
{
273278
"case_id": case.id,
274279
"note_type": "assessment",
275280
"content": step.get(
@@ -282,7 +287,8 @@ def _process_case_journey(self, case, journey, fake):
282287
elif action == "add_referral":
283288
service = self._get_or_create_service(step.get("service", "External Service"))
284289
if service:
285-
Referral.sudo().create( {
290+
Referral.sudo().create(
291+
{
286292
"case_id": case.id,
287293
"service_id": service.id,
288294
"referral_reason": step.get("reason", "Service needed"),
@@ -299,13 +305,15 @@ def _process_case_journey(self, case, journey, fake):
299305
limit=1,
300306
)
301307
if closure_stage:
302-
case.sudo().write( {
308+
case.sudo().write(
309+
{
303310
"stage_id": closure_stage.id,
304311
"actual_closure_date": action_date,
305312
}
306313
)
307314
if current_plan:
308315
current_plan.sudo().write({"state": "completed"})
316+
309317
def _create_random_case(self, fake, beneficiaries):
310318
"""Create a random case with realistic data."""
311319
# Random date within range
@@ -370,7 +378,8 @@ def _add_random_plan(self, case, fake, intake_date):
370378
Plan = self.env["spp.case.intervention.plan"]
371379
Intervention = self.env["spp.case.intervention"]
372380

373-
plan = Plan.sudo().create( {
381+
plan = Plan.sudo().create(
382+
{
374383
"case_id": case.id,
375384
"name": f"Support Plan - {case.partner_id.name or 'Client'}",
376385
"is_current": True,
@@ -391,7 +400,8 @@ def _add_random_plan(self, case, fake, intake_date):
391400
]
392401

393402
for _i in range(random.randint(2, 4)):
394-
Intervention.sudo().create( {
403+
Intervention.sudo().create(
404+
{
395405
"plan_id": plan.id,
396406
"name": random.choice(intervention_names),
397407
"description": fake.sentence(),
@@ -406,7 +416,8 @@ def _add_random_visits(self, case, fake, intake_date):
406416

407417
for _i in range(random.randint(1, 3)):
408418
visit_date = intake_date + timedelta(days=random.randint(5, 60))
409-
Visit.sudo().create( {
419+
Visit.sudo().create(
420+
{
410421
"case_id": case.id,
411422
"visit_type": random.choice(["home", "office", "phone", "virtual"]),
412423
"purpose": fake.sentence(nb_words=5),
@@ -421,7 +432,8 @@ def _add_random_notes(self, case, fake, intake_date):
421432

422433
for _i in range(random.randint(1, 4)):
423434
note_date = intake_date + timedelta(days=random.randint(1, 60))
424-
Note.sudo().create( {
435+
Note.sudo().create(
436+
{
425437
"case_id": case.id,
426438
"note_type": random.choice(["progress", "assessment", "general", "supervision"]),
427439
"content": fake.paragraph(nb_sentences=random.randint(2, 5)),
@@ -440,7 +452,8 @@ def _close_random_case(self, case, fake, intake_date):
440452

441453
if closure_stage:
442454
closure_date = intake_date + timedelta(days=random.randint(30, 90))
443-
case.sudo().write( {
455+
case.sudo().write(
456+
{
444457
"stage_id": closure_stage.id,
445458
"actual_closure_date": closure_date,
446459
}
@@ -472,7 +485,8 @@ def _get_or_create_case_type(self, type_name):
472485
CaseType = self.env["spp.case.type"]
473486
case_type = CaseType.search([("name", "=", type_name)], limit=1)
474487
if not case_type:
475-
case_type = CaseType.sudo().create( {
488+
case_type = CaseType.sudo().create(
489+
{
476490
"name": type_name,
477491
"code": type_name.upper().replace(" ", "_")[:10],
478492
}
@@ -528,7 +542,8 @@ def _get_or_create_service(self, service_name):
528542
Service = self.env["spp.service"]
529543
service = Service.search([("name", "=", service_name)], limit=1)
530544
if not service:
531-
service = Service.sudo().create( {
545+
service = Service.sudo().create(
546+
{
532547
"name": service_name,
533548
"service_type": "external",
534549
}

spp_grm/controllers/grm_portal.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,10 @@ def portal_ticket_submit(self, **kw):
4747
"channel_id": request.env.ref("spp_grm.grm_ticket_channel_web").id,
4848
"partner_id": partner.id,
4949
}
50+
# nosemgrep: semgrep.odoo-sudo-without-context -- portal users need sudo to create tickets
5051
ticket = request.env["spp.grm.ticket"].sudo().create(vals)
5152

5253
ticket.send_ticket_confirmation_email(ticket)
5354

54-
# Redirect to the fixed internal tickets page; target is a constant
55-
# relative URL, so this is not an open redirect.
56-
return request.redirect(
57-
"/my/tickets"
58-
) # nosemgrep: odoo-unvalidated-redirect - Redirect target is fixed internal '/my/tickets' URL.
55+
# nosemgrep: semgrep.odoo-unvalidated-redirect -- fixed internal URL
56+
return request.redirect("/my/tickets")

spp_grm/models/grm_ticket.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ def _compute_sla_status(self):
538538
if ticket.sla_status == "breached" and old_status != "breached":
539539
# Use sudo() to call _on_sla_breach in a new environment context
540540
# to avoid triggering compute dependencies during the compute itself
541+
# nosemgrep: semgrep.odoo-sudo-without-context
541542
ticket.sudo()._on_sla_breach()
542543

543544
def _on_sla_breach(self):
@@ -677,6 +678,7 @@ def send_ticket_confirmation_email(self, ticket):
677678
"""Send the ticket submission confirmation email."""
678679
template = self.env.ref("spp_grm.ticket_submission_confirmation", raise_if_not_found=False)
679680
if template:
681+
# nosemgrep: semgrep.odoo-sudo-without-context -- mail templates require sudo
680682
template.sudo().send_mail(
681683
ticket.id,
682684
force_send=True,

spp_grm_cel/models/grm_routing_rule.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ def apply_routing(self, ticket):
259259
)
260260

261261
# Update match count
262+
# nosemgrep: semgrep.odoo-sudo-without-context -- counter update needs sudo
262263
rule.sudo().write({"match_count": rule.match_count + 1})
263264

264265
# Only apply the first matching rule

0 commit comments

Comments
 (0)