feat(api): closes #9123 category and topic routes migrated to Write API

v1.18.x
Julian Lam 4 years ago
parent 77a5adb616
commit edb8da1ef9

@ -1,73 +1,85 @@
CategoryObject: CategoryObject:
type: object allOf:
properties: - type: object
cid: properties:
type: number cid:
description: A category identifier assigned upon category creation (this value cannot be changed) type: number
name: description: A category identifier assigned upon category creation (this value cannot be changed)
type: string name:
description: The category's name/title type: string
description: description: The category's name/title
type: string description:
description: A variable-length description of the category (usually displayed underneath the category name) type: string
descriptionParsed: description: A variable-length description of the category (usually displayed underneath the category name)
type: string descriptionParsed:
description: A variable-length description of the category (usually displayed underneath the category name). Unlike `description`, this value here will have been run through any parsers installed on the forum (e.g. Markdown) type: string
icon: description: A variable-length description of the category (usually displayed underneath the category name). Unlike `description`, this value here will have been run through any parsers installed on the forum (e.g. Markdown)
type: string icon:
description: A FontAwesome icon string type: string
example: fa-comments-o description: A FontAwesome icon string
bgColor: example: fa-comments-o
type: string bgColor:
description: Theme-related, a six-character hexadecimal string representing the background colour of the category type: string
color: description: Theme-related, a six-character hexadecimal string representing the background colour of the category
type: string color:
description: Theme-related, a six-character hexadecimal string representing the foreground/text colour of the category type: string
slug: description: Theme-related, a six-character hexadecimal string representing the foreground/text colour of the category
type: string slug:
description: An URL-safe variant of the category title. This value is automatically generated. type: string
readOnly: true description: An URL-safe variant of the category title. This value is automatically generated.
parentCid: readOnly: true
type: number parentCid:
description: The category identifier for the category that is the immediate ancestor of the current category type: number
topic_count: description: The category identifier for the category that is the immediate ancestor of the current category
type: number topic_count:
description: The number of topics in the category type: number
post_count: description: The number of topics in the category
type: number post_count:
description: The number of posts in the category type: number
disabled: description: The number of posts in the category
type: number disabled:
description: Whether or not this category is disabled. type: number
order: description: Whether or not this category is disabled.
type: number order:
description: A number representing the category's place in the hierarchy type: number
link: description: A number representing the category's place in the hierarchy
type: string link:
description: If set, attempting to access the forum will go to this external link instead (theme-specific) type: string
numRecentReplies: description: If set, attempting to access the forum will go to this external link instead (theme-specific)
type: number numRecentReplies:
description: The number of posts to render in the API response (this is mostly used at the theme level) type: number
class: description: The number of posts to render in the API response (this is mostly used at the theme level)
type: string class:
description: Values that are appended to the `class` attribute of the category's parent/root element type: string
imageClass: description: Values that are appended to the `class` attribute of the category's parent/root element
type: string imageClass:
enum: [auto, cover, contain] type: string
description: The `background-position` of the category background image, if one is set enum: [auto, cover, contain]
isSection: description: The `background-position` of the category background image, if one is set
type: number isSection:
minTags: type: number
type: number minTags:
description: Minimum tags per topic in this category type: number
maxTags: description: Minimum tags per topic in this category
type: number maxTags:
description: Maximum tags per topic in this category type: number
postQueue: description: Maximum tags per topic in this category
type: number postQueue:
totalPostCount: type: number
type: number totalPostCount:
description: The number of posts in the category type: number
totalTopicCount: description: The number of posts in the category
type: number totalTopicCount:
description: The number of topics in the category type: number
description: The number of topics in the category
- type: object
description: Optional properties that may or may not be present (except for `cid`, which is always present, and is only here as a hack to pass validation)
properties:
cid:
type: number
description: A category identifier
backgroundImage:
type: string
description: Relative URL to the category's background image
required:
- cid

@ -3,19 +3,8 @@ TopicObject:
- $ref: '#/TopicObjectSlim' - $ref: '#/TopicObjectSlim'
- type: object - type: object
properties: properties:
title:
type: string
slug:
type: string
lastposttime: lastposttime:
type: number type: number
teaserPid:
oneOf:
- type: number
- type: string
nullable: true
titleRaw:
type: string
thumbs: thumbs:
type: array type: array
items: items:
@ -218,6 +207,10 @@ TopicObjectSlim:
cid: cid:
type: number type: number
description: A category identifier description: A category identifier
title:
type: string
slug:
type: string
mainPid: mainPid:
type: number type: number
description: The post id of the first post in this topic (also called the "original post") description: The post id of the first post in this topic (also called the "original post")
@ -231,6 +224,8 @@ TopicObjectSlim:
type: number type: number
deleterUid: deleterUid:
type: number type: number
titleRaw:
type: string
locked: locked:
type: number type: number
pinned: pinned:
@ -258,4 +253,9 @@ TopicObjectSlim:
downvotes: downvotes:
type: number type: number
votes: votes:
type: number type: number
teaserPid:
oneOf:
- type: number
- type: string
nullable: true

@ -1,6 +1,31 @@
get:
tags:
- categories
summary: get a category
description: This operation retrieves a category's data
parameters:
- in: path
name: cid
schema:
type: string
required: true
description: a valid category id
example: 2
responses:
'200':
description: Category successfully retrieved
content:
application/json:
schema:
type: object
properties:
status:
$ref: ../../components/schemas/Status.yaml#/Status
response:
$ref: ../../components/schemas/CategoryObject.yaml#/CategoryObject
put: put:
tags: tags:
- topics - categories
summary: update a category summary: update a category
description: This operation updates an existing category. description: This operation updates an existing category.
parameters: parameters:
@ -42,7 +67,7 @@ put:
type: string type: string
delete: delete:
tags: tags:
- topics - categories
summary: delete a category summary: delete a category
description: This operation deletes and purges a category and all of its topics and posts (careful, there is no confirmation!) description: This operation deletes and purges a category and all of its topics and posts (careful, there is no confirmation!)
parameters: parameters:

@ -1,3 +1,69 @@
get:
tags:
- posts
summary: get a post
description: This operation retrieves a post's data
parameters:
- in: path
name: pid
schema:
type: string
required: true
description: a valid post id
example: 1
responses:
'200':
description: Post successfully retrieved
content:
application/json:
schema:
type: object
properties:
status:
$ref: ../../components/schemas/Status.yaml#/Status
response:
type: object
properties:
pid:
type: number
uid:
type: number
description: A user identifier
tid:
type: number
description: A topic identifier
content:
type: string
timestamp:
type: number
flagId:
type: number
deleted:
type: number
upvotes:
type: number
downvotes:
type: number
deleterUid:
type: number
edited:
type: number
replies:
type: number
bookmarks:
type: number
votes:
type: number
timestampISO:
type: string
description: An ISO 8601 formatted date string (complementing `timestamp`)
editedISO:
type: string
description: An ISO 8601 formatted date string (complementing `timestamp`)
upvoted:
type: boolean
downvoted:
type: boolean
put: put:
tags: tags:
- posts - posts

@ -1,3 +1,28 @@
get:
tags:
- topics
summary: get a topic
description: This operation retrieves a topic's data
parameters:
- in: path
name: tid
schema:
type: string
required: true
description: a valid topic id
example: 1
responses:
'200':
description: Topic successfully retrieved
content:
application/json:
schema:
type: object
properties:
status:
$ref: ../../components/schemas/Status.yaml#/Status
response:
$ref: ../../components/schemas/TopicObject.yaml#/TopicObjectSlim
post: post:
tags: tags:
- topics - topics

@ -15,6 +15,10 @@ const hasAdminPrivilege = async (uid) => {
} }
}; };
Categories.get = async (req, res) => {
helpers.formatApiResponse(200, res, await api.categories.get(req, req.params));
};
Categories.create = async (req, res) => { Categories.create = async (req, res) => {
await hasAdminPrivilege(req.uid); await hasAdminPrivilege(req.uid);

@ -12,6 +12,10 @@ const uploadsController = require('../uploads');
const Topics = module.exports; const Topics = module.exports;
Topics.get = async (req, res) => {
helpers.formatApiResponse(200, res, await api.topics.get(req, req.params));
};
Topics.create = async (req, res) => { Topics.create = async (req, res) => {
const payload = await api.topics.create(req, req.body); const payload = await api.topics.create(req, req.body);
if (payload.queued) { if (payload.queued) {

@ -11,6 +11,7 @@ module.exports = function () {
const middlewares = [middleware.authenticate]; const middlewares = [middleware.authenticate];
setupApiRoute(router, 'post', '/', [...middlewares, middleware.checkRequired.bind(null, ['name'])], controllers.write.categories.create); setupApiRoute(router, 'post', '/', [...middlewares, middleware.checkRequired.bind(null, ['name'])], controllers.write.categories.create);
setupApiRoute(router, 'get', '/:cid', [middleware.authenticateOrGuest], controllers.write.categories.get);
setupApiRoute(router, 'put', '/:cid', [...middlewares], controllers.write.categories.update); setupApiRoute(router, 'put', '/:cid', [...middlewares], controllers.write.categories.update);
setupApiRoute(router, 'delete', '/:cid', [...middlewares], controllers.write.categories.delete); setupApiRoute(router, 'delete', '/:cid', [...middlewares], controllers.write.categories.delete);

@ -14,6 +14,7 @@ module.exports = function () {
var multipartMiddleware = multipart(); var multipartMiddleware = multipart();
setupApiRoute(router, 'post', '/', [middleware.authenticateOrGuest, middleware.checkRequired.bind(null, ['cid', 'title', 'content'])], controllers.write.topics.create); setupApiRoute(router, 'post', '/', [middleware.authenticateOrGuest, middleware.checkRequired.bind(null, ['cid', 'title', 'content'])], controllers.write.topics.create);
setupApiRoute(router, 'get', '/:tid', [middleware.authenticateOrGuest], controllers.write.topics.get);
setupApiRoute(router, 'post', '/:tid', [middleware.authenticateOrGuest, middleware.checkRequired.bind(null, ['content']), middleware.assert.topic], controllers.write.topics.reply); setupApiRoute(router, 'post', '/:tid', [middleware.authenticateOrGuest, middleware.checkRequired.bind(null, ['content']), middleware.assert.topic], controllers.write.topics.reply);
setupApiRoute(router, 'delete', '/:tid', [...middlewares], controllers.write.topics.purge); setupApiRoute(router, 'delete', '/:tid', [...middlewares], controllers.write.topics.purge);

Loading…
Cancel
Save