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

Feat(editor): User account deletion endpoint #843

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

tr1ten
Copy link
Collaborator

@tr1ten tr1ten commented May 21, 2022

Problem

BB-260: Implement the user account deletion endpoint

Solution

Added post route /delete-user to remove account from BB project

Copy link
Contributor

@MonkeyDo MonkeyDo left a comment

Choose a reason for hiding this comment

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

Looks great, thanks for doing this !

Considering the importance of this endpoint, we definitely want some tests to ensure that the authorization is covered, in case of changes in the future we don't want this to break silently.

It means mocking the http request in the tests with superagent

We also want a separate test to fetch a deleted user after the endpoint was called succesfully, and ensure all their info is wiped.

Copy link
Contributor

@MonkeyDo MonkeyDo left a comment

Choose a reason for hiding this comment

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

OK, I did a thorough review, and good on us because I missed a bunch of things ! :p

Thanks a lot for writing tests, that allowed me to think about the code more thoroughly and project into specific scenarios.
I took special care with the review on this one, just to ensure nothing can go wrong :)

// Setting up mocking agent for test
// eslint-disable-next-line node/no-process-env
if (process.env.NODE_ENV === 'test') {
mock(request, config);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need to be in this file? Could it not be set up at the beginning of the test file instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Placing it inside the test file also seems to work, though i initially thought it needs to be in same lexical scope.

expect(res.ok).to.be.true;
const editor = await new Editor({id: userEditorId}).fetch();
expect(editor).to.exist;
expect(verifyDeletedUser(editor.toJSON())).to.be.true;
Copy link
Contributor

Choose a reason for hiding this comment

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

We can probably replace verifyDeletedUser with a direct comparison between the editor json object and deletedUserAttrib, just for simplicity of reading the code.
We'll need to omit a couple of properties that will change between runs, as well as add a couple to deletedUserAttrib:

Suggested change
expect(verifyDeletedUser(editor.toJSON())).to.be.true;
const editorJson = _.omit(editor.toJSON(),['activeAt','createdAt','typeId'])
expect(editorJson).to.equal(deletedUserAttrib);

And to add to deletedUserAttrib:

"id": 2,
"name": "Deleted User #2",
"reputation": 0

@@ -0,0 +1,41 @@
/* eslint-disable camelcase */
Copy link
Contributor

Choose a reason for hiding this comment

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

This file is currently placed in the repo root, we'll want it in test/test-helpers instead.

const otherEditorName = 'NormalUser2';
let agent;
before(async () => {
await createEditor(adminEditorId, {name: adminEditorName});
Copy link
Contributor

Choose a reason for hiding this comment

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

This user shouldn't be necessary.
The UserDeleter special user is in the MusicBrainz database, not in the BookBrainz one, and we don't really interact with MB other than authenticate it

return res.status(404).send();
}
// deleting all user info
const deletedUser = `Deleted User#${editor.get('id')}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const deletedUser = `Deleted User#${editor.get('id')}`;
const deletedUser = `Deleted User #${editor.get('id')}`;

editor.set('revisions_applied', 0);
editor.set('revisions_reverted', 0);
editor.set('total_revisions', 0);
editor.set('metabrainz_user_id', null);
Copy link
Contributor

Choose a reason for hiding this comment

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

I need to think about this, not sure if we want to keep this to be able to link it back to an MB account.
I'm thinking for example for abusive accounts that would get deleted by admins across the platforms, it could be necessary to have this information.

editor.set('name', deletedUser);
await editor.save();
// eslint-disable-next-line camelcase
return res.send({metabrainz_user_id: USER_DELETER_MBID, sub: USER_DELETER});
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably no need to return any actual data. Looking at the description of https://tickets.metabrainz.org/browse/MBS-9680 and the comments there, MB only expects a 200 status code if all went well.

Comment on lines 46 to 47
await createEditor(userEditorId, {name: userEditorName});
await createEditor(otherEditorId, {name: otherEditorName});
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand why we need two more users here.
If I remember correctly, when you use agent = await chai.request.agent(app); below it should run the superagent queries authenticated as our mock-user with id 123456.

Meaning your test "Normal User should not be able to delete other users" is actually testing that user 123456 is not authorized, which is completely valid but does not require the extraneous users

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yep, you are correct. we only need one user ( that we test for deletion) else only those ids would suffice.

expect(res.ok).to.be.false;
// unauthorized
expect(res.status).to.be.equal(401);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd also love to see, for good measure, another test to ensure we get a 401 for an unauthenticated user.
Basically the same test as the above, but using await chai.request(app).post(… <- this will not use a user session because we won't call /cb as we do in the before function

@@ -121,7 +121,7 @@ export function createEditor(editorId) {
editorAttribs.id = editorId || random.number();
editorAttribs.genderId = gender.id;
editorAttribs.typeId = editorType.id;
editorAttribs.name = internet.userName();
editorAttribs.name = otherEditorAttribs?.name || internet.userName();
Copy link
Contributor

Choose a reason for hiding this comment

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

Considering I'm already making you change something here (using metabrainzUserId instead of name) let's make it easier to be reusable:

After defining sane defaults, we can merge editorAttribs and otherEditorAttribs and pass the result to new Editor(…
Maybe the simple new Editor({...editorAttribs,…otherEditorAttribs}) ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants