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
const path = require('path');
/**
* @TODO: pass these in as dependencies
*/
const PostRevisions = require('@tryghost/post-revisions');
const labs = require('../../shared/labs');
/**
* @typedef {Object} IdbBackup
* @prop {() => Promise<string>} backup
@ -150,6 +156,16 @@ class Users {
return this.models.Base.transaction(async (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({
id: frameOptions.id,
context: frameOptions.context,

View File

@ -21,9 +21,11 @@ class PostRevisions {
* @param {object} deps
* @param {object} deps.config
* @param {number} deps.config.max_revisions
* @param {object} deps.model
*/
constructor(deps) {
this.config = deps.config;
this.model = deps.model;
}
/**
@ -77,6 +79,35 @@ class PostRevisions {
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;

View File

@ -1,4 +1,5 @@
const assert = require('assert');
const sinon = require('sinon');
const PostRevisions = require('../');
const config = {
@ -165,4 +166,74 @@ describe('PostRevisions', function () {
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);
});
});
});