mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-27 21:03:29 +03:00
Merge pull request #2814 from lennerd/issue-2601
Refactore slug API for generating tag and post slugs
This commit is contained in:
commit
97011e5eca
@ -13,13 +13,14 @@ var _ = require('lodash'),
|
|||||||
tags = require('./tags'),
|
tags = require('./tags'),
|
||||||
themes = require('./themes'),
|
themes = require('./themes'),
|
||||||
users = require('./users'),
|
users = require('./users'),
|
||||||
|
slugs = require('./slugs'),
|
||||||
|
|
||||||
http,
|
http,
|
||||||
formatHttpErrors,
|
formatHttpErrors,
|
||||||
cacheInvalidationHeader,
|
cacheInvalidationHeader,
|
||||||
locationHeader,
|
locationHeader,
|
||||||
contentDispositionHeader,
|
contentDispositionHeader,
|
||||||
init,
|
init;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ### Init
|
* ### Init
|
||||||
@ -247,5 +248,6 @@ module.exports = {
|
|||||||
settings: settings,
|
settings: settings,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
themes: themes,
|
themes: themes,
|
||||||
users: users
|
users: users,
|
||||||
|
slugs: slugs
|
||||||
};
|
};
|
||||||
|
@ -168,26 +168,6 @@ posts = {
|
|||||||
}, function () {
|
}, function () {
|
||||||
return when.reject(new errors.NoPermissionError('You do not have permission to remove posts.'));
|
return when.reject(new errors.NoPermissionError('You do not have permission to remove posts.'));
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ## Generate Slug
|
|
||||||
* Create a unique slug for a given post title
|
|
||||||
* @param {{title (required), transacting}} options
|
|
||||||
* @returns {Promise(String)} Unique string
|
|
||||||
*/
|
|
||||||
generateSlug: function generateSlug(options) {
|
|
||||||
return canThis(options.context).slug.post().then(function () {
|
|
||||||
return dataProvider.Base.Model.generateSlug(dataProvider.Post, options.title, {status: 'all'})
|
|
||||||
.then(function (slug) {
|
|
||||||
if (slug) {
|
|
||||||
return slug;
|
|
||||||
}
|
|
||||||
return when.reject(new errors.InternalServerError('Could not generate slug'));
|
|
||||||
});
|
|
||||||
}, function () {
|
|
||||||
return when.reject(new errors.NoPermissionError('You do not have permission.'));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
46
core/server/api/slugs.js
Normal file
46
core/server/api/slugs.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
var canThis = require('../permissions').canThis,
|
||||||
|
dataProvider = require('../models'),
|
||||||
|
errors = require('../errors'),
|
||||||
|
when = require('when'),
|
||||||
|
|
||||||
|
slugs,
|
||||||
|
// `allowedTypes` is used to define allowed slug types and map them against it's model class counterpart
|
||||||
|
allowedTypes = {
|
||||||
|
post: dataProvider.Post,
|
||||||
|
tag: dataProvider.Tag
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Generate Slug
|
||||||
|
* Create a unique slug for a given post title
|
||||||
|
* @param {{type (required), context}} options
|
||||||
|
* @param {{title (required), transacting}} options
|
||||||
|
* @returns {Promise(String)} Unique string
|
||||||
|
*/
|
||||||
|
slugs = {
|
||||||
|
|
||||||
|
// #### Generate slug
|
||||||
|
// **takes:** a string to generate the slug from
|
||||||
|
generate: function (options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
return canThis(options.context).generate.slug().then(function () {
|
||||||
|
if (allowedTypes[options.type] === undefined) {
|
||||||
|
return when.reject(new errors.BadRequestError('Unknown slug type \'' + options.type + '\'.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataProvider.Base.Model.generateSlug(allowedTypes[options.type], options.title, {status: 'all'}).then(function (slug) {
|
||||||
|
if (!slug) {
|
||||||
|
return when.reject(new errors.InternalServerError('Could not generate slug.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { slugs: [{ slug: slug }] };
|
||||||
|
});
|
||||||
|
}, function () {
|
||||||
|
return when.reject(new errors.NoPermissionError('You do not have permission to generate a slug.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = slugs;
|
@ -71,9 +71,14 @@ var fixtures = {
|
|||||||
|
|
||||||
permissions003: [
|
permissions003: [
|
||||||
{
|
{
|
||||||
"name": "Get slug",
|
"name": "Generate post slug",
|
||||||
"action_type": "slug",
|
"action_type": "generate",
|
||||||
"object_type": "post"
|
"object_type": "slug"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Generate tag slug",
|
||||||
|
"action_type": "generate",
|
||||||
|
"object_type": "slug"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Export database",
|
"name": "Export database",
|
||||||
@ -185,7 +190,7 @@ populateFixtures = function () {
|
|||||||
Role.forge({name: 'Editor'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
Role.forge({name: 'Editor'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||||
Permissions.forge().fetch().then(function (perms) {
|
Permissions.forge().fetch().then(function (perms) {
|
||||||
var editor_perm = _.map(perms.toJSON(), function (perm) {
|
var editor_perm = _.map(perms.toJSON(), function (perm) {
|
||||||
if (perm.object_type === 'post' || perm.object_type === 'user') {
|
if (perm.object_type === 'post' || perm.object_type === 'user' || perm.object_type === 'slug') {
|
||||||
return perm.id;
|
return perm.id;
|
||||||
}
|
}
|
||||||
if (perm.object_type === 'setting' &&
|
if (perm.object_type === 'setting' &&
|
||||||
@ -198,12 +203,14 @@ populateFixtures = function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// author gets access to post.add, post.slug, settings.browse, settings.read, users.browse and users.read
|
// author gets access to post.add, slug.generate, settings.browse, settings.read, users.browse and users.read
|
||||||
Role.forge({name: 'Author'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
Role.forge({name: 'Author'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||||
Permissions.forge().fetch().then(function (perms) {
|
Permissions.forge().fetch().then(function (perms) {
|
||||||
var author_perm = _.map(perms.toJSON(), function (perm) {
|
var author_perm = _.map(perms.toJSON(), function (perm) {
|
||||||
if (perm.object_type === 'post' &&
|
if (perm.object_type === 'post' && perm.action_type === 'add') {
|
||||||
(perm.action_type === 'add' || perm.action_type === 'slug')) {
|
return perm.id;
|
||||||
|
}
|
||||||
|
if (perm.object_type === 'slug' && perm.action_type === 'generate') {
|
||||||
return perm.id;
|
return perm.id;
|
||||||
}
|
}
|
||||||
if (perm.object_type === 'setting' &&
|
if (perm.object_type === 'setting' &&
|
||||||
@ -272,8 +279,10 @@ updateFixtures = function () {
|
|||||||
Role.forge({name: 'Author'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
Role.forge({name: 'Author'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||||
Permissions.forge().fetch().then(function (perms) {
|
Permissions.forge().fetch().then(function (perms) {
|
||||||
var author_perm = _.map(perms.toJSON(), function (perm) {
|
var author_perm = _.map(perms.toJSON(), function (perm) {
|
||||||
if (perm.object_type === 'post' &&
|
if (perm.object_type === 'post' && perm.action_type === 'add') {
|
||||||
(perm.action_type === 'add' || perm.action_type === 'slug')) {
|
return perm.id;
|
||||||
|
}
|
||||||
|
if (perm.object_type === 'slug' && perm.action_type === 'generate') {
|
||||||
return perm.id;
|
return perm.id;
|
||||||
}
|
}
|
||||||
if (perm.object_type === 'setting' &&
|
if (perm.object_type === 'setting' &&
|
||||||
|
@ -38,6 +38,8 @@ apiRoutes = function (server) {
|
|||||||
// ## Mail
|
// ## Mail
|
||||||
server.post('/ghost/api/v0.1/mail', api.http(api.mail.send));
|
server.post('/ghost/api/v0.1/mail', api.http(api.mail.send));
|
||||||
server.post('/ghost/api/v0.1/mail/test', api.http(api.mail.sendTest));
|
server.post('/ghost/api/v0.1/mail/test', api.http(api.mail.sendTest));
|
||||||
|
// #### Slugs
|
||||||
|
server.get('/ghost/api/v0.1/slugs/:type/:title', api.http(api.slugs.generate));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = apiRoutes;
|
module.exports = apiRoutes;
|
@ -5,8 +5,8 @@ var testUtils = require('../../utils'),
|
|||||||
// Stuff we are testing
|
// Stuff we are testing
|
||||||
permissions = require('../../../server/permissions'),
|
permissions = require('../../../server/permissions'),
|
||||||
DataGenerator = require('../../utils/fixtures/data-generator'),
|
DataGenerator = require('../../utils/fixtures/data-generator'),
|
||||||
dbAPI = require('../../../server/api/db');
|
dbAPI = require('../../../server/api/db'),
|
||||||
TagsAPI = require('../../../server/api/tags');
|
TagsAPI = require('../../../server/api/tags'),
|
||||||
PostAPI = require('../../../server/api/posts');
|
PostAPI = require('../../../server/api/posts');
|
||||||
|
|
||||||
describe('DB API', function () {
|
describe('DB API', function () {
|
||||||
|
66
core/test/integration/api/api_slugs_spec.js
Normal file
66
core/test/integration/api/api_slugs_spec.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
var testUtils = require('../../utils'),
|
||||||
|
should = require('should'),
|
||||||
|
|
||||||
|
permissions = require('../../../server/permissions'),
|
||||||
|
slugAPI = require('../../../server/api/slugs');
|
||||||
|
|
||||||
|
describe('Slug API', function () {
|
||||||
|
|
||||||
|
before(function (done) {
|
||||||
|
testUtils.clearData().then(function () {
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(function (done) {
|
||||||
|
testUtils.initData().then(function () {
|
||||||
|
return testUtils.insertDefaultFixtures();
|
||||||
|
}).then(function () {
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function (done) {
|
||||||
|
testUtils.clearData().then(function () {
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can generate post slug', function (done) {
|
||||||
|
permissions.init().then(function () {
|
||||||
|
return slugAPI.generate({ context: {user: 1}, type: 'post', title: 'A fancy Title'});
|
||||||
|
}).then(function (results) {
|
||||||
|
should.exist(results);
|
||||||
|
testUtils.API.checkResponse(results, 'slugs');
|
||||||
|
results.slugs.length.should.be.above(0);
|
||||||
|
testUtils.API.checkResponse(results.slugs[0], 'slug');
|
||||||
|
results.slugs[0].slug.should.equal('a-fancy-title');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can generate tag slug', function (done) {
|
||||||
|
permissions.init().then(function () {
|
||||||
|
return slugAPI.generate({ context: {user: 1}, type: 'tag', title: 'A fancy Title'});
|
||||||
|
}).then(function (results) {
|
||||||
|
should.exist(results);
|
||||||
|
testUtils.API.checkResponse(results, 'slugs');
|
||||||
|
results.slugs.length.should.be.above(0);
|
||||||
|
testUtils.API.checkResponse(results.slugs[0], 'slug');
|
||||||
|
results.slugs[0].slug.should.equal('a-fancy-title');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reject unknown type', function (done) {
|
||||||
|
permissions.init().then(function () {
|
||||||
|
return slugAPI.generate({ context: {user: 1}, type: 'unknown type', title: 'A fancy Title'});
|
||||||
|
}).then(function () {
|
||||||
|
done(new Error('Generate a slug for a unknown type is not rejected.'));
|
||||||
|
}, function (error) {
|
||||||
|
error.type.should.eql('BadRequestError');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -18,7 +18,9 @@ var url = require('url'),
|
|||||||
user: ['id', 'uuid', 'name', 'slug', 'email', 'image', 'cover', 'bio', 'website',
|
user: ['id', 'uuid', 'name', 'slug', 'email', 'image', 'cover', 'bio', 'website',
|
||||||
'location', 'accessibility', 'status', 'language', 'meta_title', 'meta_description', 'last_login',
|
'location', 'accessibility', 'status', 'language', 'meta_title', 'meta_description', 'last_login',
|
||||||
'created_at', 'created_by', 'updated_at', 'updated_by'],
|
'created_at', 'created_by', 'updated_at', 'updated_by'],
|
||||||
notification: ['type', 'message', 'status', 'id', 'dismissable', 'location']
|
notification: ['type', 'message', 'status', 'id', 'dismissable', 'location'],
|
||||||
|
slugs: ['slugs'],
|
||||||
|
slug: ['slug']
|
||||||
};
|
};
|
||||||
|
|
||||||
function getApiQuery(route) {
|
function getApiQuery(route) {
|
||||||
|
Loading…
Reference in New Issue
Block a user