commit
						3ce6601f04
					
				
					 79 changed files with 1381 additions and 1338 deletions
				
			
		| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
import Like from '../../../models/like';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id).expect.id().required().qed();
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
import Like from '../../../models/like';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id).expect.id().required().qed();
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -16,14 +16,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id).expect.id().required().qed();
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -16,14 +16,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id).expect.id().required().qed();
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import User from '../../../models/user';
 | 
			
		||||
import Following from '../../../models/following';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	const userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null) {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id).expect.id().required().qed();
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
	const user = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import User from '../../../models/user';
 | 
			
		||||
import Following from '../../../models/following';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	const userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null) {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id).expect.id().required().qed();
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
	const user = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import User from '../../../models/user';
 | 
			
		||||
import Like from '../../../models/like';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	const userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null) {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id).expect.id().required().qed();
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
	const user = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import User from '../../../models/user';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	const userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null) {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id).expect.id().required().qed();
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
	const user = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,9 @@
 | 
			
		|||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import rndstr from 'rndstr';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import App from '../../models/app';
 | 
			
		||||
import { isValidNameId } from '../../models/app';
 | 
			
		||||
import serialize from '../../serializers/app';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -71,41 +73,25 @@ module.exports = async (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'name_id' parameter
 | 
			
		||||
	const nameId = params.name_id;
 | 
			
		||||
	if (nameId == null) {
 | 
			
		||||
		return rej('name_id is required');
 | 
			
		||||
	} else if (typeof nameId != 'string') {
 | 
			
		||||
		return rej('name_id must be a string');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Validate name_id
 | 
			
		||||
	if (!/^[a-zA-Z0-9\-]{3,30}$/.test(nameId)) {
 | 
			
		||||
		return rej('invalid name_id');
 | 
			
		||||
	}
 | 
			
		||||
	const [nameId, nameIdErr] = it(params.name_id).expect.string().required().validate(isValidNameId).qed();
 | 
			
		||||
	if (nameIdErr) return rej('invalid name_id param');
 | 
			
		||||
 | 
			
		||||
	// Get 'name' parameter
 | 
			
		||||
	const name = params.name;
 | 
			
		||||
	if (name == null || name == '') {
 | 
			
		||||
		return rej('name is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [name, nameErr] = it(params.name).expect.string().required().qed();
 | 
			
		||||
	if (nameErr) return rej('invalid name param');
 | 
			
		||||
 | 
			
		||||
	// Get 'description' parameter
 | 
			
		||||
	const description = params.description;
 | 
			
		||||
	if (description == null || description == '') {
 | 
			
		||||
		return rej('description is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [description, descriptionErr] = it(params.description).expect.string().required().qed();
 | 
			
		||||
	if (descriptionErr) return rej('invalid description param');
 | 
			
		||||
 | 
			
		||||
	// Get 'permission' parameter
 | 
			
		||||
	const permission = params.permission;
 | 
			
		||||
	if (permission == null || permission == '') {
 | 
			
		||||
		return rej('permission is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [permission, permissionErr] = it(params.permission).expect.array().unique().allString().required().qed();
 | 
			
		||||
	if (permissionErr) return rej('invalid permission param');
 | 
			
		||||
 | 
			
		||||
	// Get 'callback_url' parameter
 | 
			
		||||
	let callback = params.callback_url;
 | 
			
		||||
	if (callback === '') {
 | 
			
		||||
		callback = null;
 | 
			
		||||
	}
 | 
			
		||||
	// TODO: Check it is valid url
 | 
			
		||||
	const [callbackUrl, callbackUrlErr] = it(params.callback_url).expect.nullable.string().default(null).qed();
 | 
			
		||||
	if (callbackUrlErr) return rej('invalid callback_url param');
 | 
			
		||||
 | 
			
		||||
	// Generate secret
 | 
			
		||||
	const secret = rndstr('a-zA-Z0-9', 32);
 | 
			
		||||
| 
						 | 
				
			
			@ -118,8 +104,8 @@ module.exports = async (params, user) =>
 | 
			
		|||
		name_id: nameId,
 | 
			
		||||
		name_id_lower: nameId.toLowerCase(),
 | 
			
		||||
		description: description,
 | 
			
		||||
		permission: permission.split(','),
 | 
			
		||||
		callback_url: callback,
 | 
			
		||||
		permission: permission,
 | 
			
		||||
		callback_url: callbackUrl,
 | 
			
		||||
		secret: secret
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,9 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import App from '../../../models/app';
 | 
			
		||||
import { isValidNameId } from '../../../models/app';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @swagger
 | 
			
		||||
| 
						 | 
				
			
			@ -44,15 +46,8 @@ module.exports = async (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'name_id' parameter
 | 
			
		||||
	const nameId = params.name_id;
 | 
			
		||||
	if (nameId == null || nameId == '') {
 | 
			
		||||
		return rej('name_id is required');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Validate name_id
 | 
			
		||||
	if (!/^[a-zA-Z0-9\-]{3,30}$/.test(nameId)) {
 | 
			
		||||
		return rej('invalid name_id');
 | 
			
		||||
	}
 | 
			
		||||
	const [nameId, nameIdErr] = it(params.name_id).expect.string().required().validate(isValidNameId).qed();
 | 
			
		||||
	if (nameIdErr) return rej('invalid name_id param');
 | 
			
		||||
 | 
			
		||||
	// Get exist
 | 
			
		||||
	const exist = await App
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import App from '../../models/app';
 | 
			
		||||
import serialize from '../../serializers/app';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,16 +50,12 @@ module.exports = (params, user, _, isSecure) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'app_id' parameter
 | 
			
		||||
	let appId = params.app_id;
 | 
			
		||||
	if (appId == null || appId == '') {
 | 
			
		||||
		appId = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [appId, appIdErr] = it(params.app_id, 'id');
 | 
			
		||||
	if (appIdErr) return rej('invalid app_id param');
 | 
			
		||||
 | 
			
		||||
	// Get 'name_id' parameter
 | 
			
		||||
	let nameId = params.name_id;
 | 
			
		||||
	if (nameId == null || nameId == '') {
 | 
			
		||||
		nameId = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [nameId, nameIdErr] = it(params.name_id, 'string');
 | 
			
		||||
	if (nameIdErr) return rej('invalid name_id param');
 | 
			
		||||
 | 
			
		||||
	if (appId === null && nameId === null) {
 | 
			
		||||
		return rej('app_id or name_id is required');
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +63,7 @@ module.exports = (params, user, _, isSecure) =>
 | 
			
		|||
 | 
			
		||||
	// Lookup app
 | 
			
		||||
	const app = appId !== null
 | 
			
		||||
		? await App.findOne({ _id: new mongo.ObjectID(appId) })
 | 
			
		||||
		? await App.findOne({ _id: appId })
 | 
			
		||||
		: await App.findOne({ name_id_lower: nameId.toLowerCase() });
 | 
			
		||||
 | 
			
		||||
	if (app === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
 */
 | 
			
		||||
import rndstr from 'rndstr';
 | 
			
		||||
const crypto = require('crypto');
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import App from '../../models/app';
 | 
			
		||||
import AuthSess from '../../models/auth-session';
 | 
			
		||||
import AccessToken from '../../models/access-token';
 | 
			
		||||
| 
						 | 
				
			
			@ -43,21 +44,19 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'token' parameter
 | 
			
		||||
	const sesstoken = params.token;
 | 
			
		||||
	if (sesstoken == null) {
 | 
			
		||||
		return rej('token is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [token, tokenErr] = it(params.token).expect.string().required().qed();
 | 
			
		||||
	if (tokenErr) return rej('invalid token param');
 | 
			
		||||
 | 
			
		||||
	// Fetch token
 | 
			
		||||
	const session = await AuthSess
 | 
			
		||||
		.findOne({ token: sesstoken });
 | 
			
		||||
		.findOne({ token: token });
 | 
			
		||||
 | 
			
		||||
	if (session === null) {
 | 
			
		||||
		return rej('session not found');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Generate access token
 | 
			
		||||
	const token = rndstr('a-zA-Z0-9', 32);
 | 
			
		||||
	const accessToken = rndstr('a-zA-Z0-9', 32);
 | 
			
		||||
 | 
			
		||||
	// Fetch exist access token
 | 
			
		||||
	const exist = await AccessToken.findOne({
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +72,7 @@ module.exports = (params, user) =>
 | 
			
		|||
 | 
			
		||||
		// Generate Hash
 | 
			
		||||
		const sha256 = crypto.createHash('sha256');
 | 
			
		||||
		sha256.update(token + app.secret);
 | 
			
		||||
		sha256.update(accessToken + app.secret);
 | 
			
		||||
		const hash = sha256.digest('hex');
 | 
			
		||||
 | 
			
		||||
		// Insert access token doc
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +80,7 @@ module.exports = (params, user) =>
 | 
			
		|||
			created_at: new Date(),
 | 
			
		||||
			app_id: session.app_id,
 | 
			
		||||
			user_id: user._id,
 | 
			
		||||
			token: token,
 | 
			
		||||
			token: accessToken,
 | 
			
		||||
			hash: hash
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as uuid from 'uuid';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import App from '../../../models/app';
 | 
			
		||||
import AuthSess from '../../../models/auth-session';
 | 
			
		||||
import config from '../../../../conf';
 | 
			
		||||
| 
						 | 
				
			
			@ -49,10 +50,8 @@ module.exports = (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'app_secret' parameter
 | 
			
		||||
	const appSecret = params.app_secret;
 | 
			
		||||
	if (appSecret == null) {
 | 
			
		||||
		return rej('app_secret is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [appSecret, appSecretErr] = it(params.app_secret).expect.string().required().qed();
 | 
			
		||||
	if (appSecretErr) return rej('invalid app_secret param');
 | 
			
		||||
 | 
			
		||||
	// Lookup app
 | 
			
		||||
	const app = await App.findOne({
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import AuthSess from '../../../models/auth-session';
 | 
			
		||||
import serialize from '../../../serializers/auth-session';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,10 +58,8 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'token' parameter
 | 
			
		||||
	const token = params.token;
 | 
			
		||||
	if (token == null) {
 | 
			
		||||
		return rej('token is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [token, tokenErr] = it(params.token).expect.string().required().qed();
 | 
			
		||||
	if (tokenErr) return rej('invalid token param');
 | 
			
		||||
 | 
			
		||||
	// Lookup session
 | 
			
		||||
	const session = await AuthSess.findOne({
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import App from '../../../models/app';
 | 
			
		||||
import AuthSess from '../../../models/auth-session';
 | 
			
		||||
import AccessToken from '../../../models/access-token';
 | 
			
		||||
| 
						 | 
				
			
			@ -53,10 +54,8 @@ import serialize from '../../../serializers/user';
 | 
			
		|||
module.exports = (params) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'app_secret' parameter
 | 
			
		||||
		const appSecret = params.app_secret;
 | 
			
		||||
		if (appSecret == null) {
 | 
			
		||||
			return rej('app_secret is required');
 | 
			
		||||
		}
 | 
			
		||||
		const [appSecret, appSecretErr] = it(params.app_secret).expect.string().required().qed();
 | 
			
		||||
		if (appSecretErr) return rej('invalid app_secret param');
 | 
			
		||||
 | 
			
		||||
		// Lookup app
 | 
			
		||||
		const app = await App.findOne({
 | 
			
		||||
| 
						 | 
				
			
			@ -68,10 +67,8 @@ module.exports = (params) =>
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		// Get 'token' parameter
 | 
			
		||||
		const token = params.token;
 | 
			
		||||
		if (token == null) {
 | 
			
		||||
			return rej('token is required');
 | 
			
		||||
		}
 | 
			
		||||
		const [token, tokenErr] = it(params.token).expect.string().required().qed();
 | 
			
		||||
		if (tokenErr) return rej('invalid token param');
 | 
			
		||||
 | 
			
		||||
		// Fetch token
 | 
			
		||||
		const session = await AuthSess
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import DriveFile from '../../models/drive-file';
 | 
			
		||||
import serialize from '../../serializers/drive-file';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,33 +19,25 @@ 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);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== 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);
 | 
			
		||||
	}
 | 
			
		||||
	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 = {
 | 
			
		||||
| 
						 | 
				
			
			@ -53,16 +45,16 @@ module.exports = (params, user, app) =>
 | 
			
		|||
	};
 | 
			
		||||
	const query = {
 | 
			
		||||
		user_id: user._id,
 | 
			
		||||
		folder_id: folder
 | 
			
		||||
	};
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
		folder_id: folderId
 | 
			
		||||
	} as any;
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4,10 +4,8 @@
 | 
			
		|||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as fs from 'fs';
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import File from '../../../models/drive-file';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,15 +43,11 @@ module.exports = (file, params, user) =>
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'folder_id' parameter
 | 
			
		||||
	let folder = params.folder_id;
 | 
			
		||||
	if (folder === undefined || folder === null) {
 | 
			
		||||
		folder = null;
 | 
			
		||||
	} else {
 | 
			
		||||
		folder = new mongo.ObjectID(folder);
 | 
			
		||||
	}
 | 
			
		||||
	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, folder);
 | 
			
		||||
	const driveFile = await create(user, buffer, name, null, folderId);
 | 
			
		||||
 | 
			
		||||
	// Serialize
 | 
			
		||||
	const fileObj = await serialize(driveFile);
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import DriveFile from '../../../models/drive-file';
 | 
			
		||||
import serialize from '../../../serializers/drive-file';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,25 +18,19 @@ 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');
 | 
			
		||||
	}
 | 
			
		||||
	const [name, nameErr] = it(params.name).expect.string().required().qed();
 | 
			
		||||
	if (nameErr) return rej('invalid name param');
 | 
			
		||||
 | 
			
		||||
	// Get 'folder_id' parameter
 | 
			
		||||
	let folder = params.folder_id;
 | 
			
		||||
	if (folder === undefined || folder === null) {
 | 
			
		||||
		folder = null;
 | 
			
		||||
	} else {
 | 
			
		||||
		folder = new mongo.ObjectID(folder);
 | 
			
		||||
	}
 | 
			
		||||
	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: folder
 | 
			
		||||
			folder_id: folderId
 | 
			
		||||
		}, {
 | 
			
		||||
			fields: {
 | 
			
		||||
				data: false
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import DriveFile from '../../../models/drive-file';
 | 
			
		||||
import serialize from '../../../serializers/drive-file';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,14 +18,13 @@ 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 [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: new mongo.ObjectID(fileId),
 | 
			
		||||
			_id: fileId,
 | 
			
		||||
			user_id: user._id
 | 
			
		||||
		}, {
 | 
			
		||||
			fields: {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import DriveFolder from '../../../models/drive-folder';
 | 
			
		||||
import DriveFile from '../../../models/drive-file';
 | 
			
		||||
import { validateFileName } from '../../../models/drive-file';
 | 
			
		||||
| 
						 | 
				
			
			@ -21,19 +21,13 @@ 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 [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: new mongo.ObjectID(fileId),
 | 
			
		||||
			_id: fileId,
 | 
			
		||||
			user_id: user._id
 | 
			
		||||
		}, {
 | 
			
		||||
			fields: {
 | 
			
		||||
| 
						 | 
				
			
			@ -46,29 +40,19 @@ module.exports = (params, user) =>
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'name' parameter
 | 
			
		||||
	let name = params.name;
 | 
			
		||||
	if (name) {
 | 
			
		||||
		name = name.trim();
 | 
			
		||||
		if (validateFileName(name)) {
 | 
			
		||||
			file.name = name;
 | 
			
		||||
		} else {
 | 
			
		||||
			return rej('invalid file name');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
	let folderId = params.folder_id;
 | 
			
		||||
	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 {
 | 
			
		||||
			// Validate id
 | 
			
		||||
			if (!mongo.ObjectID.isValid(folderId)) {
 | 
			
		||||
				return rej('incorrect folder_id');
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			folderId = new mongo.ObjectID(folderId);
 | 
			
		||||
 | 
			
		||||
			// Fetch folder
 | 
			
		||||
			const folder = await DriveFolder
 | 
			
		||||
				.findOne({
 | 
			
		||||
					_id: folderId,
 | 
			
		||||
| 
						 | 
				
			
			@ -5,10 +5,8 @@
 | 
			
		|||
 */
 | 
			
		||||
import * as URL from 'url';
 | 
			
		||||
const download = require('download');
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import File from '../../../models/drive-file';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,10 +22,8 @@ module.exports = (params, user) =>
 | 
			
		|||
{
 | 
			
		||||
	// Get 'url' parameter
 | 
			
		||||
	// TODO: Validate this url
 | 
			
		||||
	const url = params.url;
 | 
			
		||||
	if (url == null) {
 | 
			
		||||
		return rej('url is required');
 | 
			
		||||
	}
 | 
			
		||||
	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)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -35,18 +31,14 @@ module.exports = (params, user) =>
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'folder_id' parameter
 | 
			
		||||
	let folder = params.folder_id;
 | 
			
		||||
	if (folder === undefined || folder === null) {
 | 
			
		||||
		folder = null;
 | 
			
		||||
	} else {
 | 
			
		||||
		folder = new mongo.ObjectID(folder);
 | 
			
		||||
	}
 | 
			
		||||
	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, folder);
 | 
			
		||||
	const driveFile = await create(user, data, name, null, folderId);
 | 
			
		||||
 | 
			
		||||
	// Serialize
 | 
			
		||||
	const fileObj = await serialize(driveFile);
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import DriveFolder from '../../models/drive-folder';
 | 
			
		||||
import serialize from '../../serializers/drive-folder';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,33 +19,25 @@ 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);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== 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);
 | 
			
		||||
	}
 | 
			
		||||
	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 = {
 | 
			
		||||
| 
						 | 
				
			
			@ -53,16 +45,16 @@ module.exports = (params, user, app) =>
 | 
			
		|||
	};
 | 
			
		||||
	const query = {
 | 
			
		||||
		user_id: user._id,
 | 
			
		||||
		parent_id: folder
 | 
			
		||||
	};
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
		parent_id: folderId
 | 
			
		||||
	} as any;
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import DriveFolder from '../../../models/drive-folder';
 | 
			
		||||
import { isValidFolderName } from '../../../models/drive-folder';
 | 
			
		||||
import serialize from '../../../serializers/drive-folder';
 | 
			
		||||
| 
						 | 
				
			
			@ -20,33 +20,17 @@ 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;
 | 
			
		||||
	}
 | 
			
		||||
	const [name, nameErr] = it(params.name).expect.string().validate(isValidFolderName).default('無題のフォルダー').qed();
 | 
			
		||||
	if (nameErr) return rej('invalid name param');
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
	// 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 !== null) {
 | 
			
		||||
	if (parentId) {
 | 
			
		||||
		// Fetch parent folder
 | 
			
		||||
		parent = await DriveFolder
 | 
			
		||||
			.findOne({
 | 
			
		||||
				_id: parentId,
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +38,7 @@ module.exports = (params, user) =>
 | 
			
		|||
			});
 | 
			
		||||
 | 
			
		||||
		if (parent === null) {
 | 
			
		||||
			return reject('parent-not-found');
 | 
			
		||||
			return rej('parent-not-found');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import DriveFolder from '../../../models/drive-folder';
 | 
			
		||||
import serialize from '../../../serializers/drive-folder';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,18 +18,12 @@ 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');
 | 
			
		||||
	}
 | 
			
		||||
	const [name, nameErr] = it(params.name).expect.string().required().qed();
 | 
			
		||||
	if (nameErr) return rej('invalid name param');
 | 
			
		||||
 | 
			
		||||
	// Get 'parent_id' parameter
 | 
			
		||||
	let parentId = params.parent_id;
 | 
			
		||||
	if (parentId === undefined || parentId === null) {
 | 
			
		||||
		parentId = null;
 | 
			
		||||
	} else {
 | 
			
		||||
		parentId = new mongo.ObjectID(parentId);
 | 
			
		||||
	}
 | 
			
		||||
	const [parentId, parentIdErr] = it(params.parent_id).expect.id().qed();
 | 
			
		||||
	if (parentIdErr) return rej('invalid parent_id param');
 | 
			
		||||
 | 
			
		||||
	// Issue query
 | 
			
		||||
	const folders = await DriveFolder
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import DriveFolder from '../../../models/drive-folder';
 | 
			
		||||
import serialize from '../../../serializers/drive-folder';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,15 +18,13 @@ 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');
 | 
			
		||||
	}
 | 
			
		||||
	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: new mongo.ObjectID(folderId),
 | 
			
		||||
			_id: folderId,
 | 
			
		||||
			user_id: user._id
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import DriveFolder from '../../../models/drive-folder';
 | 
			
		||||
import { isValidFolderName } from '../../../models/drive-folder';
 | 
			
		||||
import serialize from '../../../serializers/drive-file';
 | 
			
		||||
| 
						 | 
				
			
			@ -20,20 +20,13 @@ 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');
 | 
			
		||||
	}
 | 
			
		||||
	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: new mongo.ObjectID(folderId),
 | 
			
		||||
			_id: folderId,
 | 
			
		||||
			user_id: user._id
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,29 +35,17 @@ module.exports = (params, user) =>
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'name' parameter
 | 
			
		||||
	let name = params.name;
 | 
			
		||||
	if (name) {
 | 
			
		||||
		name = name.trim();
 | 
			
		||||
		if (isValidFolderName(name)) {
 | 
			
		||||
			folder.name = name;
 | 
			
		||||
		} else {
 | 
			
		||||
			return rej('invalid folder name');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
	let parentId = params.parent_id;
 | 
			
		||||
	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 {
 | 
			
		||||
			// 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({
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import DriveFile from '../../models/drive-file';
 | 
			
		||||
import serialize from '../../serializers/drive-file';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,35 +18,25 @@ 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);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== 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, '.+?')}$`);
 | 
			
		||||
	}
 | 
			
		||||
	const [type, typeErr] = it(params.type).expect.string().match(/^[a-zA-Z\/\-\*]+$/).qed();
 | 
			
		||||
	if (typeErr) return rej('invalid type param');
 | 
			
		||||
 | 
			
		||||
	// Construct query
 | 
			
		||||
	const sort = {
 | 
			
		||||
| 
						 | 
				
			
			@ -54,19 +44,19 @@ module.exports = (params, user) =>
 | 
			
		|||
	};
 | 
			
		||||
	const query = {
 | 
			
		||||
		user_id: user._id
 | 
			
		||||
	};
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
	} as any;
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
	if (type !== null) {
 | 
			
		||||
		query.type = type;
 | 
			
		||||
		query.type = new RegExp(`^${type.replace(/\*/g, '.+?')}$`);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Issue query
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import Following from '../../models/following';
 | 
			
		||||
import notify from '../../common/notify';
 | 
			
		||||
| 
						 | 
				
			
			@ -23,15 +23,8 @@ module.exports = (params, user) =>
 | 
			
		|||
	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');
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id, 'id', true);
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// 自分自身
 | 
			
		||||
	if (user._id.equals(userId)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +33,7 @@ module.exports = (params, user) =>
 | 
			
		|||
 | 
			
		||||
	// Get followee
 | 
			
		||||
	const followee = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			data: false,
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import Following from '../../models/following';
 | 
			
		||||
import event from '../../event';
 | 
			
		||||
| 
						 | 
				
			
			@ -22,15 +22,8 @@ module.exports = (params, user) =>
 | 
			
		|||
	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');
 | 
			
		||||
	}
 | 
			
		||||
	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)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +32,7 @@ module.exports = (params, user) =>
 | 
			
		|||
 | 
			
		||||
	// Get followee
 | 
			
		||||
	const followee = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			data: false,
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import AccessToken from '../../models/access-token';
 | 
			
		||||
import serialize from '../../serializers/app';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,28 +18,16 @@ 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Get 'sort' parameter
 | 
			
		||||
	let sort = params.sort || 'desc';
 | 
			
		||||
	const [sort, sortError] = it(params.sort).expect.string().or('desc asc').default('desc').qed();
 | 
			
		||||
	if (sortError) return rej('invalid sort param');
 | 
			
		||||
 | 
			
		||||
	// Get tokens
 | 
			
		||||
	const tokens = await AccessToken
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Favorite from '../../models/favorite';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -11,37 +11,26 @@ import serialize from '../../serializers/post';
 | 
			
		|||
 * Get followers of a user
 | 
			
		||||
 *
 | 
			
		||||
 * @param {any} params
 | 
			
		||||
 * @param {any} user
 | 
			
		||||
 * @return {Promise<any>}
 | 
			
		||||
 */
 | 
			
		||||
module.exports = (params) =>
 | 
			
		||||
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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Get 'sort' parameter
 | 
			
		||||
	let sort = params.sort || 'desc';
 | 
			
		||||
	const [sort, sortError] = it(params.sort).expect.string().or('desc asc').default('desc').qed();
 | 
			
		||||
	if (sortError) return rej('invalid sort param');
 | 
			
		||||
 | 
			
		||||
	// Get favorites
 | 
			
		||||
	const favorites = await Favorites
 | 
			
		||||
	const favorites = await Favorite
 | 
			
		||||
		.find({
 | 
			
		||||
			user_id: user._id
 | 
			
		||||
		}, {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Notification from '../../models/notification';
 | 
			
		||||
import serialize from '../../serializers/notification';
 | 
			
		||||
import getFriends from '../../common/get-friends';
 | 
			
		||||
| 
						 | 
				
			
			@ -19,44 +19,38 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'following' parameter
 | 
			
		||||
	const following = params.following;
 | 
			
		||||
	const [following, followingError] =
 | 
			
		||||
		it(params.following).expect.boolean().default(false).qed();
 | 
			
		||||
	if (followingError) return rej('invalid following param');
 | 
			
		||||
 | 
			
		||||
	// Get 'mark_as_read' parameter
 | 
			
		||||
	let markAsRead = params.mark_as_read;
 | 
			
		||||
	if (markAsRead == null) {
 | 
			
		||||
		markAsRead = true;
 | 
			
		||||
	}
 | 
			
		||||
	const [markAsRead, markAsReadErr] = it(params.mark_as_read).expect.boolean().default(true).qed();
 | 
			
		||||
	if (markAsReadErr) return rej('invalid mark_as_read param');
 | 
			
		||||
 | 
			
		||||
	// Get 'type' parameter
 | 
			
		||||
	let type = params.type;
 | 
			
		||||
	if (type !== undefined && type !== null) {
 | 
			
		||||
		type = type.split(',').map(x => x.trim());
 | 
			
		||||
	}
 | 
			
		||||
	const [type, typeErr] = it(params.type).expect.array().unique().allString().qed();
 | 
			
		||||
	if (typeErr) return rej('invalid type param');
 | 
			
		||||
 | 
			
		||||
	// Get 'limit' parameter
 | 
			
		||||
	let limit = params.limit;
 | 
			
		||||
	if (limit !== undefined && limit !== null) {
 | 
			
		||||
		limit = parseInt(limit, 10);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== null) {
 | 
			
		||||
		return rej('cannot set since_id and max_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const query = {
 | 
			
		||||
		notifiee_id: user._id
 | 
			
		||||
	};
 | 
			
		||||
	} as any;
 | 
			
		||||
 | 
			
		||||
	const sort = {
 | 
			
		||||
		_id: -1
 | 
			
		||||
| 
						 | 
				
			
			@ -77,14 +71,14 @@ module.exports = (params, user) =>
 | 
			
		|||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Signin from '../../models/signin';
 | 
			
		||||
import serialize from '../../serializers/signin';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,42 +18,38 @@ 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);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== null) {
 | 
			
		||||
		return rej('cannot set since_id and max_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const query = {
 | 
			
		||||
		user_id: user._id
 | 
			
		||||
	};
 | 
			
		||||
	} as any;
 | 
			
		||||
 | 
			
		||||
	const sort = {
 | 
			
		||||
		_id: -1
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,119 +0,0 @@
 | 
			
		|||
'use strict';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import { isValidName, isValidBirthday } from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
import event from '../../event';
 | 
			
		||||
import config from '../../../conf';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Update myself
 | 
			
		||||
 *
 | 
			
		||||
 * @param {any} params
 | 
			
		||||
 * @param {any} user
 | 
			
		||||
 * @param {any} _
 | 
			
		||||
 * @param {boolean} isSecure
 | 
			
		||||
 * @return {Promise<any>}
 | 
			
		||||
 */
 | 
			
		||||
module.exports = async (params, user, _, isSecure) =>
 | 
			
		||||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'name' parameter
 | 
			
		||||
	const name = params.name;
 | 
			
		||||
	if (name !== undefined && name !== null) {
 | 
			
		||||
		if (typeof name != 'string') {
 | 
			
		||||
			return rej('name must be a string');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!isValidName(name)) {
 | 
			
		||||
			return rej('invalid name');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		user.name = name;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'description' parameter
 | 
			
		||||
	const description = params.description;
 | 
			
		||||
	if (description !== undefined && description !== null) {
 | 
			
		||||
		if (description.length > 500) {
 | 
			
		||||
			return rej('too long description');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		user.description = description;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'location' parameter
 | 
			
		||||
	const location = params.location;
 | 
			
		||||
	if (location !== undefined && location !== null) {
 | 
			
		||||
		if (location.length > 50) {
 | 
			
		||||
			return rej('too long location');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		user.profile.location = location;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'birthday' parameter
 | 
			
		||||
	const birthday = params.birthday;
 | 
			
		||||
	if (birthday != null) {
 | 
			
		||||
		if (!isValidBirthday(birthday)) {
 | 
			
		||||
			return rej('invalid birthday');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		user.profile.birthday = birthday;
 | 
			
		||||
	} else {
 | 
			
		||||
		user.profile.birthday = null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'avatar_id' parameter
 | 
			
		||||
	const avatar = params.avatar_id;
 | 
			
		||||
	if (avatar !== undefined && avatar !== null) {
 | 
			
		||||
		user.avatar_id = new mongo.ObjectID(avatar);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'banner_id' parameter
 | 
			
		||||
	const banner = params.banner_id;
 | 
			
		||||
	if (banner !== undefined && banner !== null) {
 | 
			
		||||
		user.banner_id = new mongo.ObjectID(banner);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	await User.update(user._id, {
 | 
			
		||||
		$set: {
 | 
			
		||||
			name: user.name,
 | 
			
		||||
			description: user.description,
 | 
			
		||||
			avatar_id: user.avatar_id,
 | 
			
		||||
			banner_id: user.banner_id,
 | 
			
		||||
			profile: user.profile
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	// Serialize
 | 
			
		||||
	const iObj = await serialize(user, user, {
 | 
			
		||||
		detail: true,
 | 
			
		||||
		includeSecrets: isSecure
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	// Send response
 | 
			
		||||
	res(iObj);
 | 
			
		||||
 | 
			
		||||
	// Publish i updated event
 | 
			
		||||
	event(user._id, 'i_updated', iObj);
 | 
			
		||||
 | 
			
		||||
	// Update search index
 | 
			
		||||
	if (config.elasticsearch.enable) {
 | 
			
		||||
		const es = require('../../../db/elasticsearch');
 | 
			
		||||
 | 
			
		||||
		es.index({
 | 
			
		||||
			index: 'misskey',
 | 
			
		||||
			type: 'user',
 | 
			
		||||
			id: user._id.toString(),
 | 
			
		||||
			body: {
 | 
			
		||||
				name: user.name,
 | 
			
		||||
				bio: user.bio
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										91
									
								
								src/api/endpoints/i/update.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/api/endpoints/i/update.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
'use strict';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import { isValidName, isValidDescription, isValidLocation, isValidBirthday } from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
import event from '../../event';
 | 
			
		||||
import config from '../../../conf';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Update myself
 | 
			
		||||
 *
 | 
			
		||||
 * @param {any} params
 | 
			
		||||
 * @param {any} user
 | 
			
		||||
 * @param {any} _
 | 
			
		||||
 * @param {boolean} isSecure
 | 
			
		||||
 * @return {Promise<any>}
 | 
			
		||||
 */
 | 
			
		||||
module.exports = async (params, user, _, isSecure) =>
 | 
			
		||||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'name' parameter
 | 
			
		||||
	const [name, nameErr] = it(params.name).expect.string().validate(isValidName).qed();
 | 
			
		||||
	if (nameErr) return rej('invalid name param');
 | 
			
		||||
	if (name) user.name = name;
 | 
			
		||||
 | 
			
		||||
	// Get 'description' parameter
 | 
			
		||||
	const [description, descriptionErr] = it(params.description).expect.nullable.string().validate(isValidDescription).qed();
 | 
			
		||||
	if (descriptionErr) return rej('invalid description param');
 | 
			
		||||
	if (description !== undefined) user.description = description;
 | 
			
		||||
 | 
			
		||||
	// Get 'location' parameter
 | 
			
		||||
	const [location, locationErr] = it(params.location).expect.nullable.string().validate(isValidLocation).qed();
 | 
			
		||||
	if (locationErr) return rej('invalid location param');
 | 
			
		||||
	if (location !== undefined) user.location = location;
 | 
			
		||||
 | 
			
		||||
	// Get 'birthday' parameter
 | 
			
		||||
	const [birthday, birthdayErr] = it(params.birthday).expect.nullable.string().validate(isValidBirthday).qed();
 | 
			
		||||
	if (birthdayErr) return rej('invalid birthday param');
 | 
			
		||||
	if (birthday !== undefined) user.birthday = birthday;
 | 
			
		||||
 | 
			
		||||
	// Get 'avatar_id' parameter
 | 
			
		||||
	const [avatarId, avatarIdErr] = it(params.avatar_id).expect.id().notNull().qed();
 | 
			
		||||
	if (avatarIdErr) return rej('invalid avatar_id param');
 | 
			
		||||
	if (avatarId) user.avatar_id = avatarId;
 | 
			
		||||
 | 
			
		||||
	// Get 'banner_id' parameter
 | 
			
		||||
	const [bannerId, bannerIdErr] = it(params.banner_id).expect.id().notNull().qed();
 | 
			
		||||
	if (bannerIdErr) return rej('invalid banner_id param');
 | 
			
		||||
	if (bannerId) user.banner_id = bannerId;
 | 
			
		||||
 | 
			
		||||
	await User.update(user._id, {
 | 
			
		||||
		$set: {
 | 
			
		||||
			name: user.name,
 | 
			
		||||
			description: user.description,
 | 
			
		||||
			avatar_id: user.avatar_id,
 | 
			
		||||
			banner_id: user.banner_id,
 | 
			
		||||
			profile: user.profile
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	// Serialize
 | 
			
		||||
	const iObj = await serialize(user, user, {
 | 
			
		||||
		detail: true,
 | 
			
		||||
		includeSecrets: isSecure
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	// Send response
 | 
			
		||||
	res(iObj);
 | 
			
		||||
 | 
			
		||||
	// Publish i updated event
 | 
			
		||||
	event(user._id, 'i_updated', iObj);
 | 
			
		||||
 | 
			
		||||
	// Update search index
 | 
			
		||||
	if (config.elasticsearch.enable) {
 | 
			
		||||
		const es = require('../../../db/elasticsearch');
 | 
			
		||||
 | 
			
		||||
		es.index({
 | 
			
		||||
			index: 'misskey',
 | 
			
		||||
			type: 'user',
 | 
			
		||||
			id: user._id.toString(),
 | 
			
		||||
			body: {
 | 
			
		||||
				name: user.name,
 | 
			
		||||
				bio: user.bio
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import History from '../../models/messaging-history';
 | 
			
		||||
import serialize from '../../serializers/messaging-message';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,17 +18,8 @@ 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get history
 | 
			
		||||
	const history = await History
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Message from '../../models/messaging-message';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/messaging-message';
 | 
			
		||||
| 
						 | 
				
			
			@ -21,47 +21,40 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	let recipient = params.user_id;
 | 
			
		||||
	if (recipient !== undefined && recipient !== null) {
 | 
			
		||||
		recipient = await User.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(recipient)
 | 
			
		||||
		}, {
 | 
			
		||||
			fields: {
 | 
			
		||||
				_id: true
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
	const [recipientId, recipientIdErr] = it(params.user_id).expect.id().required().qed();
 | 
			
		||||
	if (recipientIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
		if (recipient === null) {
 | 
			
		||||
			return rej('user not found');
 | 
			
		||||
	// Fetch recipient
 | 
			
		||||
	const recipient = await User.findOne({
 | 
			
		||||
		_id: recipientId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (recipient === null) {
 | 
			
		||||
		return rej('user not found');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'mark_as_read' parameter
 | 
			
		||||
	let markAsRead = params.mark_as_read;
 | 
			
		||||
	if (markAsRead == null) {
 | 
			
		||||
		markAsRead = true;
 | 
			
		||||
	}
 | 
			
		||||
	const [markAsRead, markAsReadErr] = it(params.mark_as_read).expect.boolean().default(true).qed();
 | 
			
		||||
	if (markAsReadErr) return rej('invalid mark_as_read param');
 | 
			
		||||
 | 
			
		||||
	// Get 'limit' parameter
 | 
			
		||||
	let limit = params.limit;
 | 
			
		||||
	if (limit !== undefined && limit !== null) {
 | 
			
		||||
		limit = parseInt(limit, 10);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== null) {
 | 
			
		||||
		return rej('cannot set since_id and max_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,20 +66,20 @@ module.exports = (params, user) =>
 | 
			
		|||
			user_id: recipient._id,
 | 
			
		||||
			recipient_id: user._id
 | 
			
		||||
		}]
 | 
			
		||||
	};
 | 
			
		||||
	} as any;
 | 
			
		||||
 | 
			
		||||
	const sort = {
 | 
			
		||||
		_id: -1
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,8 +3,9 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Message from '../../../models/messaging-message';
 | 
			
		||||
import { isValidText } from '../../../models/messaging-message';
 | 
			
		||||
import History from '../../../models/messaging-history';
 | 
			
		||||
import User from '../../../models/user';
 | 
			
		||||
import DriveFile from '../../../models/drive-file';
 | 
			
		||||
| 
						 | 
				
			
			@ -13,11 +14,6 @@ import publishUserStream from '../../../event';
 | 
			
		|||
import { publishMessagingStream } from '../../../event';
 | 
			
		||||
import config from '../../../../conf';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 最大文字数
 | 
			
		||||
 */
 | 
			
		||||
const maxTextLength = 500;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a message
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -29,55 +25,39 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	let recipient = params.user_id;
 | 
			
		||||
	if (recipient !== undefined && recipient !== null) {
 | 
			
		||||
		if (typeof recipient != 'string') {
 | 
			
		||||
			return rej('user_id must be a string');
 | 
			
		||||
		}
 | 
			
		||||
	const [recipientId, recipientIdErr] = it(params.user_id).expect.id().required().qed();
 | 
			
		||||
	if (recipientIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
		// Validate id
 | 
			
		||||
		if (!mongo.ObjectID.isValid(recipient)) {
 | 
			
		||||
			return rej('incorrect user_id');
 | 
			
		||||
		}
 | 
			
		||||
	// Myself
 | 
			
		||||
	if (recipientId.equals(user._id)) {
 | 
			
		||||
		return rej('cannot send message to myself');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		// Myself
 | 
			
		||||
		if (new mongo.ObjectID(recipient).equals(user._id)) {
 | 
			
		||||
			return rej('cannot send message to myself');
 | 
			
		||||
	// Fetch recipient
 | 
			
		||||
	const recipient = await User.findOne({
 | 
			
		||||
		_id: recipientId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
		recipient = await User.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(recipient)
 | 
			
		||||
		}, {
 | 
			
		||||
			fields: {
 | 
			
		||||
				_id: true
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (recipient === null) {
 | 
			
		||||
			return rej('user not found');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	if (recipient === null) {
 | 
			
		||||
		return rej('user not found');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'text' parameter
 | 
			
		||||
	let text = params.text;
 | 
			
		||||
	if (text !== undefined && text !== null) {
 | 
			
		||||
		text = text.trim();
 | 
			
		||||
		if (text.length === 0) {
 | 
			
		||||
			text = null;
 | 
			
		||||
		} else if (text.length > maxTextLength) {
 | 
			
		||||
			return rej('too long text');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		text = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [text, textErr] = it(params.text).expect.string().validate(isValidText).qed();
 | 
			
		||||
	if (textErr) return rej('invalid text');
 | 
			
		||||
 | 
			
		||||
	// Get 'file_id' parameter
 | 
			
		||||
	let file = params.file_id;
 | 
			
		||||
	if (file !== undefined && file !== null) {
 | 
			
		||||
	const [fileId, fileIdErr] = it(params.file_id).expect.id().qed();
 | 
			
		||||
	if (fileIdErr) return rej('invalid file_id param');
 | 
			
		||||
 | 
			
		||||
	let file = null;
 | 
			
		||||
	if (fileId !== null) {
 | 
			
		||||
		file = await DriveFile.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(file),
 | 
			
		||||
			_id: fileId,
 | 
			
		||||
			user_id: user._id
 | 
			
		||||
		}, {
 | 
			
		||||
			data: false
 | 
			
		||||
| 
						 | 
				
			
			@ -86,8 +66,6 @@ module.exports = (params, user) =>
 | 
			
		|||
		if (file === null) {
 | 
			
		||||
			return rej('file not found');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		file = null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// テキストが無いかつ添付ファイルも無かったらエラー
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import App from '../../models/app';
 | 
			
		||||
import serialize from '../../serializers/app';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,25 +18,12 @@ 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	const query = {
 | 
			
		||||
		user_id: user._id
 | 
			
		||||
| 
						 | 
				
			
			@ -3,10 +3,10 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import Notification from '../../../models/notification';
 | 
			
		||||
import serialize from '../../../serializers/notification';
 | 
			
		||||
import event from '../../../event';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Notification from '../../models/notification';
 | 
			
		||||
import serialize from '../../serializers/notification';
 | 
			
		||||
import event from '../../event';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Mark as read a notification
 | 
			
		||||
| 
						 | 
				
			
			@ -17,16 +17,13 @@ import event from '../../../event';
 | 
			
		|||
 */
 | 
			
		||||
module.exports = (params, user) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		const notificationId = params.notification;
 | 
			
		||||
 | 
			
		||||
		if (notificationId === undefined || notificationId === null) {
 | 
			
		||||
			return rej('notification is required');
 | 
			
		||||
		}
 | 
			
		||||
		const [notificationId, notificationIdErr] = it(params.notification_id).expect.id().required().qed();
 | 
			
		||||
		if (notificationIdErr) return rej('invalid notification_id param');
 | 
			
		||||
 | 
			
		||||
		// Get notification
 | 
			
		||||
		const notification = await Notification
 | 
			
		||||
			.findOne({
 | 
			
		||||
				_id: new mongo.ObjectID(notificationId),
 | 
			
		||||
				_id: notificationId,
 | 
			
		||||
				i: user._id
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,87 +0,0 @@
 | 
			
		|||
'use strict';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import Post from '../models/post';
 | 
			
		||||
import serialize from '../serializers/post';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Lists all posts
 | 
			
		||||
 *
 | 
			
		||||
 * @param {any} params
 | 
			
		||||
 * @return {Promise<any>}
 | 
			
		||||
 */
 | 
			
		||||
module.exports = (params) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'include_replies' parameter
 | 
			
		||||
		let includeReplies = params.include_replies;
 | 
			
		||||
		if (includeReplies === true) {
 | 
			
		||||
			includeReplies = true;
 | 
			
		||||
		} else {
 | 
			
		||||
			includeReplies = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Get 'include_reposts' parameter
 | 
			
		||||
		let includeReposts = params.include_reposts;
 | 
			
		||||
		if (includeReposts === true) {
 | 
			
		||||
			includeReposts = true;
 | 
			
		||||
		} else {
 | 
			
		||||
			includeReposts = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 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');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Construct query
 | 
			
		||||
		const sort = {
 | 
			
		||||
			_id: -1
 | 
			
		||||
		};
 | 
			
		||||
		const query = {};
 | 
			
		||||
		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 (!includeReplies) {
 | 
			
		||||
			query.reply_to_id = null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!includeReposts) {
 | 
			
		||||
			query.repost_id = null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Issue query
 | 
			
		||||
		const posts = await Post
 | 
			
		||||
			.find(query, {
 | 
			
		||||
				limit: limit,
 | 
			
		||||
				sort: sort
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
		// Serialize
 | 
			
		||||
		res(await Promise.all(posts.map(async post => await serialize(post))));
 | 
			
		||||
	});
 | 
			
		||||
							
								
								
									
										76
									
								
								src/api/endpoints/posts.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/api/endpoints/posts.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
'use strict';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../it';
 | 
			
		||||
import Post from '../models/post';
 | 
			
		||||
import serialize from '../serializers/post';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Lists all posts
 | 
			
		||||
 *
 | 
			
		||||
 * @param {any} params
 | 
			
		||||
 * @return {Promise<any>}
 | 
			
		||||
 */
 | 
			
		||||
module.exports = (params) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'include_replies' parameter
 | 
			
		||||
		const [includeReplies, includeRepliesErr] = it(params.include_replies).expect.boolean().default(true).qed();
 | 
			
		||||
		if (includeRepliesErr) return rej('invalid include_replies param');
 | 
			
		||||
 | 
			
		||||
		// Get 'include_reposts' parameter
 | 
			
		||||
		const [includeReposts, includeRepostsErr] = it(params.include_reposts).expect.boolean().default(true).qed();
 | 
			
		||||
		if (includeRepostsErr) return rej('invalid include_reposts param');
 | 
			
		||||
 | 
			
		||||
		// 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');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Construct query
 | 
			
		||||
		const sort = {
 | 
			
		||||
			_id: -1
 | 
			
		||||
		};
 | 
			
		||||
		const query = {} as any;
 | 
			
		||||
		if (sinceId) {
 | 
			
		||||
			sort._id = 1;
 | 
			
		||||
			query._id = {
 | 
			
		||||
				$gt: sinceId
 | 
			
		||||
			};
 | 
			
		||||
		} else if (maxId) {
 | 
			
		||||
			query._id = {
 | 
			
		||||
				$lt: maxId
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!includeReplies) {
 | 
			
		||||
			query.reply_to_id = null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!includeReposts) {
 | 
			
		||||
			query.repost_id = null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Issue query
 | 
			
		||||
		const posts = await Post
 | 
			
		||||
			.find(query, {
 | 
			
		||||
				limit: limit,
 | 
			
		||||
				sort: sort
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
		// Serialize
 | 
			
		||||
		res(await Promise.all(posts.map(async post => await serialize(post))));
 | 
			
		||||
	});
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,39 +18,24 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
		return rej('post not found', 'POST_NOT_FOUND');
 | 
			
		||||
		return rej('post not found');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const context = [];
 | 
			
		||||
| 
						 | 
				
			
			@ -3,28 +3,18 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import parse from '../../../common/text';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import { isValidText } from '../../models/post';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import Following from '../../models/following';
 | 
			
		||||
import DriveFile from '../../models/drive-file';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
import createFile from '../../common/add-file-to-drive';
 | 
			
		||||
import notify from '../../common/notify';
 | 
			
		||||
import event from '../../event';
 | 
			
		||||
import config from '../../../conf';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 最大文字数
 | 
			
		||||
 */
 | 
			
		||||
const maxTextLength = 1000;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 添付できるファイルの数
 | 
			
		||||
 */
 | 
			
		||||
const maxMediaCount = 4;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a post
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -37,55 +27,26 @@ module.exports = (params, user, app) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'text' parameter
 | 
			
		||||
	let text = params.text;
 | 
			
		||||
	if (text !== undefined && text !== null) {
 | 
			
		||||
		if (typeof text != 'string') {
 | 
			
		||||
			return rej('text must be a string');
 | 
			
		||||
		}
 | 
			
		||||
		text = text.trim();
 | 
			
		||||
		if (text.length == 0) {
 | 
			
		||||
			text = null;
 | 
			
		||||
		} else if (text.length > maxTextLength) {
 | 
			
		||||
			return rej('too long text');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		text = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [text, textErr] = it(params.text).must.be.a.string().validate(isValidText).qed();
 | 
			
		||||
	if (textErr) return rej('invalid text');
 | 
			
		||||
 | 
			
		||||
	// Get 'media_ids' parameter
 | 
			
		||||
	let medias = params.media_ids;
 | 
			
		||||
	const [mediaIds, mediaIdsErr] = it(params.media_ids).must.be.an.array().unique().range(1, 4).qed();
 | 
			
		||||
	if (mediaIdsErr) return rej('invalid media_ids');
 | 
			
		||||
 | 
			
		||||
	let files = [];
 | 
			
		||||
	if (medias !== undefined && medias !== null) {
 | 
			
		||||
		if (!Array.isArray(medias)) {
 | 
			
		||||
			return rej('media_ids must be an array');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (medias.length > maxMediaCount) {
 | 
			
		||||
			return rej('too many media');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Drop duplications
 | 
			
		||||
		medias = medias.filter((x, i, s) => s.indexOf(x) == i);
 | 
			
		||||
 | 
			
		||||
	if (mediaIds !== null) {
 | 
			
		||||
		// Fetch files
 | 
			
		||||
		// forEach だと途中でエラーなどがあっても return できないので
 | 
			
		||||
		// 敢えて for を使っています。
 | 
			
		||||
		for (let i = 0; i < medias.length; i++) {
 | 
			
		||||
			const media = medias[i];
 | 
			
		||||
 | 
			
		||||
			if (typeof media != 'string') {
 | 
			
		||||
				return rej('media id must be a string');
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Validate id
 | 
			
		||||
			if (!mongo.ObjectID.isValid(media)) {
 | 
			
		||||
				return rej('incorrect media id');
 | 
			
		||||
			}
 | 
			
		||||
		for (let i = 0; i < mediaIds.length; i++) {
 | 
			
		||||
			const [mediaId, mediaIdErr] = it(mediaIds[i]).must.be.an.id().required().qed();
 | 
			
		||||
			if (mediaIdErr) return rej('invalid media id');
 | 
			
		||||
 | 
			
		||||
			// Fetch file
 | 
			
		||||
			// SELECT _id
 | 
			
		||||
			const entity = await DriveFile.findOne({
 | 
			
		||||
				_id: new mongo.ObjectID(media),
 | 
			
		||||
				_id: mediaId,
 | 
			
		||||
				user_id: user._id
 | 
			
		||||
			}, {
 | 
			
		||||
				_id: true
 | 
			
		||||
| 
						 | 
				
			
			@ -102,20 +63,14 @@ module.exports = (params, user, app) =>
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'repost_id' parameter
 | 
			
		||||
	let repost = params.repost_id;
 | 
			
		||||
	if (repost !== undefined && repost !== null) {
 | 
			
		||||
		if (typeof repost != 'string') {
 | 
			
		||||
			return rej('repost_id must be a string');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Validate id
 | 
			
		||||
		if (!mongo.ObjectID.isValid(repost)) {
 | 
			
		||||
			return rej('incorrect repost_id');
 | 
			
		||||
		}
 | 
			
		||||
	const [repostId, repostIdErr] = it(params.repost_id).must.be.an.id().qed();
 | 
			
		||||
	if (repostIdErr) return rej('invalid repost_id');
 | 
			
		||||
 | 
			
		||||
	let repost = null;
 | 
			
		||||
	if (repostId !== null) {
 | 
			
		||||
		// Fetch repost to post
 | 
			
		||||
		repost = await Post.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(repost)
 | 
			
		||||
			_id: repostId
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (repost == null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -147,92 +102,56 @@ module.exports = (params, user, app) =>
 | 
			
		|||
				text === null && files === null) {
 | 
			
		||||
			return rej('二重Repostです(NEED TRANSLATE)');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		repost = null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'reply_to_id' parameter
 | 
			
		||||
	let replyTo = params.reply_to_id;
 | 
			
		||||
	if (replyTo !== undefined && replyTo !== null) {
 | 
			
		||||
		if (typeof replyTo != 'string') {
 | 
			
		||||
			return rej('reply_to_id must be a string');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Validate id
 | 
			
		||||
		if (!mongo.ObjectID.isValid(replyTo)) {
 | 
			
		||||
			return rej('incorrect reply_to_id');
 | 
			
		||||
		}
 | 
			
		||||
	// Get 'in_reply_to_post_id' parameter
 | 
			
		||||
	const [inReplyToPostId, inReplyToPostIdErr] = it(params.reply_to_id, 'id');
 | 
			
		||||
	if (inReplyToPostIdErr) return rej('invalid in_reply_to_post_id');
 | 
			
		||||
 | 
			
		||||
	let inReplyToPost = null;
 | 
			
		||||
	if (inReplyToPostId !== null) {
 | 
			
		||||
		// Fetch reply
 | 
			
		||||
		replyTo = await Post.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(replyTo)
 | 
			
		||||
		inReplyToPost = await Post.findOne({
 | 
			
		||||
			_id: inReplyToPostId
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (replyTo === null) {
 | 
			
		||||
			return rej('reply to post is not found');
 | 
			
		||||
		if (inReplyToPost === null) {
 | 
			
		||||
			return rej('in reply to post is not found');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 返信対象が引用でないRepostだったらエラー
 | 
			
		||||
		if (replyTo.repost_id && !replyTo.text && !replyTo.media_ids) {
 | 
			
		||||
		if (inReplyToPost.repost_id && !inReplyToPost.text && !inReplyToPost.media_ids) {
 | 
			
		||||
			return rej('cannot reply to repost');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		replyTo = null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'poll' parameter
 | 
			
		||||
	let poll = params.poll;
 | 
			
		||||
	if (poll !== undefined && poll !== null) {
 | 
			
		||||
		// 選択肢が無かったらエラー
 | 
			
		||||
		if (poll.choices == null) {
 | 
			
		||||
			return rej('poll choices is required');
 | 
			
		||||
		}
 | 
			
		||||
	const [_poll, pollErr] = it(params.poll, 'object');
 | 
			
		||||
	if (pollErr) return rej('invalid poll');
 | 
			
		||||
 | 
			
		||||
		// 選択肢が配列でなかったらエラー
 | 
			
		||||
		if (!Array.isArray(poll.choices)) {
 | 
			
		||||
			return rej('poll choices must be an array');
 | 
			
		||||
		}
 | 
			
		||||
	let poll = null;
 | 
			
		||||
	if (_poll !== null) {
 | 
			
		||||
		const [pollChoices, pollChoicesErr] =
 | 
			
		||||
			it(params.poll).expect.array()
 | 
			
		||||
				.unique()
 | 
			
		||||
				.allString()
 | 
			
		||||
				.range(1, 10)
 | 
			
		||||
				.validate(choices => !choices.some(choice => {
 | 
			
		||||
					if (typeof choice != 'string') return true;
 | 
			
		||||
					if (choice.trim().length == 0) return true;
 | 
			
		||||
					if (choice.trim().length > 50) return true;
 | 
			
		||||
					return false;
 | 
			
		||||
				}))
 | 
			
		||||
				.qed();
 | 
			
		||||
		if (pollChoicesErr) return rej('invalid poll choices');
 | 
			
		||||
 | 
			
		||||
		// 選択肢が空の配列でエラー
 | 
			
		||||
		if (poll.choices.length == 0) {
 | 
			
		||||
			return rej('poll choices is required');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Validate each choices
 | 
			
		||||
		const shouldReject = poll.choices.some(choice => {
 | 
			
		||||
			if (typeof choice !== 'string') return true;
 | 
			
		||||
			if (choice.trim().length === 0) return true;
 | 
			
		||||
			if (choice.trim().length > 100) return true;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (shouldReject) {
 | 
			
		||||
			return rej('invalid poll choices');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Trim choices
 | 
			
		||||
		poll.choices = poll.choices.map(choice => choice.trim());
 | 
			
		||||
 | 
			
		||||
		// Drop duplications
 | 
			
		||||
		poll.choices = poll.choices.filter((x, i, s) => s.indexOf(x) == i);
 | 
			
		||||
 | 
			
		||||
		// 選択肢がひとつならエラー
 | 
			
		||||
		if (poll.choices.length == 1) {
 | 
			
		||||
			return rej('poll choices must be ひとつ以上');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 選択肢が多すぎてもエラー
 | 
			
		||||
		if (poll.choices.length > 10) {
 | 
			
		||||
			return rej('many poll choices');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// serialize
 | 
			
		||||
		poll.choices = poll.choices.map((choice, i) => ({
 | 
			
		||||
		_poll.choices = pollChoices.map((choice, i) => ({
 | 
			
		||||
			id: i, // IDを付与
 | 
			
		||||
			text: choice,
 | 
			
		||||
			text: choice.trim(),
 | 
			
		||||
			votes: 0
 | 
			
		||||
		}));
 | 
			
		||||
	} else {
 | 
			
		||||
		poll = null;
 | 
			
		||||
 | 
			
		||||
		poll = _poll;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// テキストが無いかつ添付ファイルが無いかつRepostも無いかつ投票も無かったらエラー
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +163,7 @@ module.exports = (params, user, app) =>
 | 
			
		|||
	const post = await Post.insert({
 | 
			
		||||
		created_at: new Date(),
 | 
			
		||||
		media_ids: files ? files.map(file => file._id) : undefined,
 | 
			
		||||
		reply_to_id: replyTo ? replyTo._id : undefined,
 | 
			
		||||
		reply_to_id: inReplyToPost ? inReplyToPost._id : undefined,
 | 
			
		||||
		repost_id: repost ? repost._id : undefined,
 | 
			
		||||
		poll: poll ? poll : undefined,
 | 
			
		||||
		text: text,
 | 
			
		||||
| 
						 | 
				
			
			@ -302,21 +221,21 @@ module.exports = (params, user, app) =>
 | 
			
		|||
	});
 | 
			
		||||
 | 
			
		||||
	// If has in reply to post
 | 
			
		||||
	if (replyTo) {
 | 
			
		||||
	if (inReplyToPost) {
 | 
			
		||||
		// Increment replies count
 | 
			
		||||
		Post.update({ _id: replyTo._id }, {
 | 
			
		||||
		Post.update({ _id: inReplyToPost._id }, {
 | 
			
		||||
			$inc: {
 | 
			
		||||
				replies_count: 1
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		// 自分自身へのリプライでない限りは通知を作成
 | 
			
		||||
		notify(replyTo.user_id, user._id, 'reply', {
 | 
			
		||||
		notify(inReplyToPost.user_id, user._id, 'reply', {
 | 
			
		||||
			post_id: post._id
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		// Add mention
 | 
			
		||||
		addMention(replyTo.user_id, 'reply');
 | 
			
		||||
		addMention(inReplyToPost.user_id, 'reply');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If it is repost
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +280,7 @@ module.exports = (params, user, app) =>
 | 
			
		|||
	if (text) {
 | 
			
		||||
		// Analyze
 | 
			
		||||
		const tokens = parse(text);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
		// Extract a hashtags
 | 
			
		||||
		const hashtags = tokens
 | 
			
		||||
			.filter(t => t.type == 'hashtag')
 | 
			
		||||
| 
						 | 
				
			
			@ -370,8 +289,8 @@ module.exports = (params, user, app) =>
 | 
			
		|||
			.filter((v, i, s) => s.indexOf(v) == i);
 | 
			
		||||
 | 
			
		||||
		// ハッシュタグをデータベースに登録
 | 
			
		||||
		//registerHashtags(user, hashtags);
 | 
			
		||||
 | 
			
		||||
		registerHashtags(user, hashtags);
 | 
			
		||||
*/
 | 
			
		||||
		// Extract an '@' mentions
 | 
			
		||||
		const atMentions = tokens
 | 
			
		||||
			.filter(t => t.type == 'mention')
 | 
			
		||||
| 
						 | 
				
			
			@ -392,7 +311,7 @@ module.exports = (params, user, app) =>
 | 
			
		|||
			if (mentionee == null) return;
 | 
			
		||||
 | 
			
		||||
			// 既に言及されたユーザーに対する返信や引用repostの場合も無視
 | 
			
		||||
			if (replyTo && replyTo.user_id.equals(mentionee._id)) return;
 | 
			
		||||
			if (inReplyToPost && inReplyToPost.user_id.equals(mentionee._id)) return;
 | 
			
		||||
			if (repost && repost.user_id.equals(mentionee._id)) return;
 | 
			
		||||
 | 
			
		||||
			// Add mention
 | 
			
		||||
| 
						 | 
				
			
			@ -3,9 +3,9 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import Favorite from '../../models/favorite';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Favorite from '../../../models/favorite';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Favorite a post
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ import Post from '../../models/post';
 | 
			
		|||
module.exports = (params, user) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'post_id' parameter
 | 
			
		||||
		let postId = params.post_id;
 | 
			
		||||
		if (postId === undefined || postId === null) {
 | 
			
		||||
			return rej('post_id is required');
 | 
			
		||||
		}
 | 
			
		||||
		const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
		if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
		// Get favoritee
 | 
			
		||||
		const post = await Post.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(postId)
 | 
			
		||||
			_id: postId
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,9 +3,9 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import Favorite from '../../models/favorite';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Favorite from '../../../models/favorite';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Unfavorite a post
 | 
			
		||||
| 
						 | 
				
			
			@ -17,14 +17,12 @@ import Post from '../../models/post';
 | 
			
		|||
module.exports = (params, user) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'post_id' parameter
 | 
			
		||||
		let postId = params.post_id;
 | 
			
		||||
		if (postId === undefined || postId === null) {
 | 
			
		||||
			return rej('post_id is required');
 | 
			
		||||
		}
 | 
			
		||||
		const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
		if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
		// Get favoritee
 | 
			
		||||
		const post = await Post.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(postId)
 | 
			
		||||
			_id: postId
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import Like from '../../models/like';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
| 
						 | 
				
			
			@ -19,38 +19,24 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Get 'sort' parameter
 | 
			
		||||
	let sort = params.sort || 'desc';
 | 
			
		||||
	const [sort, sortError] = it(params.sort).expect.string().or('desc asc').default('desc').qed();
 | 
			
		||||
	if (sortError) return rej('invalid sort param');
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Like from '../../../models/like';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
import User from '../../../models/user';
 | 
			
		||||
| 
						 | 
				
			
			@ -19,19 +19,12 @@ import notify from '../../../common/notify';
 | 
			
		|||
module.exports = (params, user) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'post_id' parameter
 | 
			
		||||
		let postId = params.post_id;
 | 
			
		||||
		if (postId === undefined || postId === null) {
 | 
			
		||||
			return rej('post_id is required');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Validate id
 | 
			
		||||
		if (!mongo.ObjectID.isValid(postId)) {
 | 
			
		||||
			return rej('incorrect post_id');
 | 
			
		||||
		}
 | 
			
		||||
		const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
		if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
		// Get likee
 | 
			
		||||
		const post = await Post.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(postId)
 | 
			
		||||
			_id: postId
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Like from '../../../models/like';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
import User from '../../../models/user';
 | 
			
		||||
| 
						 | 
				
			
			@ -19,19 +19,12 @@ import User from '../../../models/user';
 | 
			
		|||
module.exports = (params, user) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'post_id' parameter
 | 
			
		||||
		let postId = params.post_id;
 | 
			
		||||
		if (postId === undefined || postId === null) {
 | 
			
		||||
			return rej('post_id is required');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Validate id
 | 
			
		||||
		if (!mongo.ObjectID.isValid(postId)) {
 | 
			
		||||
			return rej('incorrect post_id');
 | 
			
		||||
		}
 | 
			
		||||
		const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
		if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
		// Get likee
 | 
			
		||||
		const post = await Post.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(postId)
 | 
			
		||||
			_id: postId
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import getFriends from '../../common/get-friends';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
| 
						 | 
				
			
			@ -19,33 +19,31 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'following' parameter
 | 
			
		||||
	const following = params.following;
 | 
			
		||||
	const [following, followingError] =
 | 
			
		||||
		it(params.following).expect.boolean().default(false).qed();
 | 
			
		||||
	if (followingError) return rej('invalid following param');
 | 
			
		||||
 | 
			
		||||
	// Get 'limit' parameter
 | 
			
		||||
	let limit = params.limit;
 | 
			
		||||
	if (limit !== undefined && limit !== null) {
 | 
			
		||||
		limit = parseInt(limit, 10);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== null) {
 | 
			
		||||
		return rej('cannot set since_id and max_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Construct query
 | 
			
		||||
	const query = {
 | 
			
		||||
		mentions: user._id
 | 
			
		||||
	};
 | 
			
		||||
	} as any;
 | 
			
		||||
 | 
			
		||||
	const sort = {
 | 
			
		||||
		_id: -1
 | 
			
		||||
| 
						 | 
				
			
			@ -59,14 +57,14 @@ module.exports = (params, user) =>
 | 
			
		|||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (since) {
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../../it';
 | 
			
		||||
import Vote from '../../../models/poll-vote';
 | 
			
		||||
import Post from '../../../models/post';
 | 
			
		||||
import notify from '../../../common/notify';
 | 
			
		||||
| 
						 | 
				
			
			@ -18,19 +18,12 @@ import notify from '../../../common/notify';
 | 
			
		|||
module.exports = (params, user) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'post_id' parameter
 | 
			
		||||
		const postId = params.post_id;
 | 
			
		||||
		if (postId === undefined || postId === null) {
 | 
			
		||||
			return rej('post_id is required');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Validate id
 | 
			
		||||
		if (!mongo.ObjectID.isValid(postId)) {
 | 
			
		||||
			return rej('incorrect post_id');
 | 
			
		||||
		}
 | 
			
		||||
		const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
		if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
		// Get votee
 | 
			
		||||
		const post = await Post.findOne({
 | 
			
		||||
			_id: new mongo.ObjectID(postId)
 | 
			
		||||
			_id: postId
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -42,15 +35,12 @@ module.exports = (params, user) =>
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		// Get 'choice' parameter
 | 
			
		||||
		const choice = params.choice;
 | 
			
		||||
		if (choice == null) {
 | 
			
		||||
			return rej('choice is required');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Validate choice
 | 
			
		||||
		if (!post.poll.choices.some(x => x.id == choice)) {
 | 
			
		||||
			return rej('invalid choice');
 | 
			
		||||
		}
 | 
			
		||||
		const [choice, choiceError] =
 | 
			
		||||
			it(params.choice).expect.string()
 | 
			
		||||
				.required()
 | 
			
		||||
				.validate(c => post.poll.choices.some(x => x.id == c))
 | 
			
		||||
				.qed();
 | 
			
		||||
		if (choiceError) return rej('invalid choice param');
 | 
			
		||||
 | 
			
		||||
		// if already voted
 | 
			
		||||
		const exist = await Vote.findOne({
 | 
			
		||||
| 
						 | 
				
			
			@ -76,8 +66,6 @@ module.exports = (params, user) =>
 | 
			
		|||
		const inc = {};
 | 
			
		||||
		inc[`poll.choices.${findWithAttr(post.poll.choices, 'id', choice)}.votes`] = 1;
 | 
			
		||||
 | 
			
		||||
		console.log(inc);
 | 
			
		||||
 | 
			
		||||
		// Increment likes count
 | 
			
		||||
		Post.update({ _id: post._id }, {
 | 
			
		||||
			$inc: inc
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,42 +18,28 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Get 'sort' parameter
 | 
			
		||||
	let sort = params.sort || 'desc';
 | 
			
		||||
	const [sort, sortError] = it(params.sort).expect.string().or('desc asc').default('desc').qed();
 | 
			
		||||
	if (sortError) return rej('invalid sort param');
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
		return rej('post not found', 'POST_NOT_FOUND');
 | 
			
		||||
		return rej('post not found');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Issue query
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,39 +18,33 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// Get 'limit' parameter
 | 
			
		||||
	let limit = params.limit;
 | 
			
		||||
	if (limit !== undefined && limit !== null) {
 | 
			
		||||
		limit = parseInt(limit, 10);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== null) {
 | 
			
		||||
		return rej('cannot set since_id and max_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Lookup post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
		return rej('post not found', 'POST_NOT_FOUND');
 | 
			
		||||
		return rej('post not found');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Construct query
 | 
			
		||||
| 
						 | 
				
			
			@ -59,15 +53,15 @@ module.exports = (params, user) =>
 | 
			
		|||
	};
 | 
			
		||||
	const query = {
 | 
			
		||||
		repost_id: post._id
 | 
			
		||||
	};
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
	} as any;
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
const escapeRegexp = require('escape-regexp');
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
| 
						 | 
				
			
			@ -20,31 +21,16 @@ module.exports = (params, me) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'query' parameter
 | 
			
		||||
	let query = params.query;
 | 
			
		||||
	if (query === undefined || query === null || query.trim() === '') {
 | 
			
		||||
		return rej('query is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [query, queryError] = it(params.query).expect.string().required().trim().validate(x => x != '').qed();
 | 
			
		||||
	if (queryError) return rej('invalid query param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Get 'max' parameter
 | 
			
		||||
	let max = params.max;
 | 
			
		||||
	if (max !== undefined && max !== null) {
 | 
			
		||||
		max = parseInt(max, 10);
 | 
			
		||||
 | 
			
		||||
		// From 1 to 30
 | 
			
		||||
		if (!(1 <= max && max <= 30)) {
 | 
			
		||||
			return rej('invalid max range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		max = 10;
 | 
			
		||||
	}
 | 
			
		||||
	const [max, maxErr] = it(params.max).expect.number().range(1, 30).default(10).qed();
 | 
			
		||||
	if (maxErr) return rej('invalid max param');
 | 
			
		||||
 | 
			
		||||
	// If Elasticsearch is available, search by it
 | 
			
		||||
	// If not, search by MongoDB
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,19 +18,12 @@ module.exports = (params, user) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'post_id' parameter
 | 
			
		||||
	const postId = params.post_id;
 | 
			
		||||
	if (postId === undefined || postId === null) {
 | 
			
		||||
		return rej('post_id is required');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Validate id
 | 
			
		||||
	if (!mongo.ObjectID.isValid(postId)) {
 | 
			
		||||
		return rej('incorrect post_id');
 | 
			
		||||
	}
 | 
			
		||||
	const [postId, postIdErr] = it(params.post_id, 'id', true);
 | 
			
		||||
	if (postIdErr) return rej('invalid post_id param');
 | 
			
		||||
 | 
			
		||||
	// Get post
 | 
			
		||||
	const post = await Post.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(postId)
 | 
			
		||||
		_id: postId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	if (post === null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import getFriends from '../../common/get-friends';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
| 
						 | 
				
			
			@ -20,23 +20,19 @@ 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);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== null) {
 | 
			
		||||
		return rej('cannot set since_id and max_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,15 +47,15 @@ module.exports = (params, user, app) =>
 | 
			
		|||
		user_id: {
 | 
			
		||||
			$in: followingIds
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
	} as any;
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import { validateUsername } from '../../models/user';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,15 +17,8 @@ module.exports = async (params) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'username' parameter
 | 
			
		||||
	const username = params.username;
 | 
			
		||||
	if (username == null || username == '') {
 | 
			
		||||
		return rej('username-is-required');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Validate username
 | 
			
		||||
	if (!validateUsername(username)) {
 | 
			
		||||
		return rej('invalid-username');
 | 
			
		||||
	}
 | 
			
		||||
	const [username, usernameError] = it(params.username).expect.string().required().trim().validate(validateUsername).qed();
 | 
			
		||||
	if (usernameError) return rej('invalid username param');
 | 
			
		||||
 | 
			
		||||
	// Get exist
 | 
			
		||||
	const exist = await User
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../it';
 | 
			
		||||
import User from '../models/user';
 | 
			
		||||
import serialize from '../serializers/user';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,23 +17,19 @@ import serialize from '../serializers/user';
 | 
			
		|||
module.exports = (params, me) =>
 | 
			
		||||
	new Promise(async (res, rej) => {
 | 
			
		||||
		// Get 'limit' parameter
 | 
			
		||||
		let limit = params.limit;
 | 
			
		||||
		if (limit !== undefined && limit !== null) {
 | 
			
		||||
			limit = parseInt(limit, 10);
 | 
			
		||||
		const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
		if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
			// From 1 to 100
 | 
			
		||||
			if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
				return rej('invalid limit range');
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			limit = 10;
 | 
			
		||||
		}
 | 
			
		||||
		// Get 'since_id' parameter
 | 
			
		||||
		const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
		if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
		const since = params.since_id || null;
 | 
			
		||||
		const max = params.max_id || null;
 | 
			
		||||
		// 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 (since !== null && max !== null) {
 | 
			
		||||
		if (sinceId !== null && maxId !== null) {
 | 
			
		||||
			return rej('cannot set since_id and max_id');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,15 +37,15 @@ module.exports = (params, me) =>
 | 
			
		|||
		const sort = {
 | 
			
		||||
			_id: -1
 | 
			
		||||
		};
 | 
			
		||||
		const query = {};
 | 
			
		||||
		if (since !== null) {
 | 
			
		||||
		const query = {} as any;
 | 
			
		||||
		if (sinceId) {
 | 
			
		||||
			sort._id = 1;
 | 
			
		||||
			query._id = {
 | 
			
		||||
				$gt: new mongo.ObjectID(since)
 | 
			
		||||
				$gt: sinceId
 | 
			
		||||
			};
 | 
			
		||||
		} else if (max !== null) {
 | 
			
		||||
		} else if (maxId) {
 | 
			
		||||
			query._id = {
 | 
			
		||||
				$lt: new mongo.ObjectID(max)
 | 
			
		||||
				$lt: maxId
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import Following from '../../models/following';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
| 
						 | 
				
			
			@ -20,33 +20,24 @@ module.exports = (params, me) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	const userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null) {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id, 'id', true);
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Get 'iknow' parameter
 | 
			
		||||
	const iknow = params.iknow;
 | 
			
		||||
	const [iknow, iknowErr] = it(params.iknow).expect.boolean().default(false).qed();
 | 
			
		||||
	if (iknowErr) return rej('invalid iknow param');
 | 
			
		||||
 | 
			
		||||
	// 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'cursor' parameter
 | 
			
		||||
	const cursor = params.cursor || null;
 | 
			
		||||
	const [cursor, cursorErr] = it(params.cursor).expect.id().default(null).qed();
 | 
			
		||||
	if (cursorErr) return rej('invalid cursor param');
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
	const user = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +52,7 @@ module.exports = (params, me) =>
 | 
			
		|||
	const query = {
 | 
			
		||||
		followee_id: user._id,
 | 
			
		||||
		deleted_at: { $exists: false }
 | 
			
		||||
	};
 | 
			
		||||
	} as any;
 | 
			
		||||
 | 
			
		||||
	// ログインしていてかつ iknow フラグがあるとき
 | 
			
		||||
	if (me && iknow) {
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +67,7 @@ module.exports = (params, me) =>
 | 
			
		|||
	// カーソルが指定されている場合
 | 
			
		||||
	if (cursor) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(cursor)
 | 
			
		||||
			$lt: cursor
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import Following from '../../models/following';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
| 
						 | 
				
			
			@ -20,33 +20,24 @@ module.exports = (params, me) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	const userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null) {
 | 
			
		||||
		return rej('user_id is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id, 'id', true);
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Get 'iknow' parameter
 | 
			
		||||
	const iknow = params.iknow;
 | 
			
		||||
	const [iknow, iknowErr] = it(params.iknow).expect.boolean().default(false).qed();
 | 
			
		||||
	if (iknowErr) return rej('invalid iknow param');
 | 
			
		||||
 | 
			
		||||
	// 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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'cursor' parameter
 | 
			
		||||
	const cursor = params.cursor || null;
 | 
			
		||||
	const [cursor, cursorErr] = it(params.cursor).expect.id().default(null).qed();
 | 
			
		||||
	if (cursorErr) return rej('invalid cursor param');
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
	const user = await User.findOne({
 | 
			
		||||
		_id: new mongo.ObjectID(userId)
 | 
			
		||||
		_id: userId
 | 
			
		||||
	}, {
 | 
			
		||||
		fields: {
 | 
			
		||||
			_id: true
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +52,7 @@ module.exports = (params, me) =>
 | 
			
		|||
	const query = {
 | 
			
		||||
		follower_id: user._id,
 | 
			
		||||
		deleted_at: { $exists: false }
 | 
			
		||||
	};
 | 
			
		||||
	} as any;
 | 
			
		||||
 | 
			
		||||
	// ログインしていてかつ iknow フラグがあるとき
 | 
			
		||||
	if (me && iknow) {
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +67,7 @@ module.exports = (params, me) =>
 | 
			
		|||
	// カーソルが指定されている場合
 | 
			
		||||
	if (cursor) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(cursor)
 | 
			
		||||
			$lt: cursor
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import Post from '../../models/post';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/post';
 | 
			
		||||
| 
						 | 
				
			
			@ -19,56 +19,44 @@ module.exports = (params, me) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	let userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null || userId === '') {
 | 
			
		||||
		userId = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id, 'id');
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Get 'username' parameter
 | 
			
		||||
	let username = params.username;
 | 
			
		||||
	if (username === undefined || username === null || username === '') {
 | 
			
		||||
		username = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [username, usernameErr] = it(params.username, 'string');
 | 
			
		||||
	if (usernameErr) return rej('invalid username param');
 | 
			
		||||
 | 
			
		||||
	if (userId === null && username === null) {
 | 
			
		||||
		return rej('user_id or username is required');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get 'with_replies' parameter
 | 
			
		||||
	let withReplies = params.with_replies;
 | 
			
		||||
	if (withReplies == null) {
 | 
			
		||||
		withReplies = true;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'include_replies' parameter
 | 
			
		||||
	const [includeReplies, includeRepliesErr] = it(params.include_replies).expect.boolean().default(true).qed();
 | 
			
		||||
	if (includeRepliesErr) return rej('invalid include_replies param');
 | 
			
		||||
 | 
			
		||||
	// Get 'with_media' parameter
 | 
			
		||||
	let withMedia = params.with_media;
 | 
			
		||||
	if (withMedia == null) {
 | 
			
		||||
		withMedia = false;
 | 
			
		||||
	}
 | 
			
		||||
	const [withMedia, withMediaErr] = it(params.with_media).expect.boolean().default(false).qed();
 | 
			
		||||
	if (withMediaErr) return rej('invalid with_media param');
 | 
			
		||||
 | 
			
		||||
	// Get 'limit' parameter
 | 
			
		||||
	let limit = params.limit;
 | 
			
		||||
	if (limit !== undefined && limit !== null) {
 | 
			
		||||
		limit = parseInt(limit, 10);
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
		// From 1 to 100
 | 
			
		||||
		if (!(1 <= limit && limit <= 100)) {
 | 
			
		||||
			return rej('invalid limit range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		limit = 10;
 | 
			
		||||
	}
 | 
			
		||||
	// Get 'since_id' parameter
 | 
			
		||||
	const [sinceId, sinceIdErr] = it(params.since_id).expect.id().qed();
 | 
			
		||||
	if (sinceIdErr) return rej('invalid since_id param');
 | 
			
		||||
 | 
			
		||||
	const since = params.since_id || null;
 | 
			
		||||
	const max = params.max_id || null;
 | 
			
		||||
	// 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 (since !== null && max !== null) {
 | 
			
		||||
	if (sinceId !== null && maxId !== null) {
 | 
			
		||||
		return rej('cannot set since_id and max_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const q = userId != null
 | 
			
		||||
		? { _id: new mongo.ObjectID(userId) }
 | 
			
		||||
		? { _id: userId }
 | 
			
		||||
		: { username_lower: username.toLowerCase() } ;
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
| 
						 | 
				
			
			@ -88,19 +76,19 @@ module.exports = (params, me) =>
 | 
			
		|||
	};
 | 
			
		||||
	const query = {
 | 
			
		||||
		user_id: user._id
 | 
			
		||||
	};
 | 
			
		||||
	if (since !== null) {
 | 
			
		||||
	} as any;
 | 
			
		||||
	if (sinceId) {
 | 
			
		||||
		sort._id = 1;
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$gt: new mongo.ObjectID(since)
 | 
			
		||||
			$gt: sinceId
 | 
			
		||||
		};
 | 
			
		||||
	} else if (max !== null) {
 | 
			
		||||
	} else if (maxId) {
 | 
			
		||||
		query._id = {
 | 
			
		||||
			$lt: new mongo.ObjectID(max)
 | 
			
		||||
			$lt: maxId
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!withReplies) {
 | 
			
		||||
	if (!includeReplies) {
 | 
			
		||||
		query.reply_to_id = null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
import getFriends from '../../common/get-friends';
 | 
			
		||||
| 
						 | 
				
			
			@ -18,25 +19,12 @@ module.exports = (params, me) =>
 | 
			
		|||
	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 [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// ID list of the user itself and other users who the user follows
 | 
			
		||||
	const followingIds = await getFriends(me._id);
 | 
			
		||||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
import config from '../../../conf';
 | 
			
		||||
| 
						 | 
				
			
			@ -20,31 +21,16 @@ module.exports = (params, me) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'query' parameter
 | 
			
		||||
	let query = params.query;
 | 
			
		||||
	if (query === undefined || query === null || query.trim() === '') {
 | 
			
		||||
		return rej('query is required');
 | 
			
		||||
	}
 | 
			
		||||
	const [query, queryError] = it(params.query).expect.string().required().trim().validate(x => x != '').qed();
 | 
			
		||||
	if (queryError) return rej('invalid query param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Get 'max' parameter
 | 
			
		||||
	let max = params.max;
 | 
			
		||||
	if (max !== undefined && max !== null) {
 | 
			
		||||
		max = parseInt(max, 10);
 | 
			
		||||
 | 
			
		||||
		// From 1 to 30
 | 
			
		||||
		if (!(1 <= max && max <= 30)) {
 | 
			
		||||
			return rej('invalid max range');
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		max = 10;
 | 
			
		||||
	}
 | 
			
		||||
	const [max, maxErr] = it(params.max).expect.number().range(1, 30).default(10).qed();
 | 
			
		||||
	if (maxErr) return rej('invalid max param');
 | 
			
		||||
 | 
			
		||||
	// If Elasticsearch is available, search by it
 | 
			
		||||
	// If not, search by MongoDB
 | 
			
		||||
| 
						 | 
				
			
			@ -3,8 +3,9 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import { validateUsername } from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -18,37 +19,16 @@ module.exports = (params, me) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'query' parameter
 | 
			
		||||
	let query = params.query;
 | 
			
		||||
	if (query === undefined || query === null || query.trim() === '') {
 | 
			
		||||
		return rej('query is required');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	query = query.trim();
 | 
			
		||||
 | 
			
		||||
	if (!/^[a-zA-Z0-9-]+$/.test(query)) {
 | 
			
		||||
		return rej('invalid query');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 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 [query, queryError] = it(params.query).expect.string().required().trim().validate(validateUsername).qed();
 | 
			
		||||
	if (queryError) return rej('invalid query param');
 | 
			
		||||
 | 
			
		||||
	// Get 'offset' parameter
 | 
			
		||||
	let offset = params.offset;
 | 
			
		||||
	if (offset !== undefined && offset !== null) {
 | 
			
		||||
		offset = parseInt(offset, 10);
 | 
			
		||||
	} else {
 | 
			
		||||
		offset = 0;
 | 
			
		||||
	}
 | 
			
		||||
	const [offset, offsetErr] = it(params.offset).expect.number().min(0).default(0).qed();
 | 
			
		||||
	if (offsetErr) return rej('invalid offset param');
 | 
			
		||||
 | 
			
		||||
	// Get 'limit' parameter
 | 
			
		||||
	const [limit, limitErr] = it(params.limit).expect.number().range(1, 100).default(10).qed();
 | 
			
		||||
	if (limitErr) return rej('invalid limit param');
 | 
			
		||||
 | 
			
		||||
	const users = await User
 | 
			
		||||
		.find({
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Module dependencies
 | 
			
		||||
 */
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import it from '../../it';
 | 
			
		||||
import User from '../../models/user';
 | 
			
		||||
import serialize from '../../serializers/user';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,28 +18,19 @@ module.exports = (params, me) =>
 | 
			
		|||
	new Promise(async (res, rej) =>
 | 
			
		||||
{
 | 
			
		||||
	// Get 'user_id' parameter
 | 
			
		||||
	let userId = params.user_id;
 | 
			
		||||
	if (userId === undefined || userId === null || userId === '') {
 | 
			
		||||
		userId = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [userId, userIdErr] = it(params.user_id, 'id');
 | 
			
		||||
	if (userIdErr) return rej('invalid user_id param');
 | 
			
		||||
 | 
			
		||||
	// Get 'username' parameter
 | 
			
		||||
	let username = params.username;
 | 
			
		||||
	if (username === undefined || username === null || username === '') {
 | 
			
		||||
		username = null;
 | 
			
		||||
	}
 | 
			
		||||
	const [username, usernameErr] = it(params.username, 'string');
 | 
			
		||||
	if (usernameErr) return rej('invalid username param');
 | 
			
		||||
 | 
			
		||||
	if (userId === null && username === null) {
 | 
			
		||||
		return rej('user_id or username is required');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Validate id
 | 
			
		||||
	if (userId && !mongo.ObjectID.isValid(userId)) {
 | 
			
		||||
		return rej('incorrect user_id');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const q = userId != null
 | 
			
		||||
		? { _id: new mongo.ObjectID(userId) }
 | 
			
		||||
		? { _id: userId }
 | 
			
		||||
		: { username_lower: username.toLowerCase() } ;
 | 
			
		||||
 | 
			
		||||
	// Lookup user
 | 
			
		||||
							
								
								
									
										593
									
								
								src/api/it.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										593
									
								
								src/api/it.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,593 @@
 | 
			
		|||
/**
 | 
			
		||||
 * it
 | 
			
		||||
 * 楽しいバリデーション
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Usage Examples
 | 
			
		||||
 *
 | 
			
		||||
 * const [val, err] = it(x).must.be.a.string().or('asc desc').default('desc').qed();
 | 
			
		||||
 * → xは文字列でなければならず、'asc'または'desc'でなければならない。省略された場合のデフォルトは'desc'とする。
 | 
			
		||||
 *
 | 
			
		||||
 * const [val, err] = it(x).must.be.a.number().required().range(0, 100).qed();
 | 
			
		||||
 * → xは数値でなければならず、かつ0~100の範囲内でなければならない。この値は省略することはできない。
 | 
			
		||||
 *
 | 
			
		||||
 * const [val, err] = it(x).must.be.an.array().unique().required().validate(x => x[0] != 'strawberry pasta').qed();
 | 
			
		||||
 * → xは配列でなければならず、かつ中身が重複していてはならない。この値を省略することはできない。そして配列の最初の要素が'strawberry pasta'という文字列であってはならない。
 | 
			
		||||
 *
 | 
			
		||||
 * ・意味的に矛盾するので、required と default は併用できません。
 | 
			
		||||
 *
 | 
			
		||||
 * ~糖衣構文~
 | 
			
		||||
 * const [val, err] = it(x).must.be.a.string().required().qed();
 | 
			
		||||
 * は
 | 
			
		||||
 * const [val, err] = it(x, 'string', true);
 | 
			
		||||
 * と書けます
 | 
			
		||||
 *
 | 
			
		||||
 * ~BDD風記法~
 | 
			
		||||
 * must.be.a(n) の代わりに expect とも書けます:
 | 
			
		||||
 * const [val, err] = it(x).expect.string().required().qed();
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * null と undefined の扱い
 | 
			
		||||
 *
 | 
			
		||||
 * 「値が null または undefined」な状態を「値が空である」と表現しています。
 | 
			
		||||
 * 値が空である場合、バリデータやその他の処理メソッドは呼ばれません。
 | 
			
		||||
 *
 | 
			
		||||
 * 内部的には null と undefined を次のように区別しています:
 | 
			
		||||
 * null ... 値が「無い」と明示されている
 | 
			
		||||
 * undefined ... 値を指定していない
 | 
			
		||||
 *
 | 
			
		||||
 * 例えばアカウントのプロフィールを更新するAPIに次のデータを含むリクエストが来たとします:
 | 
			
		||||
 * { name: 'Alice' }
 | 
			
		||||
 * アカウントには本来、他にも birthday といったフィールドがありますが、
 | 
			
		||||
 * このリクエストではそれに触れず、ただ単に name フィールドを更新することを要求しています。
 | 
			
		||||
 * ここで、このリクエストにおける birthday フィールドは undefined なわけですが、
 | 
			
		||||
 * それはnull(=birthdayを未設定にしたい)とは違うものです。
 | 
			
		||||
 * undefined も null も区別しないとしたら、触れていないフィールドまでリセットされることになってしまいます。
 | 
			
		||||
 * ですので、undefined と null は区別しています。
 | 
			
		||||
 *
 | 
			
		||||
 * 明示的に null を許可しない限り、null はエラーになります。
 | 
			
		||||
 * null を許可する場合は nullable をプリフィックスします:
 | 
			
		||||
 * const [val, err] = it(x).must.be.a.nullable.string().required().qed();
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import * as mongo from 'mongodb';
 | 
			
		||||
import hasDuplicates from '../common/has-duplicates';
 | 
			
		||||
 | 
			
		||||
type Validator<T> = (value: T) => boolean | Error;
 | 
			
		||||
 | 
			
		||||
interface Query {
 | 
			
		||||
	/**
 | 
			
		||||
	 * qedはQ.E.D.でもあり'QueryEnD'の略でもある
 | 
			
		||||
	 */
 | 
			
		||||
	qed: () => [any, Error];
 | 
			
		||||
 | 
			
		||||
	required: () => Query;
 | 
			
		||||
 | 
			
		||||
	default: (value: any) => Query;
 | 
			
		||||
 | 
			
		||||
	validate: (validator: Validator<any>) => Query;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class QueryCore implements Query {
 | 
			
		||||
	value: any;
 | 
			
		||||
	error: Error;
 | 
			
		||||
 | 
			
		||||
	constructor(value: any, nullable: boolean = false) {
 | 
			
		||||
		if (value === null && !nullable) {
 | 
			
		||||
			this.value = undefined;
 | 
			
		||||
			this.error = new Error('must-be-not-a-null');
 | 
			
		||||
		} else {
 | 
			
		||||
			this.value = value;
 | 
			
		||||
			this.error = null;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get isUndefined() {
 | 
			
		||||
		return this.value === undefined;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get isNull() {
 | 
			
		||||
		return this.value === null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get isEmpty() {
 | 
			
		||||
		return this.isUndefined || this.isNull;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が空、またはエラーが存在しているなどして、処理をスキップするべきか否か
 | 
			
		||||
	 */
 | 
			
		||||
	get shouldSkip() {
 | 
			
		||||
		return this.error !== null || this.isEmpty;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が指定されていない(=undefined)ときにエラーにします
 | 
			
		||||
	 */
 | 
			
		||||
	required() {
 | 
			
		||||
		if (this.error === null && this.isUndefined) {
 | 
			
		||||
			this.error = new Error('required');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が設定されていない(=undefined)ときにデフォルトで設定する値を設定します
 | 
			
		||||
	 */
 | 
			
		||||
	default(value: any) {
 | 
			
		||||
		if (this.isUndefined) {
 | 
			
		||||
			this.value = value;
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値およびエラーを取得します
 | 
			
		||||
	 */
 | 
			
		||||
	qed(): [any, Error] {
 | 
			
		||||
		return [this.value, this.error];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値に対して妥当性を検証します
 | 
			
		||||
	 * バリデータが false またはエラーを返した場合エラーにします
 | 
			
		||||
	 * @param validator バリデータ
 | 
			
		||||
	 */
 | 
			
		||||
	validate(validator: Validator<any>) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		const result = validator(this.value);
 | 
			
		||||
		if (result === false) {
 | 
			
		||||
			this.error = new Error('invalid-format');
 | 
			
		||||
		} else if (result instanceof Error) {
 | 
			
		||||
			this.error = result;
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class BooleanQuery extends QueryCore {
 | 
			
		||||
	value: boolean;
 | 
			
		||||
	error: Error;
 | 
			
		||||
 | 
			
		||||
	constructor(value: any, nullable: boolean = false) {
 | 
			
		||||
		super(value, nullable);
 | 
			
		||||
		if (!this.isEmpty && typeof value != 'boolean') {
 | 
			
		||||
			this.error = new Error('must-be-a-boolean');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が設定されていないときにデフォルトで設定する値を設定します
 | 
			
		||||
	 */
 | 
			
		||||
	default(value: boolean) {
 | 
			
		||||
		return super.default(value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値およびエラーを取得します
 | 
			
		||||
	 */
 | 
			
		||||
	qed(): [boolean, Error] {
 | 
			
		||||
		return super.qed();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値に対して妥当性を検証します
 | 
			
		||||
	 * バリデータが false またはエラーを返した場合エラーにします
 | 
			
		||||
	 * @param validator バリデータ
 | 
			
		||||
	 */
 | 
			
		||||
	validate(validator: Validator<boolean>) {
 | 
			
		||||
		return super.validate(validator);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class NumberQuery extends QueryCore {
 | 
			
		||||
	value: number;
 | 
			
		||||
	error: Error;
 | 
			
		||||
 | 
			
		||||
	constructor(value: any, nullable: boolean = false) {
 | 
			
		||||
		super(value, nullable);
 | 
			
		||||
		if (!this.isEmpty && !Number.isFinite(value)) {
 | 
			
		||||
			this.error = new Error('must-be-a-number');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 値が指定された範囲内にない場合エラーにします
 | 
			
		||||
	 * @param min 下限
 | 
			
		||||
	 * @param max 上限
 | 
			
		||||
	 */
 | 
			
		||||
	range(min: number, max: number) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (this.value < min || this.value > max) {
 | 
			
		||||
			this.error = new Error('invalid-range');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が指定された下限より下回っている場合エラーにします
 | 
			
		||||
	 * @param value 下限
 | 
			
		||||
	 */
 | 
			
		||||
	min(value: number) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (this.value < value) {
 | 
			
		||||
			this.error = new Error('invalid-range');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が指定された上限より上回っている場合エラーにします
 | 
			
		||||
	 * @param value 上限
 | 
			
		||||
	 */
 | 
			
		||||
	max(value: number) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (this.value > value) {
 | 
			
		||||
			this.error = new Error('invalid-range');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が設定されていないときにデフォルトで設定する値を設定します
 | 
			
		||||
	 */
 | 
			
		||||
	default(value: number) {
 | 
			
		||||
		return super.default(value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値およびエラーを取得します
 | 
			
		||||
	 */
 | 
			
		||||
	qed(): [number, Error] {
 | 
			
		||||
		return super.qed();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値に対して妥当性を検証します
 | 
			
		||||
	 * バリデータが false またはエラーを返した場合エラーにします
 | 
			
		||||
	 * @param validator バリデータ
 | 
			
		||||
	 */
 | 
			
		||||
	validate(validator: Validator<number>) {
 | 
			
		||||
		return super.validate(validator);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class StringQuery extends QueryCore {
 | 
			
		||||
	value: string;
 | 
			
		||||
	error: Error;
 | 
			
		||||
 | 
			
		||||
	constructor(value: any, nullable: boolean = false) {
 | 
			
		||||
		super(value, nullable);
 | 
			
		||||
		if (!this.isEmpty && typeof value != 'string') {
 | 
			
		||||
			this.error = new Error('must-be-a-string');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 文字数が指定された範囲内にない場合エラーにします
 | 
			
		||||
	 * @param min 下限
 | 
			
		||||
	 * @param max 上限
 | 
			
		||||
	 */
 | 
			
		||||
	range(min: number, max: number) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (this.value.length < min || this.value.length > max) {
 | 
			
		||||
			this.error = new Error('invalid-range');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	trim() {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		this.value = this.value.trim();
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が設定されていないときにデフォルトで設定する値を設定します
 | 
			
		||||
	 */
 | 
			
		||||
	default(value: string) {
 | 
			
		||||
		return super.default(value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値およびエラーを取得します
 | 
			
		||||
	 */
 | 
			
		||||
	qed(): [string, Error] {
 | 
			
		||||
		return super.qed();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値に対して妥当性を検証します
 | 
			
		||||
	 * バリデータが false またはエラーを返した場合エラーにします
 | 
			
		||||
	 * @param validator バリデータ
 | 
			
		||||
	 */
 | 
			
		||||
	validate(validator: Validator<string>) {
 | 
			
		||||
		return super.validate(validator);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの文字列が、与えられたパターン内の文字列のどれかと一致するか検証します
 | 
			
		||||
	 * どれとも一致しない場合エラーにします
 | 
			
		||||
	 * @param pattern 文字列の配列またはスペースで区切られた文字列
 | 
			
		||||
	 */
 | 
			
		||||
	or(pattern: string | string[]) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (typeof pattern == 'string') pattern = pattern.split(' ');
 | 
			
		||||
		const match = pattern.some(x => x === this.value);
 | 
			
		||||
		if (!match) this.error = new Error('not-match-pattern');
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの文字列が、与えられた正規表現と一致するか検証します
 | 
			
		||||
	 * 一致しない場合エラーにします
 | 
			
		||||
	 * @param pattern 正規表現
 | 
			
		||||
	 */
 | 
			
		||||
	match(pattern: RegExp) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (!pattern.test(this.value)) this.error = new Error('not-match-pattern');
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ArrayQuery extends QueryCore {
 | 
			
		||||
	value: any[];
 | 
			
		||||
	error: Error;
 | 
			
		||||
 | 
			
		||||
	constructor(value: any, nullable: boolean = false) {
 | 
			
		||||
		super(value, nullable);
 | 
			
		||||
		if (!this.isEmpty && !Array.isArray(value)) {
 | 
			
		||||
			this.error = new Error('must-be-an-array');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 配列の値がユニークでない場合(=重複した項目がある場合)エラーにします
 | 
			
		||||
	 */
 | 
			
		||||
	unique() {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (hasDuplicates(this.value)) {
 | 
			
		||||
			this.error = new Error('must-be-unique');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 配列の長さが指定された範囲内にない場合エラーにします
 | 
			
		||||
	 * @param min 下限
 | 
			
		||||
	 * @param max 上限
 | 
			
		||||
	 */
 | 
			
		||||
	range(min: number, max: number) {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (this.value.length < min || this.value.length > max) {
 | 
			
		||||
			this.error = new Error('invalid-range');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの配列内の要素すべてが文字列であるか検証します
 | 
			
		||||
	 * ひとつでも文字列以外の要素が存在する場合エラーにします
 | 
			
		||||
	 */
 | 
			
		||||
	allString() {
 | 
			
		||||
		if (this.shouldSkip) return this;
 | 
			
		||||
		if (this.value.some(x => typeof x != 'string')) {
 | 
			
		||||
			this.error = new Error('dirty-array');
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が設定されていないときにデフォルトで設定する値を設定します
 | 
			
		||||
	 */
 | 
			
		||||
	default(value: any[]) {
 | 
			
		||||
		return super.default(value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値およびエラーを取得します
 | 
			
		||||
	 */
 | 
			
		||||
	qed(): [any[], Error] {
 | 
			
		||||
		return super.qed();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値に対して妥当性を検証します
 | 
			
		||||
	 * バリデータが false またはエラーを返した場合エラーにします
 | 
			
		||||
	 * @param validator バリデータ
 | 
			
		||||
	 */
 | 
			
		||||
	validate(validator: Validator<any[]>) {
 | 
			
		||||
		return super.validate(validator);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class IdQuery extends QueryCore {
 | 
			
		||||
	value: mongo.ObjectID;
 | 
			
		||||
	error: Error;
 | 
			
		||||
 | 
			
		||||
	constructor(value: any, nullable: boolean = false) {
 | 
			
		||||
		super(value, nullable);
 | 
			
		||||
		if (!this.isEmpty && (typeof value != 'string' || !mongo.ObjectID.isValid(value))) {
 | 
			
		||||
			this.error = new Error('must-be-an-id');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が設定されていないときにデフォルトで設定する値を設定します
 | 
			
		||||
	 */
 | 
			
		||||
	default(value: mongo.ObjectID) {
 | 
			
		||||
		return super.default(value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値およびエラーを取得します
 | 
			
		||||
	 */
 | 
			
		||||
	qed(): [mongo.ObjectID, Error] {
 | 
			
		||||
		return super.qed();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値に対して妥当性を検証します
 | 
			
		||||
	 * バリデータが false またはエラーを返した場合エラーにします
 | 
			
		||||
	 * @param validator バリデータ
 | 
			
		||||
	 */
 | 
			
		||||
	validate(validator: Validator<mongo.ObjectID>) {
 | 
			
		||||
		return super.validate(validator);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ObjectQuery extends QueryCore {
 | 
			
		||||
	value: any;
 | 
			
		||||
	error: Error;
 | 
			
		||||
 | 
			
		||||
	constructor(value: any, nullable: boolean = false) {
 | 
			
		||||
		super(value, nullable);
 | 
			
		||||
		if (!this.isEmpty && typeof value != 'object') {
 | 
			
		||||
			this.error = new Error('must-be-an-object');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値が設定されていないときにデフォルトで設定する値を設定します
 | 
			
		||||
	 */
 | 
			
		||||
	default(value: any) {
 | 
			
		||||
		return super.default(value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値およびエラーを取得します
 | 
			
		||||
	 */
 | 
			
		||||
	qed(): [any, Error] {
 | 
			
		||||
		return super.qed();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * このインスタンスの値に対して妥当性を検証します
 | 
			
		||||
	 * バリデータが false またはエラーを返した場合エラーにします
 | 
			
		||||
	 * @param validator バリデータ
 | 
			
		||||
	 */
 | 
			
		||||
	validate(validator: Validator<any>) {
 | 
			
		||||
		return super.validate(validator);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type It = {
 | 
			
		||||
	must: {
 | 
			
		||||
		be: {
 | 
			
		||||
			a: {
 | 
			
		||||
				string: () => StringQuery;
 | 
			
		||||
				number: () => NumberQuery;
 | 
			
		||||
				boolean: () => BooleanQuery;
 | 
			
		||||
				nullable: {
 | 
			
		||||
					string: () => StringQuery;
 | 
			
		||||
					number: () => NumberQuery;
 | 
			
		||||
					boolean: () => BooleanQuery;
 | 
			
		||||
					id: () => IdQuery;
 | 
			
		||||
					array: () => ArrayQuery;
 | 
			
		||||
					object: () => ObjectQuery;
 | 
			
		||||
				};
 | 
			
		||||
			};
 | 
			
		||||
			an: {
 | 
			
		||||
				id: () => IdQuery;
 | 
			
		||||
				array: () => ArrayQuery;
 | 
			
		||||
				object: () => ObjectQuery;
 | 
			
		||||
			};
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
	expect: {
 | 
			
		||||
		string: () => StringQuery;
 | 
			
		||||
		number: () => NumberQuery;
 | 
			
		||||
		boolean: () => BooleanQuery;
 | 
			
		||||
		id: () => IdQuery;
 | 
			
		||||
		array: () => ArrayQuery;
 | 
			
		||||
		object: () => ObjectQuery;
 | 
			
		||||
		nullable: {
 | 
			
		||||
			string: () => StringQuery;
 | 
			
		||||
			number: () => NumberQuery;
 | 
			
		||||
			boolean: () => BooleanQuery;
 | 
			
		||||
			id: () => IdQuery;
 | 
			
		||||
			array: () => ArrayQuery;
 | 
			
		||||
			object: () => ObjectQuery;
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const it = (value: any) => ({
 | 
			
		||||
	must: {
 | 
			
		||||
		be: {
 | 
			
		||||
			a: {
 | 
			
		||||
				string: () => new StringQuery(value),
 | 
			
		||||
				number: () => new NumberQuery(value),
 | 
			
		||||
				boolean: () => new BooleanQuery(value),
 | 
			
		||||
				nullable: {
 | 
			
		||||
					string: () => new StringQuery(value, true),
 | 
			
		||||
					number: () => new NumberQuery(value, true),
 | 
			
		||||
					boolean: () => new BooleanQuery(value, true),
 | 
			
		||||
					id: () => new IdQuery(value, true),
 | 
			
		||||
					array: () => new ArrayQuery(value, true),
 | 
			
		||||
					object: () => new ObjectQuery(value, true)
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			an: {
 | 
			
		||||
				id: () => new IdQuery(value),
 | 
			
		||||
				array: () => new ArrayQuery(value),
 | 
			
		||||
				object: () => new ObjectQuery(value)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	expect: {
 | 
			
		||||
		string: () => new StringQuery(value),
 | 
			
		||||
		number: () => new NumberQuery(value),
 | 
			
		||||
		boolean: () => new BooleanQuery(value),
 | 
			
		||||
		id: () => new IdQuery(value),
 | 
			
		||||
		array: () => new ArrayQuery(value),
 | 
			
		||||
		object: () => new ObjectQuery(value),
 | 
			
		||||
		nullable: {
 | 
			
		||||
			string: () => new StringQuery(value, true),
 | 
			
		||||
			number: () => new NumberQuery(value, true),
 | 
			
		||||
			boolean: () => new BooleanQuery(value, true),
 | 
			
		||||
			id: () => new IdQuery(value, true),
 | 
			
		||||
			array: () => new ArrayQuery(value, true),
 | 
			
		||||
			object: () => new ObjectQuery(value, true)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
type Type = 'id' | 'string' | 'number' | 'boolean' | 'array' | 'set' | 'object';
 | 
			
		||||
 | 
			
		||||
function x(value: any): It;
 | 
			
		||||
function x(value: any, type: 'id', isRequired?: boolean, validator?: Validator<mongo.ObjectID> | Validator<mongo.ObjectID>[]): [mongo.ObjectID, Error];
 | 
			
		||||
function x(value: any, type: 'string', isRequired?: boolean, validator?: Validator<string> | Validator<string>[]): [string, Error];
 | 
			
		||||
function x(value: any, type: 'number', isRequired?: boolean, validator?: Validator<number> | Validator<number>[]): [number, Error];
 | 
			
		||||
function x(value: any, type: 'boolean', isRequired?: boolean): [boolean, Error];
 | 
			
		||||
function x(value: any, type: 'array', isRequired?: boolean, validator?: Validator<any[]> | Validator<any[]>[]): [any[], Error];
 | 
			
		||||
function x(value: any, type: 'set', isRequired?: boolean, validator?: Validator<any[]> | Validator<any[]>[]): [any[], Error];
 | 
			
		||||
function x(value: any, type: 'object', isRequired?: boolean, validator?: Validator<any> | Validator<any>[]): [any, Error];
 | 
			
		||||
function x(value: any, type?: Type, isRequired?: boolean, validator?: Validator<any> | Validator<any>[]): any {
 | 
			
		||||
	if (typeof type === 'undefined') return it(value);
 | 
			
		||||
 | 
			
		||||
	let q: Query = null;
 | 
			
		||||
 | 
			
		||||
	switch (type) {
 | 
			
		||||
		case 'id': q = it(value).expect.id(); break;
 | 
			
		||||
		case 'string': q = it(value).expect.string(); break;
 | 
			
		||||
		case 'number': q = it(value).expect.number(); break;
 | 
			
		||||
		case 'boolean': q = it(value).expect.boolean(); break;
 | 
			
		||||
		case 'array': q = it(value).expect.array(); break;
 | 
			
		||||
		case 'set': q = it(value).expect.array().unique(); break;
 | 
			
		||||
		case 'object': q = it(value).expect.object(); break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isRequired) q = q.required();
 | 
			
		||||
 | 
			
		||||
	if (validator) {
 | 
			
		||||
		(Array.isArray(validator) ? validator : [validator])
 | 
			
		||||
			.forEach(v => q = q.validate(v));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return q;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default x;
 | 
			
		||||
| 
						 | 
				
			
			@ -7,3 +7,7 @@ const collection = db.get('apps');
 | 
			
		|||
(collection as any).index('secret'); // fuck type definition
 | 
			
		||||
 | 
			
		||||
export default collection as any; // fuck type definition
 | 
			
		||||
 | 
			
		||||
export function isValidNameId(nameId: string): boolean {
 | 
			
		||||
	return typeof nameId == 'string' && /^[a-zA-Z0-9\-]{3,30}$/.test(nameId);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,8 @@
 | 
			
		|||
import db from '../../db/mongodb';
 | 
			
		||||
 | 
			
		||||
export default db.get('messaging_messages') as any; // fuck type definition
 | 
			
		||||
 | 
			
		||||
export function isValidText(text: string): boolean {
 | 
			
		||||
	return text.length <= 1000 && text.trim() != '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,7 @@
 | 
			
		|||
import db from '../../db/mongodb';
 | 
			
		||||
 | 
			
		||||
export default db.get('posts') as any; // fuck type definition
 | 
			
		||||
 | 
			
		||||
export function isValidText(text: string): boolean {
 | 
			
		||||
	return text.length <= 1000 && text.trim() != '';
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,14 @@ export function isValidName(name: string): boolean {
 | 
			
		|||
	return typeof name == 'string' && name.length < 30 && name.trim() != '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isValidDescription(description: string): boolean {
 | 
			
		||||
	return typeof description == 'string' && description.length < 500 && description.trim() != '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isValidLocation(location: string): boolean {
 | 
			
		||||
	return typeof location == 'string' && location.length < 50 && location.trim() != '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isValidBirthday(birthday: string): boolean {
 | 
			
		||||
	return typeof birthday == 'string' && /^([0-9]{4})\-([0-9]{2})-([0-9]{2})$/.test(birthday);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,8 @@ export default (
 | 
			
		|||
	app: any,
 | 
			
		||||
	me?: any,
 | 
			
		||||
	options?: {
 | 
			
		||||
		includeSecret: boolean,
 | 
			
		||||
		includeProfileImageIds: boolean
 | 
			
		||||
		includeSecret?: boolean,
 | 
			
		||||
		includeProfileImageIds?: boolean
 | 
			
		||||
	}
 | 
			
		||||
) => new Promise<any>(async (resolve, reject) => {
 | 
			
		||||
	const opts = options || {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ import deepcopy = require('deepcopy');
 | 
			
		|||
 */
 | 
			
		||||
export default (
 | 
			
		||||
	message: any,
 | 
			
		||||
	me: any,
 | 
			
		||||
	me?: any,
 | 
			
		||||
	options?: {
 | 
			
		||||
		populateRecipient: boolean
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								src/common/has-duplicates.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/common/has-duplicates.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
export default (array: any[]) => (new Set(array)).size !== array.length;
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue