Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

[#382] Update User API Endpoints #471

Merged
merged 13 commits into from
May 9, 2022
Merged

[#382] Update User API Endpoints #471

merged 13 commits into from
May 9, 2022

Conversation

seanpreston
Copy link
Contributor

@seanpreston seanpreston commented May 5, 2022

Purpose

This PR adds an API endpoints to:

  • update fields on the user model
  • reset users passwords

Changes

  • /api/v1/user/{user_id} — updates the currently logged-in user's first and last names.
{
  "first_name": "...",
  "last_name": "..."
}
  • /api/v1/user/{user_id}/reset-password — updates the currently logged-in user's password if old_password matches the user's current password at the time of the update.
{
  "old_password": "...",
  "new_password": "..."
}

Checklist

  • Applicable documentation updated (guides, quickstart, postman collections, tutorial, fidesdemo, database diagram.
  • If docs updated (select one):
    • documentation complete, or draft/outline provided (tag docs-team to complete/review on this branch)
    • documentation issue created (tag docs-team to complete issue separately)
  • Good unit test/integration test coverage
  • This PR contains a DB migration. If checked, the reviewer should confirm with the author that the down_revision correctly references the previous migration before merging
  • The Run Unsafe PR Checks label has been applied, and checks have passed, if this PR touches any external services

Ticket

Fixes #

@seanpreston seanpreston changed the title 382 API endpoint to update User fields [#382] API endpoint to update User fields May 5, 2022
@seanpreston seanpreston changed the title [#382] API endpoint to update User fields [#382] Update User API Endpoints May 6, 2022
Copy link
Contributor

@TheAndrewJackson TheAndrewJackson left a comment

Choose a reason for hiding this comment

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

It looks good! I just have a few questions before merging

src/fidesops/api/v1/endpoints/user_endpoints.py Outdated Show resolved Hide resolved
@@ -234,6 +234,10 @@ def delete_all(cls, db: Session) -> int: # pylint: disable=W0622
deleted_count = db.query(cls).delete()
return deleted_count

def refresh_from_db(self, db: Session) -> FidesopsBase:
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this! I've recently queried for records that I just updated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's an intricacy here in the way DB sessions work that I'll explain.

The data in a DB session isn't guaranteed to be the same as in the database. In the event that another session mutates that same data that's currently held in another session, the data in that session becomes out of date. This manifests in our API tests because we have one session scoped to the test, and another that exists on the server within the API endpoint itself. What's happening is the test-scoped session creates data that the endpoint scoped session then mutates, and the test-scoped session no longer has accurate data. Without an effective refresh our assertions past this time would fail. This is why we also call db.expunge(...) before we call this function, to manually purge this object from the session so it's refreshed from the database.

There's a rabbit hole to go down here, that if we call db.expunge(self) within refresh_from_db(...) the following error is raised:

sqlalchemy.exc.InvalidRequestError: Instance <FidesopsUser at 0x7f5d4c70a640> is not present in this Session

which would imply the instance isn't part of the session at all, when if you call this same method within a pdb.set_trace(), the method works without issue.

Copy link
Contributor

@TheAndrewJackson TheAndrewJackson May 6, 2022

Choose a reason for hiding this comment

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

That's pretty interesting! So if db.expunge(self) isn't called refresh_from_db(...) won't get the most up to date data from the DB? I guess I assumed that the new query would pull in data directly from the DB instead of the session.

src/fidesops/util/oauth_util.py Show resolved Hide resolved
src/fidesops/util/oauth_util.py Show resolved Hide resolved
@TheAndrewJackson TheAndrewJackson merged commit 6dcd082 into main May 9, 2022
@TheAndrewJackson TheAndrewJackson deleted the 382-user-update branch May 9, 2022 15:33
adamsachs pushed a commit to adamsachs/fidesops_forked_test that referenced this pull request May 17, 2022
* adds user update scope

* adds a get_current_user from token dependency

* adds user update schema

* adds update user endpoint

* expose generate_auth_header as a util method

* adds test for user update

* adds password reset endpoint and tests for unauthorized user update

* changes error code to 401, adds refresh_from_db method to the base class

* add tests for update password endpoint

* add type annotations

* remove same user requirement for user update, add password reset scope

* remove boolean return type

* remove auto import
sanders41 pushed a commit that referenced this pull request Sep 22, 2022
* adds user update scope

* adds a get_current_user from token dependency

* adds user update schema

* adds update user endpoint

* expose generate_auth_header as a util method

* adds test for user update

* adds password reset endpoint and tests for unauthorized user update

* changes error code to 401, adds refresh_from_db method to the base class

* add tests for update password endpoint

* add type annotations

* remove same user requirement for user update, add password reset scope

* remove boolean return type

* remove auto import
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants