Skip to content

Conversation

@Simrayz
Copy link
Contributor

@Simrayz Simrayz commented Oct 13, 2025

Scope and purpose

When adding support for setting shared dashboards as a user default (#3572), I discovered that the creation of a default dashboard is handled by a SQL trigger, i.e.

CREATE OR REPLACE FUNCTION create_new_dashboard() RETURNS trigger AS $$
BEGIN
WITH inserted AS (
INSERT INTO account_dashboard (account_id, is_default, num_columns)
VALUES (NEW.id, TRUE, 3) RETURNING id
)
INSERT INTO account_navlet (account, navlet, displayorder, col, preferences, dashboard_id)
SELECT NEW.id, navlet, displayorder, col, preferences, (SELECT id from inserted)
FROM account_navlet WHERE account=0;
RETURN NULL;
END
$$ LANGUAGE plpgsql;

This is not optimal for two reasons:

  1. When we want to update the logic for what happens when a user is created, we have to also update the sql trigger.
  2. It is very difficult to reason about what happens in the system. It took a very long time to figure out that this trigger is where everything happens.

This PR proposes to replace the SQL trigger with a django post_save signal on the account model. This moves the logic from a static SQL trigger that has to be updated with migrations, to a function that we can maintain with a simple commit and changelog.

Contributor Checklist

Every pull request should have this checklist filled out, no matter how small it is.
More information about contributing to NAV can be found in the
Hacker's guide to NAV.

  • Added a changelog fragment for towncrier
  • Added/amended tests for new/changed code
  • Added/changed documentation
  • Linted/formatted the code with ruff, easiest by using pre-commit
  • Wrote the commit message so that the first line continues the sentence "If applied, this commit will ...", starts with a capital letter, does not end with punctuation and is 50 characters or less long. See https://cbea.ms/git-commit/
  • Based this pull request on the correct upstream branch: For a patch/bugfix affecting the latest stable version, it should be based on that version's branch (<major>.<minor>.x). For a new feature or other additions, it should be based on master.
  • If applicable: Created new issues if this PR does not fix the issue completely/there is further work to be done
  • If it's not obvious from a linked issue, described how to interact with NAV in order for a reviewer to observe the effects of this change first-hand (commands, URLs, UI interactions)
  • If this results in changes in the UI: Added screenshots of the before and after
  • If this adds a new Python source code file: Added the boilerplate header to that file

@Simrayz Simrayz self-assigned this Oct 13, 2025
@Simrayz Simrayz added sql discussion Requires developer feedback/discussion before implementation labels Oct 13, 2025
@Simrayz Simrayz force-pushed the chore/replace-default-dashboard-trigger branch from 13116e5 to 29c0c34 Compare October 13, 2025 09:52
@sonarqubecloud
Copy link

@github-actions
Copy link

Test results

    27 files      27 suites   45m 43s ⏱️
 2 586 tests  2 586 ✅ 0 💤 0 ❌
19 078 runs  19 078 ✅ 0 💤 0 ❌

Results for commit 29c0c34.

@codecov
Copy link

codecov bot commented Oct 13, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.21%. Comparing base (843ca70) to head (29c0c34).
⚠️ Report is 22 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3585      +/-   ##
==========================================
- Coverage   62.21%   62.21%   -0.01%     
==========================================
  Files         611      612       +1     
  Lines       44939    44951      +12     
  Branches       43       43              
==========================================
+ Hits        27960    27967       +7     
- Misses      16969    16974       +5     
  Partials       10       10              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Simrayz Simrayz marked this pull request as ready for review October 13, 2025 11:04
@Simrayz Simrayz requested a review from a team October 13, 2025 11:04
Copy link
Member

@lunkwill42 lunkwill42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be just fine in a pure Django-world. But even with this, there may be non-obvious pitfalls in the future (which is to say, I disagree with your statement that the database trigger was non-obvious, but our mileages do vary :-) )

The standard users are created using pure SQL, not using Django migrations or Python code. The next time we squash the migrations into a new SQL schema baseline, we would need to remember to also create default dashboards for the default users in pure SQL - and if we were to add new users as part of a migration at some point, we must also remember to add their dashboards, since this signal would never be triggered.

I'm not against this, I'm just saying it potentially creates different pitfalls that we still need to be aware of...

@@ -0,0 +1,32 @@
"""
signals.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeating the filename in the docstring is wholly unnecessary. However, the file lacks the license boilerplate, as mentioned in https://nav.readthedocs.io/en/latest/hacking/hacking.html#python-boilerplate-headers

@lunkwill42
Copy link
Member

We could perhaps add a safeguard against future pitfalls in the form of a test that asserts that all registered accounts has at least one dashboard.

@johannaengland johannaengland requested review from a team and hmpf October 15, 2025 12:32
verbose_name = 'NAV models'

def ready(self):
import nav.models.signals # noqa
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import nav.models.signals # noqa
import nav.models.signals # noqa: F401

just to be specific which rule you're intentionally breaking

Defines Django signal handlers for model events within the application.
Handles actions such as creating default dashboards and navlets when new Accounts
are created.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
are created.
are created.

"""
if created:
dashboard = AccountDashboard.objects.create(
name='My dashboard', account=instance, num_columns=4, is_default=True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name='My dashboard', account=instance, num_columns=4, is_default=True
name='My dashboard', account=instance, num_columns=3, is_default=True

dashboard = AccountDashboard.objects.create(
name='My dashboard', account=instance, num_columns=4, is_default=True
)
default_navlets = AccountNavlet.objects.filter(account_id=0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
default_navlets = AccountNavlet.objects.filter(account_id=0)
default_navlets = AccountNavlet.objects.filter(account_id=Account.DEFAULT_ACCOUNT)

@Simrayz
Copy link
Contributor Author

Simrayz commented Oct 15, 2025

This PR has been closed, as it has been made obsolete by a sql trigger update in #3579.

@Simrayz Simrayz closed this Oct 15, 2025
@Simrayz Simrayz deleted the chore/replace-default-dashboard-trigger branch October 15, 2025 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

discussion Requires developer feedback/discussion before implementation sql

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants