refactor(api): post move to write API

v1.18.x
Julian Lam 4 years ago
parent 0fa4c11ea6
commit 966c4117ec

@ -104,6 +104,8 @@ paths:
$ref: 'write/posts/pid.yaml'
/posts/{pid}/state:
$ref: 'write/posts/pid/state.yaml'
/posts/{pid}/move:
$ref: 'write/posts/pid/move.yaml'
/posts/{pid}/vote:
$ref: 'write/posts/pid/vote.yaml'
/posts/{pid}/bookmark:

@ -0,0 +1,36 @@
put:
tags:
- posts
summary: move a post
description: This operation moves a post to a different topic.
parameters:
- in: path
name: pid
schema:
type: number
required: true
description: a valid post id
example: 5
requestBody:
content:
application/json:
schema:
type: object
properties:
tid:
type: number
description: a valid topic id
example: 4
responses:
'200':
description: Post successfully moved
content:
application/json:
schema:
type: object
properties:
status:
$ref: ../../../components/schemas/Status.yaml#/Status
response:
type: object
properties: {}

@ -2,8 +2,8 @@
define('forum/topic/move-post', [
'components', 'postSelect', 'translator', 'alerts',
], function (components, postSelect, translator, alerts) {
'components', 'postSelect', 'translator', 'alerts', 'api',
], function (components, postSelect, translator, alerts, api) {
var MovePost = {};
var moveModal;
@ -100,10 +100,10 @@ define('forum/topic/move-post', [
if (!ajaxify.data.template.topic || !data.tid) {
return;
}
socket.emit('posts.movePosts', { pids: data.pids, tid: data.tid }, function (err) {
if (err) {
return app.alertError(err.message);
}
Promise.all(data.pids.map(pid => api.put(`/posts/${pid}/move`, {
tid: data.tid,
}))).then(() => {
data.pids.forEach(function (pid) {
components.get('post', 'pid', pid).fadeOut(500, function () {
$(this).remove();
@ -111,7 +111,7 @@ define('forum/topic/move-post', [
});
closeMoveModal();
});
}).catch(app.alertError);
}
function closeMoveModal() {

@ -13,6 +13,7 @@ const events = require('../events');
const privileges = require('../privileges');
const apiHelpers = require('./helpers');
const websockets = require('../socket.io');
const socketHelpers = require('../socket.io/helpers');
const postsAPI = module.exports;
@ -195,6 +196,27 @@ async function isMainAndLastPost(pid) {
};
}
postsAPI.move = async function (caller, data) {
const canMove = await Promise.all([
privileges.topics.isAdminOrMod(data.tid, caller.uid),
privileges.posts.canMove(data.pid, caller.uid),
]);
if (!canMove.every(Boolean)) {
throw new Error('[[error:no-privileges]]');
}
await topics.movePostToTopic(caller.uid, data.pid, data.tid);
const [postDeleted, topicDeleted] = await Promise.all([
posts.getPostField(data.pid, 'deleted'),
topics.getTopicField(data.tid, 'deleted'),
]);
if (!postDeleted && !topicDeleted) {
socketHelpers.sendNotificationToPostOwner(data.pid, caller.uid, 'move', 'notifications:moved_your_post');
}
};
postsAPI.upvote = async function (caller, data) {
return await apiHelpers.postCommand(caller, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data);
};

@ -38,6 +38,14 @@ Posts.delete = async (req, res) => {
helpers.formatApiResponse(200, res);
};
Posts.move = async (req, res) => {
await api.posts.move(req, {
pid: req.params.pid,
tid: req.body.tid,
});
helpers.formatApiResponse(200, res);
};
async function mock(req) {
const tid = await posts.getPostField(req.params.pid, 'tid');
return { pid: req.params.pid, room_id: `topic_${tid}` };

@ -46,7 +46,7 @@ Assert.topic = helpers.try(async (req, res, next) => {
Assert.post = helpers.try(async (req, res, next) => {
if (!await posts.exists(req.params.pid)) {
return controllerHelpers.formatApiResponse(404, res, new Error('[[error:no-topic]]'));
return controllerHelpers.formatApiResponse(404, res, new Error('[[error:no-post]]'));
}
next();

@ -18,6 +18,8 @@ module.exports = function () {
setupApiRoute(router, 'put', '/:pid/state', [...middlewares, middleware.assert.post], controllers.write.posts.restore);
setupApiRoute(router, 'delete', '/:pid/state', [...middlewares, middleware.assert.post], controllers.write.posts.delete);
setupApiRoute(router, 'put', '/:pid/move', [...middlewares, middleware.assert.post, middleware.checkRequired.bind(null, ['tid'])], controllers.write.posts.move);
setupApiRoute(router, 'put', '/:pid/vote', [...middlewares, middleware.checkRequired.bind(null, ['delta']), middleware.assert.post], controllers.write.posts.vote);
setupApiRoute(router, 'delete', '/:pid/vote', [...middlewares, middleware.assert.post], controllers.write.posts.unvote);

@ -1,45 +1,19 @@
'use strict';
const privileges = require('../../privileges');
const topics = require('../../topics');
const posts = require('../../posts');
const socketHelpers = require('../helpers');
const api = require('../../api');
const sockets = require('..');
module.exports = function (SocketPosts) {
SocketPosts.movePost = async function (socket, data) {
await SocketPosts.movePosts(socket, { pids: [data.pid], tid: data.tid });
sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/move');
await api.posts.move(socket, data);
};
SocketPosts.movePosts = async function (socket, data) {
if (!socket.uid) {
throw new Error('[[error:not-logged-in]]');
}
if (!data || !Array.isArray(data.pids) || !data.tid) {
throw new Error('[[error:invalid-data]]');
}
const canMove = await privileges.topics.isAdminOrMod(data.tid, socket.uid);
if (!canMove) {
throw new Error('[[error:no-privileges]]');
}
for (const pid of data.pids) {
/* eslint-disable no-await-in-loop */
const canMove = await privileges.posts.canMove(pid, socket.uid);
if (!canMove) {
throw new Error('[[error:no-privileges]]');
}
await topics.movePostToTopic(socket.uid, pid, data.tid);
const [postDeleted, topicDeleted] = await Promise.all([
posts.getPostField(pid, 'deleted'),
topics.getTopicField(data.tid, 'deleted'),
]);
if (!postDeleted && !topicDeleted) {
socketHelpers.sendNotificationToPostOwner(pid, socket.uid, 'move', 'notifications:moved_your_post');
}
}
sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/move');
await Promise.all(data.pids.map(async pid => api.posts.move(socket, {
tid: data.tid,
pid,
})));
};
};

@ -135,6 +135,12 @@ describe('API', async () => {
title: 'Test Topic 2',
content: 'Test topic 2 content',
});
await topics.post({
uid: unprivUid,
cid: testCategory.cid,
title: 'Test Topic 3',
content: 'Test topic 3 content',
});
// Create a sample flag
await flags.create('post', 1, unprivUid, 'sample reasons', Date.now());

Loading…
Cancel
Save