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

Account deletion #488

Merged
merged 94 commits into from
Feb 2, 2023
Merged

Account deletion #488

merged 94 commits into from
Feb 2, 2023

Conversation

dholms
Copy link
Collaborator

@dholms dholms commented Jan 25, 2023

Account deletion

This adds api flows for deleting your account & account data.

The flow is

  • user requests deletion (using their current session token)
  • PDS sends the user an email with a 6 digit token (with 15 min expiry)
  • user deletes account by supplying the 6 digit token & re-entering their password

Here is a preview of the email template:
Screen Shot 2023-01-26 at 2 37 23 PM

Account deletion does a hard delete of a user's repository, uploaded files, and indexed records. It also immediately frees up their handle (if provided by the PDS). It does not yet do anything with PLC (no tombstones implemented there yet).

One change (involving a migration) that I implemented for this is storing the creator of an ipld_block alongside the block itself. This involves storing duplicate blocks. But shared blocks between repos will be exceedingly rare.

I did not do this for blobs, but we may be interested in doing so in some future work.

Closes #474

"encoding": "application/json",
"schema": {
"type": "object",
"required": ["handle", "password", "token"],
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Requires re-entering password & as such does not require any auth

@@ -29,7 +29,7 @@ export default async (sc: SeedClient, mq?: MessageQueue) => {
)
const img2 = await sc.uploadFile(
carol,
'tests/image/fixtures/key-portrait-small.jpg',
'tests/image/fixtures/key-alt.jpg',
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I wanted to give carol a unique file that nobody else had uploaded. This changed a couple of test snapshots as well

@dholms dholms marked this pull request as ready for review January 26, 2023 20:48
"encoding": "application/json",
"schema": {
"type": "object",
"required": ["handle", "password", "token"],
Copy link
Collaborator

Choose a reason for hiding this comment

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

Check out #492— should we switch handle to identifier here to mirror it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hmmm probably...

altho actually, maybe it makes more sense to do did. to impress on the caller that you're deleting, not just the PDS concept of the user but the repo itself as well 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

btw ended up switching out for did for the above reason^^
As well, I think generally, we should only use handle as an "entry point" (login/password reset/discovery) & did for everything else.

2125fa4

@@ -40,6 +41,13 @@ export class ServerMailer {
})
}

async sendAccountDelete(params: { token: string }, mailOpts: Mail.Options) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Random thought coming to mind— we could send the user their repo over email as some part of the process.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah that'd be really nifty 👍

maybe we get that in the work push around account portability

Comment on lines 17 to 31
.addPrimaryKeyConstraint(`${commitBlockTable}_pkey`, [
'commit',
'block',
'creator',
])
.execute()
await db.schema
.createTable(commitHistoryTable)
.addColumn('commit', 'varchar', (col) => col.primaryKey())
.addColumn('commit', 'varchar', (col) => col.notNull())
.addColumn('prev', 'varchar')
.addColumn('creator', 'varchar', (col) => col.notNull())
.addPrimaryKeyConstraint(`${commitHistoryTable}_pkey`, [
'commit',
'creator',
])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Similar here— if we always expect to qualify these queries with a creator and want it to be cheap to enumerate commits/history by creator, then bumping creator up to the front of the index might be an easy win.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

good looks 👍

did that in the sync-revamp PR as well: 4719922

)
expect(found.length).toBe(0)
})
})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Only thing I might consider adding to these tests is confirmation that other users' data is still around. Touched on it a little bit in the blob test. It might look like confirming that exactly Alice's blocks are missing from the db.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah good looks

I changed my approach to it a bit & also added tests for more tables as well. Fortunately didn't come across any additional bugs from it 😛

d409acb

Comment on lines 27 to 33
.select([
'ipld_block.cid as cid',
'ipld_block_creator.did as creator',
'ipld_block.size as size',
'ipld_block.content as content',
'ipld_block.indexedAt as indexedAt',
]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just something to be a little careful with here— I don't think the column aliases are doing what one might expect/hope them to do. I believe all that matters is the column order. To ensure these are lining-up, might consider adding .columns(...) to the query (e.g. https://koskimas.github.io/kysely/classes/InsertQueryBuilder.html#expression).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is actually in regards to a separate kysely thing that bit me once.

on .returning()

Note that on SQLite you need to give aliases for the expressions to avoid this bug in SQLite. For example .returning('id as id').

altho i just kinda had it in my head that i always had to supply an alias, which it turns out you don't for select()

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

but i'll go ahead & add .columns() as well to be safe 👌

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh wild, good to know!

.deleteFrom('repo_commit_history')
.where('creator', '=', did)
.execute(),
this.db.db.deleteFrom('repo_root').where('did', '=', did).execute(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

👻

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

S C A R Y

Copy link
Collaborator

@devinivy devinivy left a comment

Choose a reason for hiding this comment

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

✨ Good stuff!

@pfrazee
Copy link
Collaborator

pfrazee commented Jan 26, 2023

LGTM!

Base automatically changed from sync-revamp to main January 27, 2023 00:09
Copy link
Collaborator

@devinivy devinivy left a comment

Choose a reason for hiding this comment

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

More ✅

@dholms dholms merged commit 773f9e3 into main Feb 2, 2023
@dholms dholms deleted the account-deletion branch February 2, 2023 18:34
@pfrazee pfrazee mentioned this pull request Feb 2, 2023
mloar pushed a commit to mloar/atproto that referenced this pull request Nov 15, 2023
* wip

* fleshing out repo storage

* fleshing out sql storage

* cleaning things up

* fix up tests

* dumb bug - commit log reversed

* rm staging in favor of commiting diffs to blockstore

* clean up benches

* fixing up sql storage

* some caching for sql repo store

* pr feedback

* migration

* wip

* migraiton test

* unclear param

* sql repo storage tests

* rm unused code

* fix up some diff code

* pr feedback

* enum for action types

* missed some

* wip

* ripping out auth lib

* more auth cleanup

* another lurker

* wip better sync primitives

* wip

* improving diffs & sync

* tests working!

* actually implemented checkout lol

* simplify interface & improve error handling

* writing sql storage code

* fixing up tests

* testing & bugfixes

* checkouts return records instead of cids

* one last refactor lol

* missed one

* handle other cid codecs on incoming car verification

* tests + tricky bugs

* unneeded blockstore method

* trim mst on del instead of save

* cleanup comment

* dont resolve did for every commit

* use "commit" instead of "root"

* getRoot -> getHead

* pr feedback

* very silly bug fix

* improve sync output

* reorging + sync of particular records

* serve & verify proofs. also rename some ipld methods

* fix up sync issue in mst

* find reachable records form carfile

* getRecord xrpc method

* pr feedback

* better migration test

* check migraiton result

* fixing up a couple things for pg

* explicit migrateTo

* async exceptions

* ipld car mimetype + remove updateRepo

* Update module publish scripts (bluesky-social#478)

* Update pds package publishing scripts

* Update auth package publishing scripts

* Update crypto package publishing scripts

* Update did-resolver package publishing scripts

* Update handle package publishing scripts

* Update xrpc-server package publishing scripts

* Update common package publishing scripts

* Update plc package publishing scripts

* Update uri package publishing scripts

* Update repo package publishing scripts

* Sort "suggested follows" by number of posts (bluesky-social#477)

* return suggestions by post count

* pr feedback

* fix up PG pagination issue

* partiion commit-history & commit-blocks by user did

* some lexicons

reworking routes

request deletion flows

delete actor rows

migration for user-partitioned-cids

move creator to be on ipld_block

migration tests

* delete records & repos

* delete blobs

* hook it up in route

* pettier ignore email templates

* testing & bugfixes

* testing blobs & bugfixes

* pr feedback

* make deletion test more robust

* change out handle for did on account deletion

* small cleanup

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add APIs and flows for account deletion
3 participants