Removed id restriction for posts relations in Admin API v2 (#10489)

refs #10438

- we now try to match by slug or id or email
- fallback to owner
- you cannot create a user via post endpoint
- Ghost uses the invite flow to add users
- get rid of `id` restriction on API level
This commit is contained in:
Katharina Irrgang 2019-02-13 20:38:25 +01:00 committed by GitHub
parent 6bdeeaba10
commit c2b3520652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 36 deletions

View File

@ -134,9 +134,21 @@
"id": {
"type": "string",
"maxLength": 24
},
"slug": {
"type": "string",
"maxLength": 191
},
"email": {
"type": "string",
"maxLength": 191
}
},
"required": ["id"]
"anyOf": [
{"required": ["id"]},
{"required": ["slug"]},
{"required": ["email"]}
]
}
},
"post-tags": {

View File

@ -1,6 +1,7 @@
const _ = require('lodash'),
Promise = require('bluebird'),
common = require('../../lib/common');
const _ = require('lodash');
const Promise = require('bluebird');
const common = require('../../lib/common');
const sequence = require('../../lib/promise/sequence');
/**
* Why and when do we have to fetch `authors` by default?
@ -100,10 +101,13 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
return this._handleOptions('onUpdating')(model, attrs, options);
},
// NOTE: `post.author` was always ignored [unsupported]
// @NOTE: `post.author` was always ignored [unsupported]
// @NOTE: triggered before creating and before updating
onSaving: function (model, attrs, options) {
const ops = [];
/**
* @deprecated: `author`, will be removed in Ghost 3.0
* @deprecated: `author`, will be removed in Ghost 3.0, drop v0.1
*/
model.unset('author');
@ -114,6 +118,22 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
});
}
/**
* @NOTE:
*
* Try to find a user with either id, slug or email if "authors" is present.
* Otherwise fallback to owner user.
*
* You cannot create an author via posts!
* Ghost uses the invite flow to create users.
*/
if (model.get('authors')) {
ops.push(() => {
return this.matchAuthors(model, options);
});
}
ops.push(() => {
// CASE: `post.author_id` has changed
if (model.hasChanged('author_id')) {
// CASE: you don't send `post.authors`
@ -153,6 +173,9 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
}
return proto.onSaving.call(this, model, attrs, options);
});
return sequence(ops);
},
serialize: function serialize(options) {
@ -203,6 +226,54 @@ module.exports.extendModel = function extendModel(Post, Posts, ghostBookshelf) {
}
return attrs;
},
matchAuthors(model, options) {
let ownerUser;
const ops = [];
ops.push(() => {
return ghostBookshelf
.model('User')
.getOwnerUser(Object.assign({columns: ['id']}, _.pick(options, 'transacting')))
.then((_ownerUser) => {
ownerUser = _ownerUser;
});
});
ops.push(() => {
const authors = model.get('authors');
return Promise.each(authors, (author, index) => {
const query = {};
if (author.id) {
query.id = author.id;
} else if (author.slug) {
query.slug = author.slug;
} else if (author.email) {
query.email = author.email;
}
return ghostBookshelf
.model('User')
.where(query)
.fetch(Object.assign({columns: ['id']}, _.pick(options, 'transacting')))
.then((user) => {
authors[index] = {};
if (!user) {
authors[index].id = ownerUser.id;
} else {
authors[index].id = user.id;
}
});
}).then(() => {
model.set('authors', authors);
});
});
return sequence(ops);
}
}, {
/**

View File

@ -20,7 +20,7 @@ describe('Authors Content API', function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
return testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'api_keys');
return testUtils.initFixtures('owner:post', 'users:no-owner', 'user:inactive', 'posts', 'api_keys');
});
});

View File

@ -19,7 +19,7 @@ describe('Posts Content API', function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
return testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys');
return testUtils.initFixtures('owner:post', 'users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys');
});
});