Merge pull request #232 from syuilo/#226

#226、あとTypeScriptにした
This commit is contained in:
syuilo⭐️ 2017-03-03 19:54:40 +09:00 committed by GitHub
commit c8c31322fc
79 changed files with 1381 additions and 1338 deletions

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
});

View File

@ -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

View File

@ -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) {

View File

@ -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
});
}

View File

@ -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({

View File

@ -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({

View File

@ -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

View File

@ -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
};
}

View File

@ -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);

View File

@ -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

View File

@ -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: {

View File

@ -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,

View File

@ -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);

View File

@ -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
};
}

View File

@ -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');
}
}

View File

@ -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

View File

@ -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
});

View File

@ -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({

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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
}, {

View File

@ -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
};
}

View File

@ -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
};
}

View File

@ -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
}
});
}
});

View 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
}
});
}
});

View File

@ -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

View File

@ -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
};
}

View File

@ -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;
}
// テキストが無いかつ添付ファイルも無かったらエラー

View File

@ -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

View File

@ -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
});

View File

@ -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))));
});

View 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))));
});

View File

@ -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 = [];

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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
};
}

View File

@ -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

View File

@ -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

View File

@ -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
};
}

View File

@ -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

View File

@ -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) {

View File

@ -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
};
}

View File

@ -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

View File

@ -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
};
}

View File

@ -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
};
}

View File

@ -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
};
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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({

View File

@ -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
View 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;

View File

@ -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);
}

View File

@ -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() != '';
}

View File

@ -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() != '';
}

View File

@ -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);
}

View File

@ -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 || {

View File

@ -19,7 +19,7 @@ import deepcopy = require('deepcopy');
*/
export default (
message: any,
me: any,
me?: any,
options?: {
populateRecipient: boolean
}

View File

@ -0,0 +1 @@
export default (array: any[]) => (new Set(array)).size !== array.length;