Removed post revision author id on user deletion (#16670)

no issue

When a user is deleted any post revisions created by the user are set to
be owned by nobody (null) rather than deleting the post revisions
associated with the user
This commit is contained in:
Michael Barrett 2023-04-19 14:00:45 +01:00 committed by GitHub
parent a65f928932
commit 78da6cf77d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 118 additions and 0 deletions

View File

@ -1,6 +1,12 @@
// @ts-check // @ts-check
const path = require('path'); const path = require('path');
/**
* @TODO: pass these in as dependencies
*/
const PostRevisions = require('@tryghost/post-revisions');
const labs = require('../../shared/labs');
/** /**
* @typedef {Object} IdbBackup * @typedef {Object} IdbBackup
* @prop {() => Promise<string>} backup * @prop {() => Promise<string>} backup
@ -150,6 +156,16 @@ class Users {
return this.models.Base.transaction(async (t) => { return this.models.Base.transaction(async (t) => {
frameOptions.transacting = t; frameOptions.transacting = t;
if (labs.isSet('postHistory')) {
const postRevisions = new PostRevisions({
model: this.models.PostRevision
});
await postRevisions.removeAuthorFromRevisions(frameOptions.id, {
transacting: frameOptions.transacting
});
}
await this.assignTagToUserPosts({ await this.assignTagToUserPosts({
id: frameOptions.id, id: frameOptions.id,
context: frameOptions.context, context: frameOptions.context,

View File

@ -21,9 +21,11 @@ class PostRevisions {
* @param {object} deps * @param {object} deps
* @param {object} deps.config * @param {object} deps.config
* @param {number} deps.config.max_revisions * @param {number} deps.config.max_revisions
* @param {object} deps.model
*/ */
constructor(deps) { constructor(deps) {
this.config = deps.config; this.config = deps.config;
this.model = deps.model;
} }
/** /**
@ -77,6 +79,35 @@ class PostRevisions {
title: input.title title: input.title
}; };
} }
/**
* @param {string} authorId
* @param {object} options
* @param {object} options.transacting
*/
async removeAuthorFromRevisions(authorId, options) {
const revisions = await this.model.findAll({
filter: `author_id:${authorId}`,
columns: ['id'],
transacting: options.transacting
});
const revisionIds = revisions.toJSON()
.map(({id}) => id);
if (revisionIds.length === 0) {
return;
}
await this.model.bulkEdit(revisionIds, 'post_revisions', {
data: {
author_id: null
},
column: 'id',
transacting: options.transacting,
throwErrors: true
});
}
} }
module.exports = PostRevisions; module.exports = PostRevisions;

View File

@ -1,4 +1,5 @@
const assert = require('assert'); const assert = require('assert');
const sinon = require('sinon');
const PostRevisions = require('../'); const PostRevisions = require('../');
const config = { const config = {
@ -165,4 +166,74 @@ describe('PostRevisions', function () {
assert.equal(actual.length, 2); assert.equal(actual.length, 2);
}); });
}); });
describe('removeAuthor', function () {
it('removes the provided author from post revisions', async function () {
const authorId = 'abc123';
const options = {
transacting: {}
};
const revisions = [
{
id: 'revision123',
post_id: 'post123',
author_id: 'author123'
},
{
id: 'revision456',
post_id: 'post123',
author_id: 'author123'
},
{
id: 'revision789',
post_id: 'post123',
author_id: 'author456'
}
];
const modelStub = {
findAll: sinon.stub().resolves({
toJSON: () => revisions
}),
bulkEdit: sinon.stub().resolves()
};
const postRevisions = new PostRevisions({
model: modelStub
});
await postRevisions.removeAuthorFromRevisions(authorId, options);
assert.equal(modelStub.bulkEdit.calledOnce, true);
const bulkEditArgs = modelStub.bulkEdit.getCall(0).args;
assert.deepEqual(bulkEditArgs[0], ['revision123', 'revision456', 'revision789']);
assert.equal(bulkEditArgs[1], 'post_revisions');
assert.deepEqual(bulkEditArgs[2], {
data: {
author_id: null
},
column: 'id',
transacting: options.transacting,
throwErrors: true
});
});
it('does nothing if there are no post revisions by the provided author', async function () {
const modelStub = {
findAll: sinon.stub().resolves({
toJSON: () => []
}),
bulkEdit: sinon.stub().resolves()
};
const postRevisions = new PostRevisions({
model: modelStub
});
await postRevisions.removeAuthorFromRevisions('abc123', {
transacting: {}
});
assert.equal(modelStub.bulkEdit.calledOnce, false);
});
});
}); });