Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage requirements refactor #749

Open
wants to merge 41 commits into
base: dev
Choose a base branch
from
Open

Usage requirements refactor #749

wants to merge 41 commits into from

Conversation

TheStrgamer
Copy link

@TheStrgamer TheStrgamer commented Jan 30, 2025

Proposed changes

Machine types and courses use a new permission class instead of boolean for usage requirements

Areas to review closely

Checklist

(If any of the points are not relevant, mark them as checked)

  • Remembered to run the makemigrations, makemessages and compilemessages management commands and committed any changes that should be included in this PR
  • Created tests that fail without the changes, if relevant/possible
  • Manually tested that the website UI works as intended with different device layouts
    • (Most common is to test with typical screen sizes for mobile (320-425 px), tablet (768 px) and desktop (1024+ px), which can easily be done with your browser's dev tools)
  • Manually tested that everything works as intended when logged in as different users locally
    • (This can be e.g. anonymous users (i.e. not being logged in), "normal" non-member users, members of different committees, and superusers)
  • Made sure that your code conforms to the code style guides
    • (It's not intended that you read through this whole document, but that you get yourself an overview over its contents, and that you use it as a reference guide / checklist while taking a second look at your code before opening a pull request)
  • Attempted to minimize the number of common code smells
    • (See the comment for the previous checkbox)
  • Added sufficient documentation - e.g. as comments, docstrings or in the README, if suitable
  • Added your changes to the "Unreleased" section of the changelog - mainly the changes that are of particular interest to users and/or developers, if any
  • Added a "Deployment notes" section above, if anything out of the ordinary should be done when deploying these changes to the server
  • Structured your commits reasonably

ddabble and others added 30 commits October 21, 2021 13:49
Always use the pull request template
@TheStrgamer TheStrgamer added the feature New functionality on the page label Jan 30, 2025
@TheStrgamer TheStrgamer requested a review from Gunvor4 January 30, 2025 19:56
Copy link

codecov bot commented Jan 30, 2025

Codecov Report

Attention: Patch coverage is 95.65217% with 2 lines in your changes missing coverage. Please review.

Project coverage is 88.27%. Comparing base (4d85a53) to head (f790067).
Report is 5 commits behind head on dev.

Files with missing lines Patch % Lines
src/make_queue/forms/course.py 88.88% 1 Missing ⚠️
src/make_queue/models/machine.py 91.66% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##              dev     #749      +/-   ##
==========================================
+ Coverage   88.17%   88.27%   +0.09%     
==========================================
  Files         152      152              
  Lines        6198     6198              
==========================================
+ Hits         5465     5471       +6     
+ Misses        733      727       -6     
Files with missing lines Coverage Δ
src/checkin/views.py 40.47% <100.00%> (ø)
src/make_queue/admin.py 100.00% <100.00%> (ø)
src/make_queue/models/course.py 95.52% <100.00%> (+0.69%) ⬆️
src/make_queue/forms/course.py 83.67% <88.88%> (+0.74%) ⬆️
src/make_queue/models/machine.py 91.47% <91.66%> (+3.23%) ⬆️
🚀 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.

Copy link
Member

@ddabble ddabble left a comment

Choose a reason for hiding this comment

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

Looks like you've changed all line endings from \n (the Linux/Unix default) to \r\n (the Windows default) 😅 The default Git setting on Windows is to convert all line endings to \n when committing, and you can reset that setting to the default value by running git config --global core.autocrlf true 🙂 See the GitHub docs on line endings for more details.

@ddabble
Copy link
Member

ddabble commented Jan 30, 2025

Btw, do you want my review on your code? It will be detailed, but I won't do it to enforce some code standard on this repo; rather, I'll to try to teach conventions and good coding practices that will be useful in a programming career 🙂

No worries if you're not interested 😊

@TheStrgamer
Copy link
Author

We need these changes as soon as possible for the new printers, but i'm still interested in the review for future improvement and learning. Thanks

@ddabble
Copy link
Member

ddabble commented Feb 6, 2025

We need these changes as soon as possible for the new printers

Worst case, it's always possible to just check out this branch on the server, if needed for whatever reason 🤠

But anyway: First, it would be great if you could convert the line endings, like I mentioned earlier, as the diff is pretty unreadable 😅

@Gunvor4 Gunvor4 requested a review from elisakiv February 20, 2025 19:01
@Gunvor4 Gunvor4 changed the base branch from main to dev February 20, 2025 19:38
Copy link
Contributor

@elisakiv elisakiv left a comment

Choose a reason for hiding this comment

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

Other than my singular comment, I can't seem to find any bugs or issues when running the code locally and looking at all the things I think will be impacted by the changes.

Maybe have a look at the failing check by codeclimate for some code cleanup stuff while you are changing things, it seems to mostly be about too many or not enough blank lines and similar nitpick.

Well done with the PR!

Copy link
Member

@ddabble ddabble left a comment

Choose a reason for hiding this comment

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

(Finally found some free time to review this 😅)

Very well done! 😄 I have some improvement suggestions below, but I'm impressed by your seemingly solid grasp of Django! 😊

CoursePermission = apps.get_model('make_queue', 'CoursePermission')

CoursePermission.objects.bulk_create([
CoursePermission(name='User is authenticated', short_name='AUTH', description='Permission to reserve machines and workstations at MAKE NTNU'),
Copy link
Member

Choose a reason for hiding this comment

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

I think we can remove AUTH entirely, as users are always required to be logged in when making a reservation anyway :)

def __str__(self):
return self.name


# `3DPrinterCourse` would be a syntactically invalid name :(
class Printer3DCourse(models.Model):
Copy link
Member

Choose a reason for hiding this comment

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

I guess this can be renamed to something like MachineCourse, now that we have permissions for any machine type :)


if completed_3d_printer:
CoursePermission = user.printer_3d_course.course_permissions.model
courses = CoursePermission.objects.exclude(short_name__in=["3DPR", "AUTH"])
Copy link
Member

Choose a reason for hiding this comment

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

There are quite a few hardcoded references to specific short_names in the code, so I think it would be a good idea to bring back a similar enum as the removed MachineType.UsageRequirement, to avoid magic strings :)

Also:

Suggested change
courses = CoursePermission.objects.exclude(short_name__in=["3DPR", "AUTH"])
special_courses = CoursePermission.objects.exclude(short_name__in=["3DPR", "AUTH"])

{% else %}
{% translate "No" %}
{% endif %}
{% for name in registration.get_permission_names %}
Copy link
Member

Choose a reason for hiding this comment

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

Note that the database will be queried every time get_permission_names() is called in this loop, so to prevent that potentially massive N+1 problem, replace values_list() with all() in that method (as mentioned in a previous comment), and make Printer3DCourseListView.queryset prefetch course_permissions.

Comment on lines +18 to +23
CoursePermission.objects.bulk_create([
CoursePermission(name='User is authenticated', short_name='AUTH', description='Permission to reserve machines and workstations at MAKE NTNU'),
CoursePermission(name='3D printer course', short_name='3DPR', description='Permission to use 3D printers at MAKE NTNU'),
CoursePermission(name='Raise3D course', short_name='R3DP', description='Permission to use the Raise3D printer at MAKE NTNU'),
CoursePermission(name='SLA course', short_name='SLAP', description='Permission to use the SLA printer at MAKE NTNU'),
])
Copy link
Member

Choose a reason for hiding this comment

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

Why do this when the 0035_coursepermission_printer3dcourse_course_permissions_and_more.py migration already creates these objects? :p

@@ -320,7 +320,7 @@ def test_only_internal_users_can_view_internal_machines(self):
response = self.client.get(machine_detail_url)
expected_status_code = HTTPStatus.OK
# ...except if the machine requires the SLA course
if machine_type.usage_requirement == MachineType.UsageRequirement.TAKEN_SLA_3D_PRINTER_COURSE:
if machine_type.usage_requirement.id == CoursePermission.objects.get(short_name='SLAP').id:
Copy link
Member

Choose a reason for hiding this comment

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

Prefer using pk instead of id when you're only interested in getting the field that identifies the object (i.e. the primary key), instead of the field name itself :)

Suggested change
if machine_type.usage_requirement.id == CoursePermission.objects.get(short_name='SLAP').id:
if machine_type.usage_requirement.pk == CoursePermission.objects.get(short_name='SLAP').pk:

@@ -6,15 +6,15 @@ A summary of changes made to the codebase, grouped per deployment.

### New features

-
- You can now add more permission types that can be used by machine types and courses using the CoursePermission class.
Copy link
Member

Choose a reason for hiding this comment

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

I think something like this is easier to understand for people who are unfamiliar with the code: (feel free to edit :))

Suggested change
- You can now add more permission types that can be used by machine types and courses using the CoursePermission class.
- Made it easier to add new permissions for any machine type, so that each permission can be granted when registering a
completed course

@@ -8,6 +8,16 @@
from .fields import UsernameField


class CoursePermission(models.Model):
Copy link
Member

Choose a reason for hiding this comment

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

Lastly, on the topic of refactoring (or, since we are changing the functionality of the code, something like "Usage requirements rework" would probably be a more accurate PR title), do we need this model at all? We should be able to just remove it entirely and instead let Printer3DCourse.course_permissions be an M2M field to MachineType (and rename the field to something like for_machine_types - as in "course for these machine types"), as all the existing usage requirements are tied to a specific machine type (except AUTH, which I commented on above) 🤔 For the machines without usage requirement (i.e. sewing machines, etc.), we can just always allow access.

That refactor should probably be made in another PR, though, but do you have any thoughts on making that change? 🙂


(Refactoring one step further could be to remove the MachineType model entirely and replace it with a hardcoded enum, as the PKs of that model are already hardcoded multiple places, and it's much easier to handle that with an enum instead of all the extra work of ensuring that certain MachineType objects always exist in the database and always have the same PKs. Also, we don't really add or remove the machine types often enough to warrant having it as a model, in my opinion, and adding a new enum member is usually a tiny and quick change to make to the code, while keeping the advantages mentioned earlier. But making that change is definitely for another PR :))

@ddabble
Copy link
Member

ddabble commented Mar 23, 2025

Btw, it looks like you based this branch on main instead of dev, judging by the long list of merge commits at the beginning of this PR 😅 If you find yourself in a similar situation in the future, you can fix that by simply rebasing this branch on dev, followed by force-pushing the branch (if you've already pushed it, of course) - but for this PR, since we've already started to review it, it's usually pretty disruptive to force-push, as it will make it harder to spot any new changes (especially if you're rebasing on a branch that has different contents compared to the original base branch), so no worries :)

But we should definitely squash-merge the PR, unless you're planning on cleaning up the commit history before merging.

Copy link
Contributor

@Gunvor4 Gunvor4 left a comment

Choose a reason for hiding this comment

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

Good work! 👍 I don't have a lot of comments regarding this PR. But when I was reviewing, I realized that this would have been a much easier job if there were more comments in the code, so I would like to request some comments / explanations in the code. The make_queue app contains maybe the most difficult code on the entire page, so especially when we make changes to this app, we should make an effort to make this part of the page more understandable for future members of the dev committee.
A more thorough description of the PR could also have been helpful.

Copy link
Contributor

@Gunvor4 Gunvor4 left a comment

Choose a reason for hiding this comment

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

There are some problems with course registrations, both with the form itself, and with the behaviour of the init method on the Printer3DCourseForm. These have been there before, so they were not introduced by this PR, but they should nonetheless be fixed since we are changing this part of the page anyway.
First of all - it makes very little sense to have fields for both username and user, especially since it is actually possible to enter different user names in these two fields. The 'username' field is coupled to the 'full name' field, while the 'user' field suggests users from the User model while typing. This is a nice feature that should be kept in order to minimize the change for typos when entering usernames. Therefore, I would suggest removing the 'username' field, and auto-filling the 'full name' field from the 'user' field instead.
Also - if a user is already added to the User model with an EM number, the EM number will be erased from the User model when the same user is added to the Printer3DCourse model without an EM number. It is possible that the EM number will be restored by information received from Feide, but new instances to the Printer3DCourse model should still not be able to delete information from the User model, so this is obviously a bug, and it should be fixed. If an EM number is already present for the user that is being added to the Printer3DCourse model - it should instead be auto-filled in the EM number field, like the user's full name is in the 'full name' field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New functionality on the page
Projects
Status: Ready for Review
Development

Successfully merging this pull request may close these issues.

5 participants