From e2461a9314026d95d5baaea864c5282eed7c5504 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 3 Mar 2017 19:33:14 +0900 Subject: wip --- src/api/endpoints/drive/files.js | 82 --------------- src/api/endpoints/drive/files.ts | 74 ++++++++++++++ src/api/endpoints/drive/files/create.js | 63 ------------ src/api/endpoints/drive/files/create.ts | 57 +++++++++++ src/api/endpoints/drive/files/find.js | 49 --------- src/api/endpoints/drive/files/find.ts | 43 ++++++++ src/api/endpoints/drive/files/show.js | 44 -------- src/api/endpoints/drive/files/show.ts | 43 ++++++++ src/api/endpoints/drive/files/update.js | 101 ------------------ src/api/endpoints/drive/files/update.ts | 85 ++++++++++++++++ src/api/endpoints/drive/files/upload_from_url.js | 56 ---------- src/api/endpoints/drive/files/upload_from_url.ts | 48 +++++++++ src/api/endpoints/drive/folders.js | 79 --------------- src/api/endpoints/drive/folders.ts | 71 +++++++++++++ src/api/endpoints/drive/folders/create.js | 77 -------------- src/api/endpoints/drive/folders/create.ts | 61 +++++++++++ src/api/endpoints/drive/folders/find.js | 45 -------- src/api/endpoints/drive/folders/find.ts | 39 +++++++ src/api/endpoints/drive/folders/show.js | 41 -------- src/api/endpoints/drive/folders/show.ts | 39 +++++++ src/api/endpoints/drive/folders/update.js | 124 ----------------------- src/api/endpoints/drive/folders/update.ts | 105 +++++++++++++++++++ src/api/endpoints/drive/stream.js | 85 ---------------- src/api/endpoints/drive/stream.ts | 75 ++++++++++++++ src/api/endpoints/following/create.js | 96 ------------------ src/api/endpoints/following/create.ts | 89 ++++++++++++++++ src/api/endpoints/following/delete.js | 93 ----------------- src/api/endpoints/following/delete.ts | 86 ++++++++++++++++ 28 files changed, 915 insertions(+), 1035 deletions(-) delete mode 100644 src/api/endpoints/drive/files.js create mode 100644 src/api/endpoints/drive/files.ts delete mode 100644 src/api/endpoints/drive/files/create.js create mode 100644 src/api/endpoints/drive/files/create.ts delete mode 100644 src/api/endpoints/drive/files/find.js create mode 100644 src/api/endpoints/drive/files/find.ts delete mode 100644 src/api/endpoints/drive/files/show.js create mode 100644 src/api/endpoints/drive/files/show.ts delete mode 100644 src/api/endpoints/drive/files/update.js create mode 100644 src/api/endpoints/drive/files/update.ts delete mode 100644 src/api/endpoints/drive/files/upload_from_url.js create mode 100644 src/api/endpoints/drive/files/upload_from_url.ts delete mode 100644 src/api/endpoints/drive/folders.js create mode 100644 src/api/endpoints/drive/folders.ts delete mode 100644 src/api/endpoints/drive/folders/create.js create mode 100644 src/api/endpoints/drive/folders/create.ts delete mode 100644 src/api/endpoints/drive/folders/find.js create mode 100644 src/api/endpoints/drive/folders/find.ts delete mode 100644 src/api/endpoints/drive/folders/show.js create mode 100644 src/api/endpoints/drive/folders/show.ts delete mode 100644 src/api/endpoints/drive/folders/update.js create mode 100644 src/api/endpoints/drive/folders/update.ts delete mode 100644 src/api/endpoints/drive/stream.js create mode 100644 src/api/endpoints/drive/stream.ts delete mode 100644 src/api/endpoints/following/create.js create mode 100644 src/api/endpoints/following/create.ts delete mode 100644 src/api/endpoints/following/delete.js create mode 100644 src/api/endpoints/following/delete.ts (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/drive/files.js b/src/api/endpoints/drive/files.js deleted file mode 100644 index cbfe720266..0000000000 --- a/src/api/endpoints/drive/files.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFile from '../../models/drive-file'; -import serialize from '../../serializers/drive-file'; - -/** - * Get drive files - * - * @param {any} params - * @param {any} user - * @param {any} app - * @return {Promise} - */ -module.exports = (params, user, app) => - new Promise(async (res, rej) => -{ - // Get 'limit' parameter - let limit = params.limit; - if (limit !== undefined && limit !== null) { - limit = parseInt(limit, 10); - - // From 1 to 100 - if (!(1 <= limit && limit <= 100)) { - return rej('invalid limit range'); - } - } else { - limit = 10; - } - - const since = params.since_id || null; - const max = params.max_id || null; - - // Check if both of since_id and max_id is specified - if (since !== null && max !== null) { - return rej('cannot set since_id and max_id'); - } - - // Get 'folder_id' parameter - let folder = params.folder_id; - if (folder === undefined || folder === null) { - folder = null; - } else { - folder = new mongo.ObjectID(folder); - } - - // Construct query - const sort = { - _id: -1 - }; - const query = { - user_id: user._id, - folder_id: folder - }; - if (since !== null) { - sort._id = 1; - query._id = { - $gt: new mongo.ObjectID(since) - }; - } else if (max !== null) { - query._id = { - $lt: new mongo.ObjectID(max) - }; - } - - // Issue query - const files = await DriveFile - .find(query, { - fields: { - data: false - }, - limit: limit, - sort: sort - }); - - // Serialize - res(await Promise.all(files.map(async file => - await serialize(file)))); -}); diff --git a/src/api/endpoints/drive/files.ts b/src/api/endpoints/drive/files.ts new file mode 100644 index 0000000000..c1441c554b --- /dev/null +++ b/src/api/endpoints/drive/files.ts @@ -0,0 +1,74 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import DriveFile from '../../models/drive-file'; +import serialize from '../../serializers/drive-file'; + +/** + * Get drive files + * + * @param {any} params + * @param {any} user + * @param {any} app + * @return {Promise} + */ +module.exports = (params, user, app) => + new Promise(async (res, rej) => +{ + // Get 'limit' parameter + const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed(); + if (limitErr) return rej('invalid limit param'); + + // Get 'since_id' parameter + const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed(); + if (sinceIdErr) return rej('invalid since_id param'); + + // Get 'max_id' parameter + const [maxId, maxIdErr] = it(params.max_id).expect.id().qed(); + if (maxIdErr) return rej('invalid max_id param'); + + // Check if both of since_id and max_id is specified + if (sinceId !== null && maxId !== null) { + return rej('cannot set since_id and max_id'); + } + + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.nullable.id().default(null).qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + // Construct query + const sort = { + _id: -1 + }; + const query = { + user_id: user._id, + folder_id: folderId + } as any; + if (sinceId) { + sort._id = 1; + query._id = { + $gt: sinceId + }; + } else if (maxId) { + query._id = { + $lt: maxId + }; + } + + // Issue query + const files = await DriveFile + .find(query, { + fields: { + data: false + }, + limit: limit, + sort: sort + }); + + // Serialize + res(await Promise.all(files.map(async file => + await serialize(file)))); +}); diff --git a/src/api/endpoints/drive/files/create.js b/src/api/endpoints/drive/files/create.js deleted file mode 100644 index 9690b05cfd..0000000000 --- a/src/api/endpoints/drive/files/create.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as fs from 'fs'; -import * as mongo from 'mongodb'; -import File from '../../../models/drive-file'; -import { validateFileName } from '../../../models/drive-file'; -import User from '../../../models/user'; -import serialize from '../../../serializers/drive-file'; -import create from '../../../common/add-file-to-drive'; - -/** - * Create a file - * - * @param {any} file - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (file, params, user) => - new Promise(async (res, rej) => -{ - if (file == null) { - return rej('file is required'); - } - - const buffer = fs.readFileSync(file.path); - fs.unlink(file.path, (err) => { if (err) console.log(err) }); - - // Get 'name' parameter - let name = file.originalname; - if (name !== undefined && name !== null) { - name = name.trim(); - if (name.length === 0) { - name = null; - } else if (name === 'blob') { - name = null; - } else if (!validateFileName(name)) { - return rej('invalid name'); - } - } else { - name = null; - } - - // Get 'folder_id' parameter - let folder = params.folder_id; - if (folder === undefined || folder === null) { - folder = null; - } else { - folder = new mongo.ObjectID(folder); - } - - // Create file - const driveFile = await create(user, buffer, name, null, folder); - - // Serialize - const fileObj = await serialize(driveFile); - - // Response - res(fileObj); -}); diff --git a/src/api/endpoints/drive/files/create.ts b/src/api/endpoints/drive/files/create.ts new file mode 100644 index 0000000000..7efd149813 --- /dev/null +++ b/src/api/endpoints/drive/files/create.ts @@ -0,0 +1,57 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as fs from 'fs'; +import it from '../../../it'; +import { validateFileName } from '../../../models/drive-file'; +import serialize from '../../../serializers/drive-file'; +import create from '../../../common/add-file-to-drive'; + +/** + * Create a file + * + * @param {any} file + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (file, params, user) => + new Promise(async (res, rej) => +{ + if (file == null) { + return rej('file is required'); + } + + const buffer = fs.readFileSync(file.path); + fs.unlink(file.path, (err) => { if (err) console.log(err) }); + + // Get 'name' parameter + let name = file.originalname; + if (name !== undefined && name !== null) { + name = name.trim(); + if (name.length === 0) { + name = null; + } else if (name === 'blob') { + name = null; + } else if (!validateFileName(name)) { + return rej('invalid name'); + } + } else { + name = null; + } + + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.nullable.id().default(null).qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + // Create file + const driveFile = await create(user, buffer, name, null, folderId); + + // Serialize + const fileObj = await serialize(driveFile); + + // Response + res(fileObj); +}); diff --git a/src/api/endpoints/drive/files/find.js b/src/api/endpoints/drive/files/find.js deleted file mode 100644 index 358767c5ed..0000000000 --- a/src/api/endpoints/drive/files/find.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFile from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; - -/** - * Find a file(s) - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'name' parameter - const name = params.name; - if (name === undefined || name === null) { - return rej('name is required'); - } - - // Get 'folder_id' parameter - let folder = params.folder_id; - if (folder === undefined || folder === null) { - folder = null; - } else { - folder = new mongo.ObjectID(folder); - } - - // Issue query - const files = await DriveFile - .find({ - name: name, - user_id: user._id, - folder_id: folder - }, { - fields: { - data: false - } - }); - - // Serialize - res(await Promise.all(files.map(async file => - await serialize(file)))); -}); diff --git a/src/api/endpoints/drive/files/find.ts b/src/api/endpoints/drive/files/find.ts new file mode 100644 index 0000000000..393b8c5b98 --- /dev/null +++ b/src/api/endpoints/drive/files/find.ts @@ -0,0 +1,43 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import DriveFile from '../../../models/drive-file'; +import serialize from '../../../serializers/drive-file'; + +/** + * Find a file(s) + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'name' parameter + const [name, nameErr] = it(params.name).expect.string().required().qed(); + if (nameErr) return rej('invalid name param'); + + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.nullable.id().default(null).qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + // Issue query + const files = await DriveFile + .find({ + name: name, + user_id: user._id, + folder_id: folderId + }, { + fields: { + data: false + } + }); + + // Serialize + res(await Promise.all(files.map(async file => + await serialize(file)))); +}); diff --git a/src/api/endpoints/drive/files/show.js b/src/api/endpoints/drive/files/show.js deleted file mode 100644 index 5ae98a4a7c..0000000000 --- a/src/api/endpoints/drive/files/show.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFile from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; - -/** - * Show a file - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'file_id' parameter - const fileId = params.file_id; - if (fileId === undefined || fileId === null) { - return rej('file_id is required'); - } - - const file = await DriveFile - .findOne({ - _id: new mongo.ObjectID(fileId), - user_id: user._id - }, { - fields: { - data: false - } - }); - - if (file === null) { - return rej('file-not-found'); - } - - // Serialize - res(await serialize(file, { - detail: true - })); -}); diff --git a/src/api/endpoints/drive/files/show.ts b/src/api/endpoints/drive/files/show.ts new file mode 100644 index 0000000000..2024a56ca6 --- /dev/null +++ b/src/api/endpoints/drive/files/show.ts @@ -0,0 +1,43 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import DriveFile from '../../../models/drive-file'; +import serialize from '../../../serializers/drive-file'; + +/** + * Show a file + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'file_id' parameter + const [fileId, fileIdErr] = it(params.file_id).expect.id().required().qed(); + if (fileIdErr) return rej('invalid file_id param'); + + // Fetch file + const file = await DriveFile + .findOne({ + _id: fileId, + user_id: user._id + }, { + fields: { + data: false + } + }); + + if (file === null) { + return rej('file-not-found'); + } + + // Serialize + res(await serialize(file, { + detail: true + })); +}); diff --git a/src/api/endpoints/drive/files/update.js b/src/api/endpoints/drive/files/update.js deleted file mode 100644 index 8e2ff33e9d..0000000000 --- a/src/api/endpoints/drive/files/update.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFolder from '../../../models/drive-folder'; -import DriveFile from '../../../models/drive-file'; -import { validateFileName } from '../../../models/drive-file'; -import serialize from '../../../serializers/drive-file'; -import event from '../../../event'; - -/** - * Update a file - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'file_id' parameter - const fileId = params.file_id; - if (fileId === undefined || fileId === null) { - return rej('file_id is required'); - } - - // Validate id - if (!mongo.ObjectID.isValid(fileId)) { - return rej('incorrect file_id'); - } - - const file = await DriveFile - .findOne({ - _id: new mongo.ObjectID(fileId), - user_id: user._id - }, { - fields: { - data: false - } - }); - - if (file === null) { - return rej('file-not-found'); - } - - // Get 'name' parameter - let name = params.name; - if (name) { - name = name.trim(); - if (validateFileName(name)) { - file.name = name; - } else { - return rej('invalid file name'); - } - } - - // Get 'folder_id' parameter - let folderId = params.folder_id; - if (folderId !== undefined) { - if (folderId === null) { - file.folder_id = null; - } else { - // Validate id - if (!mongo.ObjectID.isValid(folderId)) { - return rej('incorrect folder_id'); - } - - folderId = new mongo.ObjectID(folderId); - - const folder = await DriveFolder - .findOne({ - _id: folderId, - user_id: user._id - }); - - if (folder === null) { - return rej('folder-not-found'); - } - - file.folder_id = folder._id; - } - } - - DriveFile.update(file._id, { - $set: { - name: file.name, - folder_id: file.folder_id - } - }); - - // Serialize - const fileObj = await serialize(file); - - // Response - res(fileObj); - - // Publish drive_file_updated event - event(user._id, 'drive_file_updated', fileObj); -}); diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts new file mode 100644 index 0000000000..595d501658 --- /dev/null +++ b/src/api/endpoints/drive/files/update.ts @@ -0,0 +1,85 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import DriveFolder from '../../../models/drive-folder'; +import DriveFile from '../../../models/drive-file'; +import { validateFileName } from '../../../models/drive-file'; +import serialize from '../../../serializers/drive-file'; +import event from '../../../event'; + +/** + * Update a file + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'file_id' parameter + const [fileId, fileIdErr] = it(params.file_id).expect.id().required().qed(); + if (fileIdErr) return rej('invalid file_id param'); + + // Fetch file + const file = await DriveFile + .findOne({ + _id: fileId, + user_id: user._id + }, { + fields: { + data: false + } + }); + + if (file === null) { + return rej('file-not-found'); + } + + // Get 'name' parameter + const [name, nameErr] = it(params.name).expect.string().validate(validateFileName).qed(); + if (nameErr) return rej('invalid name param'); + if (name) file.name = name; + + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.nullable.id().qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + if (folderId !== undefined) { + if (folderId === null) { + file.folder_id = null; + } else { + // Fetch folder + const folder = await DriveFolder + .findOne({ + _id: folderId, + user_id: user._id + }); + + if (folder === null) { + return rej('folder-not-found'); + } + + file.folder_id = folder._id; + } + } + + DriveFile.update(file._id, { + $set: { + name: file.name, + folder_id: file.folder_id + } + }); + + // Serialize + const fileObj = await serialize(file); + + // Response + res(fileObj); + + // Publish drive_file_updated event + event(user._id, 'drive_file_updated', fileObj); +}); diff --git a/src/api/endpoints/drive/files/upload_from_url.js b/src/api/endpoints/drive/files/upload_from_url.js deleted file mode 100644 index 3619a6f107..0000000000 --- a/src/api/endpoints/drive/files/upload_from_url.js +++ /dev/null @@ -1,56 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as URL from 'url'; -const download = require('download'); -import * as mongo from 'mongodb'; -import File from '../../../models/drive-file'; -import { validateFileName } from '../../../models/drive-file'; -import User from '../../../models/user'; -import serialize from '../../../serializers/drive-file'; -import create from '../../../common/add-file-to-drive'; - -/** - * Create a file from a URL - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'url' parameter - // TODO: Validate this url - const url = params.url; - if (url == null) { - return rej('url is required'); - } - - let name = URL.parse(url).pathname.split('/').pop(); - if (!validateFileName(name)) { - name = null; - } - - // Get 'folder_id' parameter - let folder = params.folder_id; - if (folder === undefined || folder === null) { - folder = null; - } else { - folder = new mongo.ObjectID(folder); - } - - // Download file - const data = await download(url); - - // Create file - const driveFile = await create(user, data, name, null, folder); - - // Serialize - const fileObj = await serialize(driveFile); - - // Response - res(fileObj); -}); diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts new file mode 100644 index 0000000000..b6f4789317 --- /dev/null +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -0,0 +1,48 @@ +'use strict'; + +/** + * Module dependencies + */ +import * as URL from 'url'; +const download = require('download'); +import it from '../../../it'; +import { validateFileName } from '../../../models/drive-file'; +import serialize from '../../../serializers/drive-file'; +import create from '../../../common/add-file-to-drive'; + +/** + * Create a file from a URL + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'url' parameter + // TODO: Validate this url + const [url, urlErr] = it(params.url).expect.string().required().qed(); + if (urlErr) return rej('invalid url param'); + + let name = URL.parse(url).pathname.split('/').pop(); + if (!validateFileName(name)) { + name = null; + } + + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.nullable.id().default(null).qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + // Download file + const data = await download(url); + + // Create file + const driveFile = await create(user, data, name, null, folderId); + + // Serialize + const fileObj = await serialize(driveFile); + + // Response + res(fileObj); +}); diff --git a/src/api/endpoints/drive/folders.js b/src/api/endpoints/drive/folders.js deleted file mode 100644 index 631d68769f..0000000000 --- a/src/api/endpoints/drive/folders.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFolder from '../../models/drive-folder'; -import serialize from '../../serializers/drive-folder'; - -/** - * Get drive folders - * - * @param {any} params - * @param {any} user - * @param {any} app - * @return {Promise} - */ -module.exports = (params, user, app) => - new Promise(async (res, rej) => -{ - // Get 'limit' parameter - let limit = params.limit; - if (limit !== undefined && limit !== null) { - limit = parseInt(limit, 10); - - // From 1 to 100 - if (!(1 <= limit && limit <= 100)) { - return rej('invalid limit range'); - } - } else { - limit = 10; - } - - const since = params.since_id || null; - const max = params.max_id || null; - - // Check if both of since_id and max_id is specified - if (since !== null && max !== null) { - return rej('cannot set since_id and max_id'); - } - - // Get 'folder_id' parameter - let folder = params.folder_id; - if (folder === undefined || folder === null) { - folder = null; - } else { - folder = new mongo.ObjectID(folder); - } - - // Construct query - const sort = { - _id: -1 - }; - const query = { - user_id: user._id, - parent_id: folder - }; - if (since !== null) { - sort._id = 1; - query._id = { - $gt: new mongo.ObjectID(since) - }; - } else if (max !== null) { - query._id = { - $lt: new mongo.ObjectID(max) - }; - } - - // Issue query - const folders = await DriveFolder - .find(query, { - limit: limit, - sort: sort - }); - - // Serialize - res(await Promise.all(folders.map(async folder => - await serialize(folder)))); -}); diff --git a/src/api/endpoints/drive/folders.ts b/src/api/endpoints/drive/folders.ts new file mode 100644 index 0000000000..3f4a5bac0e --- /dev/null +++ b/src/api/endpoints/drive/folders.ts @@ -0,0 +1,71 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import DriveFolder from '../../models/drive-folder'; +import serialize from '../../serializers/drive-folder'; + +/** + * Get drive folders + * + * @param {any} params + * @param {any} user + * @param {any} app + * @return {Promise} + */ +module.exports = (params, user, app) => + new Promise(async (res, rej) => +{ + // Get 'limit' parameter + const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed(); + if (limitErr) return rej('invalid limit param'); + + // Get 'since_id' parameter + const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed(); + if (sinceIdErr) return rej('invalid since_id param'); + + // Get 'max_id' parameter + const [maxId, maxIdErr] = it(params.max_id).expect.id().qed(); + if (maxIdErr) return rej('invalid max_id param'); + + // Check if both of since_id and max_id is specified + if (sinceId !== null && maxId !== null) { + return rej('cannot set since_id and max_id'); + } + + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.nullable.id().default(null).qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + // Construct query + const sort = { + _id: -1 + }; + const query = { + user_id: user._id, + parent_id: folderId + } as any; + if (sinceId) { + sort._id = 1; + query._id = { + $gt: sinceId + }; + } else if (maxId) { + query._id = { + $lt: maxId + }; + } + + // Issue query + const folders = await DriveFolder + .find(query, { + limit: limit, + sort: sort + }); + + // Serialize + res(await Promise.all(folders.map(async folder => + await serialize(folder)))); +}); diff --git a/src/api/endpoints/drive/folders/create.js b/src/api/endpoints/drive/folders/create.js deleted file mode 100644 index 9ba989c212..0000000000 --- a/src/api/endpoints/drive/folders/create.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName } from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-folder'; -import event from '../../../event'; - -/** - * Create drive folder - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'name' parameter - let name = params.name; - if (name !== undefined && name !== null) { - name = name.trim(); - if (name.length === 0) { - name = null; - } else if (!isValidFolderName(name)) { - return rej('invalid name'); - } - } else { - name = null; - } - - if (name == null) { - name = '無題のフォルダー'; - } - - // Get 'folder_id' parameter - let parentId = params.folder_id; - if (parentId === undefined || parentId === null) { - parentId = null; - } else { - parentId = new mongo.ObjectID(parentId); - } - - // If the parent folder is specified - let parent = null; - if (parentId !== null) { - parent = await DriveFolder - .findOne({ - _id: parentId, - user_id: user._id - }); - - if (parent === null) { - return reject('parent-not-found'); - } - } - - // Create folder - const folder = await DriveFolder.insert({ - created_at: new Date(), - name: name, - parent_id: parent !== null ? parent._id : null, - user_id: user._id - }); - - // Serialize - const folderObj = await serialize(folder); - - // Response - res(folderObj); - - // Publish drive_folder_created event - event(user._id, 'drive_folder_created', folderObj); -}); diff --git a/src/api/endpoints/drive/folders/create.ts b/src/api/endpoints/drive/folders/create.ts new file mode 100644 index 0000000000..d327572af7 --- /dev/null +++ b/src/api/endpoints/drive/folders/create.ts @@ -0,0 +1,61 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import DriveFolder from '../../../models/drive-folder'; +import { isValidFolderName } from '../../../models/drive-folder'; +import serialize from '../../../serializers/drive-folder'; +import event from '../../../event'; + +/** + * Create drive folder + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'name' parameter + const [name, nameErr] = it(params.name).expect.string().validate(isValidFolderName).default('無題のフォルダー').qed(); + if (nameErr) return rej('invalid name param'); + + // Get 'parent_id' parameter + const [parentId, parentIdErr] = it(params.parent_id).expect.nullable.id().default(null).qed(); + if (parentIdErr) return rej('invalid parent_id param'); + + // If the parent folder is specified + let parent = null; + if (parentId) { + // Fetch parent folder + parent = await DriveFolder + .findOne({ + _id: parentId, + user_id: user._id + }); + + if (parent === null) { + return rej('parent-not-found'); + } + } + + // Create folder + const folder = await DriveFolder.insert({ + created_at: new Date(), + name: name, + parent_id: parent !== null ? parent._id : null, + user_id: user._id + }); + + // Serialize + const folderObj = await serialize(folder); + + // Response + res(folderObj); + + // Publish drive_folder_created event + event(user._id, 'drive_folder_created', folderObj); +}); diff --git a/src/api/endpoints/drive/folders/find.js b/src/api/endpoints/drive/folders/find.js deleted file mode 100644 index 802d3a7909..0000000000 --- a/src/api/endpoints/drive/folders/find.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFolder from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-folder'; - -/** - * Find a folder(s) - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'name' parameter - const name = params.name; - if (name === undefined || name === null) { - return rej('name is required'); - } - - // Get 'parent_id' parameter - let parentId = params.parent_id; - if (parentId === undefined || parentId === null) { - parentId = null; - } else { - parentId = new mongo.ObjectID(parentId); - } - - // Issue query - const folders = await DriveFolder - .find({ - name: name, - user_id: user._id, - parent_id: parentId - }); - - // Serialize - res(await Promise.all(folders.map(async folder => - await serialize(folder)))); -}); diff --git a/src/api/endpoints/drive/folders/find.ts b/src/api/endpoints/drive/folders/find.ts new file mode 100644 index 0000000000..041e9ccb2a --- /dev/null +++ b/src/api/endpoints/drive/folders/find.ts @@ -0,0 +1,39 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import DriveFolder from '../../../models/drive-folder'; +import serialize from '../../../serializers/drive-folder'; + +/** + * Find a folder(s) + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'name' parameter + const [name, nameErr] = it(params.name).expect.string().required().qed(); + if (nameErr) return rej('invalid name param'); + + // Get 'parent_id' parameter + const [parentId, parentIdErr] = it(params.parent_id).expect.id().qed(); + if (parentIdErr) return rej('invalid parent_id param'); + + // Issue query + const folders = await DriveFolder + .find({ + name: name, + user_id: user._id, + parent_id: parentId + }); + + // Serialize + res(await Promise.all(folders.map(async folder => + await serialize(folder)))); +}); diff --git a/src/api/endpoints/drive/folders/show.js b/src/api/endpoints/drive/folders/show.js deleted file mode 100644 index 986d32cf60..0000000000 --- a/src/api/endpoints/drive/folders/show.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFolder from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-folder'; - -/** - * Show a folder - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'folder_id' parameter - const folderId = params.folder_id; - if (folderId === undefined || folderId === null) { - return rej('folder_id is required'); - } - - // Get folder - const folder = await DriveFolder - .findOne({ - _id: new mongo.ObjectID(folderId), - user_id: user._id - }); - - if (folder === null) { - return rej('folder-not-found'); - } - - // Serialize - res(await serialize(folder, { - detail: true - })); -}); diff --git a/src/api/endpoints/drive/folders/show.ts b/src/api/endpoints/drive/folders/show.ts new file mode 100644 index 0000000000..3b3ed41719 --- /dev/null +++ b/src/api/endpoints/drive/folders/show.ts @@ -0,0 +1,39 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import DriveFolder from '../../../models/drive-folder'; +import serialize from '../../../serializers/drive-folder'; + +/** + * Show a folder + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.id().required().qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + // Get folder + const folder = await DriveFolder + .findOne({ + _id: folderId, + user_id: user._id + }); + + if (folder === null) { + return rej('folder-not-found'); + } + + // Serialize + res(await serialize(folder, { + detail: true + })); +}); diff --git a/src/api/endpoints/drive/folders/update.js b/src/api/endpoints/drive/folders/update.js deleted file mode 100644 index 713e17b43e..0000000000 --- a/src/api/endpoints/drive/folders/update.js +++ /dev/null @@ -1,124 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName } from '../../../models/drive-folder'; -import serialize from '../../../serializers/drive-file'; -import event from '../../../event'; - -/** - * Update a folder - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'folder_id' parameter - const folderId = params.folder_id; - if (folderId === undefined || folderId === null) { - return rej('folder_id is required'); - } - - // Validate id - if (!mongo.ObjectID.isValid(folderId)) { - return rej('incorrect folder_id'); - } - - // Fetch folder - const folder = await DriveFolder - .findOne({ - _id: new mongo.ObjectID(folderId), - user_id: user._id - }); - - if (folder === null) { - return rej('folder-not-found'); - } - - // Get 'name' parameter - let name = params.name; - if (name) { - name = name.trim(); - if (isValidFolderName(name)) { - folder.name = name; - } else { - return rej('invalid folder name'); - } - } - - // Get 'parent_id' parameter - let parentId = params.parent_id; - if (parentId !== undefined) { - if (parentId === null) { - folder.parent_id = null; - } else { - // Validate id - if (!mongo.ObjectID.isValid(parentId)) { - return rej('incorrect parent_id'); - } - - parentId = new mongo.ObjectID(parentId); - - // Get parent folder - const parent = await DriveFolder - .findOne({ - _id: parentId, - user_id: user._id - }); - - if (parent === null) { - return rej('parent-folder-not-found'); - } - - // Check if the circular reference will occur - async function checkCircle(folderId) { - // Fetch folder - const folder2 = await DriveFolder.findOne({ - _id: folderId - }, { - _id: true, - parent_id: true - }); - - if (folder2._id.equals(folder._id)) { - return true; - } else if (folder2.parent_id) { - return await checkCircle(folder2.parent_id); - } else { - return false; - } - } - - if (parent.parent_id !== null) { - if (await checkCircle(parent.parent_id)) { - return rej('detected-circular-definition'); - } - } - - folder.parent_id = parent._id; - } - } - - // Update - DriveFolder.update(folder._id, { - $set: { - name: folder.name, - parent_id: folder.parent_id - } - }); - - // Serialize - const folderObj = await serialize(folder); - - // Response - res(folderObj); - - // Publish drive_folder_updated event - event(user._id, 'drive_folder_updated', folderObj); -}); diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts new file mode 100644 index 0000000000..81d414354c --- /dev/null +++ b/src/api/endpoints/drive/folders/update.ts @@ -0,0 +1,105 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../../it'; +import DriveFolder from '../../../models/drive-folder'; +import { isValidFolderName } from '../../../models/drive-folder'; +import serialize from '../../../serializers/drive-file'; +import event from '../../../event'; + +/** + * Update a folder + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'folder_id' parameter + const [folderId, folderIdErr] = it(params.folder_id).expect.id().required().qed(); + if (folderIdErr) return rej('invalid folder_id param'); + + // Fetch folder + const folder = await DriveFolder + .findOne({ + _id: folderId, + user_id: user._id + }); + + if (folder === null) { + return rej('folder-not-found'); + } + + // Get 'name' parameter + const [name, nameErr] = it(params.name).expect.string().validate(isValidFolderName).qed(); + if (nameErr) return rej('invalid name param'); + if (name) folder.name = name; + + // Get 'parent_id' parameter + const [parentId, parentIdErr] = it(params.parent_id).expect.nullable.id().qed(); + if (parentIdErr) return rej('invalid parent_id param'); + if (parentId !== undefined) { + if (parentId === null) { + folder.parent_id = null; + } else { + // Get parent folder + const parent = await DriveFolder + .findOne({ + _id: parentId, + user_id: user._id + }); + + if (parent === null) { + return rej('parent-folder-not-found'); + } + + // Check if the circular reference will occur + async function checkCircle(folderId) { + // Fetch folder + const folder2 = await DriveFolder.findOne({ + _id: folderId + }, { + _id: true, + parent_id: true + }); + + if (folder2._id.equals(folder._id)) { + return true; + } else if (folder2.parent_id) { + return await checkCircle(folder2.parent_id); + } else { + return false; + } + } + + if (parent.parent_id !== null) { + if (await checkCircle(parent.parent_id)) { + return rej('detected-circular-definition'); + } + } + + folder.parent_id = parent._id; + } + } + + // Update + DriveFolder.update(folder._id, { + $set: { + name: folder.name, + parent_id: folder.parent_id + } + }); + + // Serialize + const folderObj = await serialize(folder); + + // Response + res(folderObj); + + // Publish drive_folder_updated event + event(user._id, 'drive_folder_updated', folderObj); +}); diff --git a/src/api/endpoints/drive/stream.js b/src/api/endpoints/drive/stream.js deleted file mode 100644 index cd39261de8..0000000000 --- a/src/api/endpoints/drive/stream.js +++ /dev/null @@ -1,85 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import DriveFile from '../../models/drive-file'; -import serialize from '../../serializers/drive-file'; - -/** - * Get drive stream - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - // Get 'limit' parameter - let limit = params.limit; - if (limit !== undefined && limit !== null) { - limit = parseInt(limit, 10); - - // From 1 to 100 - if (!(1 <= limit && limit <= 100)) { - return rej('invalid limit range'); - } - } else { - limit = 10; - } - - const since = params.since_id || null; - const max = params.max_id || null; - - // Check if both of since_id and max_id is specified - if (since !== null && max !== null) { - return rej('cannot set since_id and max_id'); - } - - // Get 'type' parameter - let type = params.type; - if (type === undefined || type === null) { - type = null; - } else if (!/^[a-zA-Z\/\-\*]+$/.test(type)) { - return rej('invalid type format'); - } else { - type = new RegExp(`^${type.replace(/\*/g, '.+?')}$`); - } - - // Construct query - const sort = { - _id: -1 - }; - const query = { - user_id: user._id - }; - if (since !== null) { - sort._id = 1; - query._id = { - $gt: new mongo.ObjectID(since) - }; - } else if (max !== null) { - query._id = { - $lt: new mongo.ObjectID(max) - }; - } - if (type !== null) { - query.type = type; - } - - // Issue query - const files = await DriveFile - .find(query, { - fields: { - data: false - }, - limit: limit, - sort: sort - }); - - // Serialize - res(await Promise.all(files.map(async file => - await serialize(file)))); -}); diff --git a/src/api/endpoints/drive/stream.ts b/src/api/endpoints/drive/stream.ts new file mode 100644 index 0000000000..6ede044f58 --- /dev/null +++ b/src/api/endpoints/drive/stream.ts @@ -0,0 +1,75 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import DriveFile from '../../models/drive-file'; +import serialize from '../../serializers/drive-file'; + +/** + * Get drive stream + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + // Get 'limit' parameter + const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed(); + if (limitErr) return rej('invalid limit param'); + + // Get 'since_id' parameter + const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed(); + if (sinceIdErr) return rej('invalid since_id param'); + + // Get 'max_id' parameter + const [maxId, maxIdErr] = it(params.max_id).expect.id().qed(); + if (maxIdErr) return rej('invalid max_id param'); + + // Check if both of since_id and max_id is specified + if (sinceId !== null && maxId !== null) { + return rej('cannot set since_id and max_id'); + } + + // Get 'type' parameter + const [type, typeErr] = it(params.type).expect.string().match(/^[a-zA-Z\/\-\*]+$/).qed(); + if (typeErr) return rej('invalid type param'); + + // Construct query + const sort = { + _id: -1 + }; + const query = { + user_id: user._id + } as any; + if (sinceId) { + sort._id = 1; + query._id = { + $gt: sinceId + }; + } else if (maxId) { + query._id = { + $lt: maxId + }; + } + if (type !== null) { + query.type = new RegExp(`^${type.replace(/\*/g, '.+?')}$`); + } + + // Issue query + const files = await DriveFile + .find(query, { + fields: { + data: false + }, + limit: limit, + sort: sort + }); + + // Serialize + res(await Promise.all(files.map(async file => + await serialize(file)))); +}); diff --git a/src/api/endpoints/following/create.js b/src/api/endpoints/following/create.js deleted file mode 100644 index 46ff77ddf1..0000000000 --- a/src/api/endpoints/following/create.js +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import User from '../../models/user'; -import Following from '../../models/following'; -import notify from '../../common/notify'; -import event from '../../event'; -import serializeUser from '../../serializers/user'; - -/** - * Follow a user - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - const follower = user; - - // Get 'user_id' parameter - let userId = params.user_id; - if (userId === undefined || userId === null) { - return rej('user_id is required'); - } - - // Validate id - if (!mongo.ObjectID.isValid(userId)) { - return rej('incorrect user_id'); - } - - // 自分自身 - if (user._id.equals(userId)) { - return rej('followee is yourself'); - } - - // Get followee - const followee = await User.findOne({ - _id: new mongo.ObjectID(userId) - }, { - fields: { - data: false, - profile: false - } - }); - - if (followee === null) { - return rej('user not found'); - } - - // Check if already following - const exist = await Following.findOne({ - follower_id: follower._id, - followee_id: followee._id, - deleted_at: { $exists: false } - }); - - if (exist !== null) { - return rej('already following'); - } - - // Create following - await Following.insert({ - created_at: new Date(), - follower_id: follower._id, - followee_id: followee._id - }); - - // Send response - res(); - - // Increment following count - User.update(follower._id, { - $inc: { - following_count: 1 - } - }); - - // Increment followers count - User.update({ _id: followee._id }, { - $inc: { - followers_count: 1 - } - }); - - // Publish follow event - event(follower._id, 'follow', await serializeUser(followee, follower)); - event(followee._id, 'followed', await serializeUser(follower, followee)); - - // Notify - notify(followee._id, follower._id, 'follow'); -}); diff --git a/src/api/endpoints/following/create.ts b/src/api/endpoints/following/create.ts new file mode 100644 index 0000000000..0edc122b94 --- /dev/null +++ b/src/api/endpoints/following/create.ts @@ -0,0 +1,89 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import User from '../../models/user'; +import Following from '../../models/following'; +import notify from '../../common/notify'; +import event from '../../event'; +import serializeUser from '../../serializers/user'; + +/** + * Follow a user + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + const follower = user; + + // Get 'user_id' parameter + const [userId, userIdErr] = it(params.user_id, 'id', true); + if (userIdErr) return rej('invalid user_id param'); + + // 自分自身 + if (user._id.equals(userId)) { + return rej('followee is yourself'); + } + + // Get followee + const followee = await User.findOne({ + _id: userId + }, { + fields: { + data: false, + profile: false + } + }); + + if (followee === null) { + return rej('user not found'); + } + + // Check if already following + const exist = await Following.findOne({ + follower_id: follower._id, + followee_id: followee._id, + deleted_at: { $exists: false } + }); + + if (exist !== null) { + return rej('already following'); + } + + // Create following + await Following.insert({ + created_at: new Date(), + follower_id: follower._id, + followee_id: followee._id + }); + + // Send response + res(); + + // Increment following count + User.update(follower._id, { + $inc: { + following_count: 1 + } + }); + + // Increment followers count + User.update({ _id: followee._id }, { + $inc: { + followers_count: 1 + } + }); + + // Publish follow event + event(follower._id, 'follow', await serializeUser(followee, follower)); + event(followee._id, 'followed', await serializeUser(follower, followee)); + + // Notify + notify(followee._id, follower._id, 'follow'); +}); diff --git a/src/api/endpoints/following/delete.js b/src/api/endpoints/following/delete.js deleted file mode 100644 index 1085013d03..0000000000 --- a/src/api/endpoints/following/delete.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ -import * as mongo from 'mongodb'; -import User from '../../models/user'; -import Following from '../../models/following'; -import event from '../../event'; -import serializeUser from '../../serializers/user'; - -/** - * Unfollow a user - * - * @param {any} params - * @param {any} user - * @return {Promise} - */ -module.exports = (params, user) => - new Promise(async (res, rej) => -{ - const follower = user; - - // Get 'user_id' parameter - let userId = params.user_id; - if (userId === undefined || userId === null) { - return rej('user_id is required'); - } - - // Validate id - if (!mongo.ObjectID.isValid(userId)) { - return rej('incorrect user_id'); - } - - // Check if the followee is yourself - if (user._id.equals(userId)) { - return rej('followee is yourself'); - } - - // Get followee - const followee = await User.findOne({ - _id: new mongo.ObjectID(userId) - }, { - fields: { - data: false, - profile: false - } - }); - - if (followee === null) { - return rej('user not found'); - } - - // Check not following - const exist = await Following.findOne({ - follower_id: follower._id, - followee_id: followee._id, - deleted_at: { $exists: false } - }); - - if (exist === null) { - return rej('already not following'); - } - - // Delete following - await Following.update({ - _id: exist._id - }, { - $set: { - deleted_at: new Date() - } - }); - - // Send response - res(); - - // Decrement following count - User.update({ _id: follower._id }, { - $inc: { - following_count: -1 - } - }); - - // Decrement followers count - User.update({ _id: followee._id }, { - $inc: { - followers_count: -1 - } - }); - - // Publish follow event - event(follower._id, 'unfollow', await serializeUser(followee, follower)); -}); diff --git a/src/api/endpoints/following/delete.ts b/src/api/endpoints/following/delete.ts new file mode 100644 index 0000000000..7f0e908068 --- /dev/null +++ b/src/api/endpoints/following/delete.ts @@ -0,0 +1,86 @@ +'use strict'; + +/** + * Module dependencies + */ +import it from '../../it'; +import User from '../../models/user'; +import Following from '../../models/following'; +import event from '../../event'; +import serializeUser from '../../serializers/user'; + +/** + * Unfollow a user + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => + new Promise(async (res, rej) => +{ + const follower = user; + + // Get 'user_id' parameter + const [userId, userIdErr] = it(params.user_id, 'id', true); + if (userIdErr) return rej('invalid user_id param'); + + // Check if the followee is yourself + if (user._id.equals(userId)) { + return rej('followee is yourself'); + } + + // Get followee + const followee = await User.findOne({ + _id: userId + }, { + fields: { + data: false, + profile: false + } + }); + + if (followee === null) { + return rej('user not found'); + } + + // Check not following + const exist = await Following.findOne({ + follower_id: follower._id, + followee_id: followee._id, + deleted_at: { $exists: false } + }); + + if (exist === null) { + return rej('already not following'); + } + + // Delete following + await Following.update({ + _id: exist._id + }, { + $set: { + deleted_at: new Date() + } + }); + + // Send response + res(); + + // Decrement following count + User.update({ _id: follower._id }, { + $inc: { + following_count: -1 + } + }); + + // Decrement followers count + User.update({ _id: followee._id }, { + $inc: { + followers_count: -1 + } + }); + + // Publish follow event + event(follower._id, 'unfollow', await serializeUser(followee, follower)); +}); -- cgit v1.2.3-freya