Skip to content

Create models and controllers for lessons (rebased against main and fixed up) #258

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

Conversation

floehopper
Copy link
Contributor

@floehopper floehopper commented Apr 11, 2024

We created this PR as follows:

  1. Creating a new branch based on the latest main.
  2. Cherry-picking the commits from Create models and controllers for lessons #241 that were not included in this squash merge commit.
  3. Resolving a number of conflicts, particularly a bunch relating to a user's roles and organisations caused by some changes in Initial project and component dashboards #242 which added a new "editor-admin" role.
  4. Fixing a bug we noticed in User.temporarily_add_organisations_until_the_profile_app_is_updated.
  5. Adding a bit of missing test coverage.

TODO:

  • Do some manual testing of the editor-ui app and/or the editor-standalone app against the code in this branch. In particular, it would be worth testing some operations on a user (e.g. logging in) and operations on projects (e.g. creating & updating).
  • Although I have already reviewed these commits as part of my original review of Create models and controllers for lessons #241, it might be worth someone else reviewing the (much smaller number of) commits in this PR.
  • Add an issue for adding proper support for non-organisation-specific roles if we think this is likely to be needed
  • We might want to replace the original issues/239-Create_models_and_controllers_for_lessons branch with this issues/239-Create_models_and_controllers_for_lessons-rebased-against-main-and-fixed-up branch to keep GitHub projects happy before we merge these changes, but I'm not sure it's essential.
  • I'd recommend we rebase this branch against main just before merging, force-push if necessary, and then merge with a merge commit (but not squashing) in order to preserve the original individual commits to make it easier to see what's happened.

/cc @sra405 @tuzz @chrislo @chrisroos

tuzz added 30 commits April 11, 2024 16:31
Set the request body from the existing params that we know are valid.
Otherwise, the request might fail with an error but the test would pass
for the wrong reason.
This is so that we can present the user attributed to the lesson. This
might not necessarily be a school-teacher if it is a public lesson
authored by Raspberry Pi.
We already have this pattern in SchoolClasses controller so make it so
that school-owner users are allowed to set the Lesson#user whereas
regular users may not - the lesson is always assigned to themselves.
The authorisation logic varies by #visibility:

- ‘private’ lessons can only be seen by the lesson’s user (e.g. a draft)
- ‘public’ lessons can be seen by all users (e.g. for Raspberry Pi lessons)
- ‘teachers’ lessons can be seen by all teachers within the school
- ‘students’ lessons can be seen by students within the school, provided
  they are a member of the lesson’s class
The naming follows the ‘remixed_from’ convention on projects.
For consistency with projects.remixed_from_id
A project can have an optional school association, e.g. if it is a
member of a school’s library of resources or if it is assigned to a
lesson.
If the user has the school-owner or school-teacher role, they can create
a project that is associated with a school (but not a school class).

If the user is a school-owner they can assign a teacher to the project
in the same was as lessons, otherwise the school-teacher is always set
as the project’s owner (user).
tuzz and others added 5 commits April 11, 2024 17:33
These methods are class methods and so we should use a "." prefix rather
than a "#" prefix which denotes an instance method.
Previously
`User.temporarily_add_organisations_until_the_profile_app_is_updated`
did not mutate the `hash` argument and the callsites ignored the return
value and so the organisations were never added. This wasn't causing any
spec failures, because all the relevant stubbing was using users from
`spec/fixtures/users.json` all of which already had a value for the
"organisations" key set.

However, the real servers for `UserInfoApiClient.from_userinfo` &
`HydraPublicApiClient.from_token` currently do *not* return a value for
the "organisations" key. Indeed that's _why_ the
`User.temporarily_add_organisations_until_the_profile_app_is_updated`
method exists in the first place.

I've added examples for `UserInfoApiClient.from_userinfo` &
`HydraPublicApiClient.from_token` which make use of a new user in
`spec/fixtures/users.json` which has no value for the "organisations"
key set. These examples failed until I changed the implementation of
`User.temporarily_add_organisations_until_the_profile_app_is_updated` to
mutate the `hash` argument.

I think there might be an argument to remove the value for the
"organisations" key for all users in `spec/fixtures/users.json`, but
this will do for now.
Strictly speaking this doesn't test that the current implementation
returns `true` if the user has the "editor-admin" role for *any*
organisation. However, that's already a bit of a bodge until we decide
whether we want to properly support non-organisation-specific roles, so
I think this is fine for now.
@cla-bot cla-bot bot added the cla-signed label Apr 11, 2024
@raspberrypiherokubot raspberrypiherokubot temporarily deployed to editor-api-p-issues-239-usxxhw April 11, 2024 17:25 Inactive
Copy link
Contributor

@tuzz tuzz left a comment

Choose a reason for hiding this comment

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

Nice spot 👍

Yeah, we had some discussions with the core team about them introducing the notion of organisations into the profile app so that user permissions could be scoped to a school (organisation). Greg or Daniel can probably explain more, I don't remember all the details.

@tuzz
Copy link
Contributor

tuzz commented Apr 11, 2024

I think this document has more details, although I no longer have access.

Previously this spec was making use of a `User` model and the
`User#serializable_hash` method. However, I'm pretty sure that was just
a convenience and there is nothing actually tying the attributes
returned from OmniAuth to the `User` model attributes.

I've changed the setup so it uses an explicit `Hash` derived from
observing the attributes that OmniAuth actually provides. This seems
more realistic and I'm hoping it will make it easier to apply an
unrelated fix in a subsequent commit.

I've also changed the assertions to be more explicit and like those
in the specs for `User.from_userinfo` & `User.from_token`.
We need to call
`User.temporarily_add_organisations_until_the_profile_app_is_updated`
from `User.from_auth` like we do from `User.from_userinfo` &
`User.from_token` so that the `organisations` attribute gets populated.
@floehopper floehopper force-pushed the issues/239-Create_models_and_controllers_for_lessons-rebased-against-main-and-fixed-up branch from 5e0939a to 80e3c88 Compare April 15, 2024 16:56
This fixes a problem that was introduced in this commit [1]. The call to
`skip_load_resource only: :create` was removed which meant that the call
to `load_and_authorize_resource` triggered an attempt to instantiate a
`Project` model using the params identified by CanCanCan. This included
the `image_list` param which did not exist as an attribute on a
`Project` and thus resulted in the following exception:

    ActiveModel::UnknownAttributeError: unknown attribute 'image_list' for Project.

I did initially look at fixing the problem while maintaining the ability
to pass the `image_list` into `Project::Create#call`. However, the
functionality in `Project::Create#build_project` which loops through the
`image_list` was not previously tested and I can't really see that it
ever worked. Furthermore, @sra405 has pointed out that we're not
currently allowing users to add their own images to a project for
safeguarding reasons and so I thought it made more sense to fix the
problem by removing support for `image_list` from the create project
endpoint for now until we actually need it. /cc @loiswells97

Removing the `image_list` param from the permitted params in
`Api::ProjectsController#base_params` should mean it is never included
in the params supplied to either CanCanCan's
`load_and_authorize_resource` method or to `Project::Create#call`,
although it will mean that a warning will appear in the logs. So ideally
we'd remove it from the params being supplied by the UI.

Note that the images from the projects in the `raspberrypilearning`
GitHub organisation [2] are added to a project using a different
mechanism and so should not be affected by this change.

[1]: 39f45f7
@floehopper
Copy link
Contributor Author

As discussed in Slack, I've fixed a problem that was causing an exception when creating a project as a logged in user with no roles.

@floehopper
Copy link
Contributor Author

floehopper commented Apr 17, 2024

  • Do some manual testing of the editor-ui app and/or the editor-standalone app against the code in this branch. In particular, it would be worth testing some operations on a user (e.g. logging in) and operations on projects (e.g. creating & updating).

I've had a go at doing this locally and this is what led me to finding and fixing the problem described in 0148d94.

One I was concerned about was that logged-in users with no roles would still be able to do what they used to be able to do and that does indeed appear to be the case. And I've double-checked this by reading the code. You can see from the code snippets below that the only difference is that the code in the branch specifies that the school_id must be nil for the relevant anuthorization logic to apply:

  • Anyone can view projects not owner by a user or a school:

In main:

can :show, Project, user_id: nil
can :show, Component, project: { user_id: nil }

In this branch:

# Anyone can view projects not owner by a user or a school.
can :show, Project, user_id: nil, school_id: nil
can :show, Component, project: { user_id: nil, school_id: nil }

  • Any authenticated user can create projects not owned by a school:

In main:

can %i[read create update destroy], Project, user_id: user.id
can %i[read create update destroy], Component, project: { user_id: user.id }

In this branch:
https://github.com/RaspberryPiFoundation/editor-api/blob/0148d94fcedf612df52e799add43b16d0379f566/app/models/ability.rb#L17C7-L19

  • Any authenticated user can manage their own projects:

In main:

can %i[read create update destroy], Project, user_id: user.id
can %i[read create update destroy], Component, project: { user_id: user.id }

In this branch:
https://github.com/RaspberryPiFoundation/editor-api/blob/0148d94fcedf612df52e799add43b16d0379f566/app/models/ability.rb#L21C7-L23

I've also confirmed that after this fix I can login to the admin dashboard with a user that has the "editor-admin" role.

So I'm happy to tick this checkbox.

@floehopper
Copy link
Contributor Author

Given that both @chrislo & I looked at a lot of the commits during our efforts to rebase the branch and all the manual testing I've done. I'm no longer convinced this is worthwhile, so I'm happy to delete this checkbox item.

@floehopper
Copy link
Contributor Author

  • Add an issue for adding proper support for non-organisation-specific roles if we think this is likely to be needed

I've created an issue in the "Ideas" section of the project: RaspberryPiFoundation/editor-ui#984

I hope that makes sense. /cc @sra405

@floehopper
Copy link
Contributor Author

  • We might want to replace the original issues/239-Create_models_and_controllers_for_lessons branch with this issues/239-Create_models_and_controllers_for_lessons-rebased-against-main-and-fixed-up branch to keep GitHub projects happy before we merge these changes, but I'm not sure it's essential.

I've discovered that it is possible to associate multiple PRs with an issue, so I don't think this step is necessary.

@floehopper
Copy link
Contributor Author

  • I'd recommend we rebase this branch against main just before merging, force-push if necessary, and then merge with a merge commit (but not squashing) in order to preserve the original individual commits to make it easier to see what's happened.

The branch is still up-to-date against main, but I will double-check before merging.

@sra405
Copy link
Contributor

sra405 commented Apr 17, 2024

I've created an issue in the "Ideas" section of the project: RaspberryPiFoundation/editor-ui#984

I hope that makes sense. /cc @sra405

Thanks @floehopper that makes sense to me 👍 thanks for adding the ticket, it's definitely one that needs mulling over

Copy link
Contributor

@chrisroos chrisroos left a comment

Choose a reason for hiding this comment

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

@chrislo and I have reviewed the last 6 commits and they look good to us 👍

@floehopper floehopper merged commit 385f5a1 into main Apr 17, 2024
@floehopper floehopper deleted the issues/239-Create_models_and_controllers_for_lessons-rebased-against-main-and-fixed-up branch April 17, 2024 11:10
@floehopper floehopper linked an issue Apr 17, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create models and controllers for lessons
5 participants