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

Add cascade delete constraints, allow users to delete their accounts #316

Merged
merged 3 commits into from
Mar 20, 2023

Conversation

DasSkelett
Copy link
Member

@DasSkelett DasSkelett commented Aug 7, 2020

Motivation

Every now and then users want to delete their accounts (we should ask for the reason the next time, out of interest).
Every website with the option to create accounts should (and also must) have another option to delete these accounts again.

How and what

There's still the discussion on what we actually want to delete if a user deletes their account.

For know, to get us started, I decided to stay consistent with what we already do and delete everything linked to that user, both in the database and on disk. This means mods of these users are deleted too.

Please continue this discussion in #215 or on the Discord and leave the comments on this PR to actual code review.
I'll update this PR depending on how we decide on that.

Changes

  • If the user's session cookie has an invalid game id (e.g. if the game has been deleted after it has been set in the cookie) _restore_game_info() threw an exception. Now it returns None.
  • Some database magic: Added cascade delete constraints to all the relationships / foreign key constraints where it makes sense. This simplifies the deletion of mods (and also deletes some stuff we forgot until now, like download events and follow events), and enables the deletion of user accounts. It'll likely help us in the future too.
    This needs a database migration.
  • Based on this, I added an option for users to delete their accounts in the profile edit page. There's not much to it, I've mostly copied the code from the password change option where possible. To prevent some unfortunate mouse clicks having a devastating effect, you have to enter your username to confirm the deletion.
  • Admins can also delete users, on the user profile page (where all the other per-user admin infos and options are)

Closes #215

@DasSkelett DasSkelett added Area: Backend Related to the Python code that runs inside gunicorn Priority: Normal Type: Feature Status: In Progress Area: Frontend Related to HTML, JS, CSS, or other browser things Area: Migration Related to Alembic database migrations labels Aug 7, 2020
@DasSkelett DasSkelett force-pushed the feature/delete-account branch from 38beb90 to 19b18f5 Compare August 7, 2020 18:06
@DasSkelett DasSkelett force-pushed the feature/delete-account branch 2 times, most recently from e759e33 to e2c5f16 Compare September 18, 2020 18:25
@DasSkelett DasSkelett force-pushed the feature/delete-account branch from e2c5f16 to ff3eda6 Compare January 10, 2021 20:45
@DasSkelett DasSkelett force-pushed the feature/delete-account branch from ff3eda6 to ff825ab Compare May 18, 2021 21:08
@HebaruSan
Copy link
Contributor

What remains to be done here? Do we just need a final decision on what should be deleted, or are there code pieces left?

@DasSkelett
Copy link
Member Author

Hm, can't really remember the technical points, maybe the deletion of zips when individual mod versions are deleted had still to be done.
It was mostly the discussion about what to delete that I didn't want to bring up again that kept this WIP.

@DasSkelett DasSkelett force-pushed the feature/delete-account branch from ff825ab to 6b42944 Compare November 2, 2021 13:09
@HebaruSan
Copy link
Contributor

HebaruSan commented Nov 2, 2021

It was mostly the discussion about what to delete that I didn't want to bring up again that kept this WIP.

Would it be easier to proceed if we deferred this decision to a config setting?

@HebaruSan HebaruSan linked an issue Nov 2, 2021 that may be closed by this pull request
@HebaruSan
Copy link
Contributor

HebaruSan commented Nov 2, 2021

Should we add cascade deletion to Following.mod_id and Following.user_id?



def upgrade() -> None:
op.drop_constraint('downloadevent_version_id_fkey', 'downloadevent', type_='foreignkey')
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to try to delete old records that weren't deleted in the past and now have invalid or missing values?

Comment on lines 208 to 210
<div class="col-md-6">
<h2 title="change-password">Delete User Account</h2>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

This 2x2 table layout breaks in a narrow window:

image

We should try to keep related elements together.

Comment on lines 482 to 483
if form_username != username:
return {'error': True, 'reason': 'Wrong username'}
Copy link
Contributor

@HebaruSan HebaruSan Nov 2, 2021

Choose a reason for hiding this comment

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

Hmm, it doesn't feel right to assume form inputs in an /api/ route. An "API" should be usable by whatever random JSON clients people want to write (e.g. Netkan or Nertea's publishing scripts), not just the front-end.

Instead of checking whether there's a match after the user clicks the Delete confirmation button, could we try this?

  • The Delete button in the popup starts out disabled (but Cancel is always enabled)
  • An event handler in the username box checks whether its value is correct, and then enables or disables the Delete button based on that

That way the user could only click the button after they type the name. If some admin wants to delete users with an API script independently, the confirmation flow would not be relevant to them anyway.

This may also make it possible to change the popup form's action to /api/user/{{ profile.username }}/delete and delete most of the new script code.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, it doesn't feel right to assume form inputs in an /api/ route. An "API" should be usable by whatever random JSON clients people want to write (e.g. Netkan or Nertea's publishing scripts), not just the front-end.

This is pretty normal and standard, we do this in a lot of API routes. That's why they are POSTs. You need some way to transmit data to the server.
I'm not aware of any HTTP client that is incapable of including form data in a POST request. Netkan only reads from the API and doesn't write anything, thus it also doesn't use POSTs. But I'm very confident that WebClient could include form data if it needed to.

Here it is primarily meant as a "confirmation" feature so you don't delete your account accidentally. Whether that's useful for APIs is debatable I guess, I'm okay with removing it. I'm pretty sure that just came from adopting the password change mechanism.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh right, the api.md documentation does say:

Submit all POSTS with the request body encoded as
multipart/form-data. Your HTTP library
of choice probably handles that for you. All responses are JSON.

... so using a form input is fine. I guess my objection is just to this one specific form input, then.

Copy link
Contributor

Choose a reason for hiding this comment

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

Added an implementation of this suggestion in #417, with script code enabling/disabling the button.

if current_user.username == username:
deletable = True
if not deletable:
return {'error': True, 'reason': 'Unauthorized'}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we use HTTP status codes for this function's returns? The change password route does this, specifically with 403.

HebaruSan added a commit to HebaruSan/SpaceDock that referenced this pull request Nov 2, 2021
HebaruSan added a commit to HebaruSan/SpaceDock that referenced this pull request Nov 2, 2021
@HebaruSan HebaruSan added the Scope: Large Complex changes requiring a lot of effort to develop and review label Nov 13, 2021
@HebaruSan HebaruSan force-pushed the feature/delete-account branch from 6b42944 to 309896a Compare March 20, 2023 03:19
@HebaruSan HebaruSan marked this pull request as ready for review March 20, 2023 03:19
@HebaruSan
Copy link
Contributor

HebaruSan commented Mar 20, 2023

Rebased and added a fix for mod_followers to fix 500 errors users have been experiencing at deletion:

Mar 19 15:50:52 sd1a gunicorn[17994]: 2023-03-19 15:50:52,142 ERROR SpaceDock:17994 Dependency rule tried to blank-out primary key column ‘mod_followers.mod_id’ on instance ‘<Following at 0x7f8c8fd720d0>’

Looks like the discussion of what to delete has wound down, and this PR's approach will be fine.

Copy link
Contributor

@HebaruSan HebaruSan left a comment

Choose a reason for hiding this comment

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

Nice work, and we need it.

@HebaruSan HebaruSan merged commit b858a2e into KSP-SpaceDock:alpha Mar 20, 2023
HebaruSan added a commit to HebaruSan/SpaceDock that referenced this pull request Mar 20, 2023
@HebaruSan HebaruSan changed the title [WIP] Add cascade delete constraints, allow users to delete their accounts Add cascade delete constraints, allow users to delete their accounts Apr 4, 2023
This was referenced Apr 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Backend Related to the Python code that runs inside gunicorn Area: Frontend Related to HTML, JS, CSS, or other browser things Area: Migration Related to Alembic database migrations Priority: Normal Scope: Large Complex changes requiring a lot of effort to develop and review Status: In Progress Type: Feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Delete Account Option
2 participants