From 9a282e37be5ba847718d198d30eb97f31d11f2a0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 2 Feb 2018 08:06:01 +0900 Subject: wip --- src/api/models/user.ts | 196 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 190 insertions(+), 6 deletions(-) (limited to 'src/api/models/user.ts') diff --git a/src/api/models/user.ts b/src/api/models/user.ts index 018979158f..48a45ac2f7 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -1,14 +1,19 @@ import * as mongo from 'mongodb'; - +import deepcopy = require('deepcopy'); +import rap from '@prezzemolo/rap'; import db from '../../db/mongodb'; -import { IPost } from './post'; +import { IPost, pack as packPost } from './post'; +import Following from './following'; +import Mute from './mute'; +import getFriends from '../common/get-friends'; +import config from '../../conf'; -const collection = db.get('users'); +const User = db.get('users'); -(collection as any).createIndex('username'); // fuck type definition -(collection as any).createIndex('token'); // fuck type definition +User.createIndex('username'); +User.createIndex('token'); -export default collection as any; // fuck type definition +export default User; export function validateUsername(username: string): boolean { return typeof username == 'string' && /^[a-zA-Z0-9\-]{3,20}$/.test(username); @@ -83,3 +88,182 @@ export function init(user): IUser { user.pinned_post_id = new mongo.ObjectID(user.pinned_post_id); return user; } + +/** + * Pack a user for API response + * + * @param user target + * @param me? serializee + * @param options? serialize options + * @return Packed user + */ +export const pack = ( + user: string | mongo.ObjectID | IUser, + me?: string | mongo.ObjectID | IUser, + options?: { + detail?: boolean, + includeSecrets?: boolean + } +) => new Promise(async (resolve, reject) => { + + const opts = Object.assign({ + detail: false, + includeSecrets: false + }, options); + + let _user: any; + + const fields = opts.detail ? { + settings: false + } : { + settings: false, + client_settings: false, + profile: false, + keywords: false, + domains: false + }; + + // Populate the user if 'user' is ID + if (mongo.ObjectID.prototype.isPrototypeOf(user)) { + _user = await User.findOne({ + _id: user + }, { fields }); + } else if (typeof user === 'string') { + _user = await User.findOne({ + _id: new mongo.ObjectID(user) + }, { fields }); + } else { + _user = deepcopy(user); + } + + if (!_user) return reject('invalid user arg.'); + + // Me + const meId: mongo.ObjectID = me + ? mongo.ObjectID.prototype.isPrototypeOf(me) + ? me as mongo.ObjectID + : typeof me === 'string' + ? new mongo.ObjectID(me) + : (me as IUser)._id + : null; + + // Rename _id to id + _user.id = _user._id; + delete _user._id; + + // Remove needless properties + delete _user.latest_post; + + // Remove private properties + delete _user.password; + delete _user.token; + delete _user.two_factor_temp_secret; + delete _user.two_factor_secret; + delete _user.username_lower; + if (_user.twitter) { + delete _user.twitter.access_token; + delete _user.twitter.access_token_secret; + } + delete _user.line; + + // Visible via only the official client + if (!opts.includeSecrets) { + delete _user.email; + delete _user.client_settings; + } + + if (!opts.detail) { + delete _user.two_factor_enabled; + } + + _user.avatar_url = _user.avatar_id != null + ? `${config.drive_url}/${_user.avatar_id}` + : `${config.drive_url}/default-avatar.jpg`; + + _user.banner_url = _user.banner_id != null + ? `${config.drive_url}/${_user.banner_id}` + : null; + + if (!meId || !meId.equals(_user.id) || !opts.detail) { + delete _user.avatar_id; + delete _user.banner_id; + + delete _user.drive_capacity; + } + + if (meId && !meId.equals(_user.id)) { + // Whether the user is following + _user.is_following = (async () => { + const follow = await Following.findOne({ + follower_id: meId, + followee_id: _user.id, + deleted_at: { $exists: false } + }); + return follow !== null; + })(); + + // Whether the user is followed + _user.is_followed = (async () => { + const follow2 = await Following.findOne({ + follower_id: _user.id, + followee_id: meId, + deleted_at: { $exists: false } + }); + return follow2 !== null; + })(); + + // Whether the user is muted + _user.is_muted = (async () => { + const mute = await Mute.findOne({ + muter_id: meId, + mutee_id: _user.id, + deleted_at: { $exists: false } + }); + return mute !== null; + })(); + } + + if (opts.detail) { + if (_user.pinned_post_id) { + // Populate pinned post + _user.pinned_post = packPost(_user.pinned_post_id, meId, { + detail: true + }); + } + + if (meId && !meId.equals(_user.id)) { + const myFollowingIds = await getFriends(meId); + + // Get following you know count + _user.following_you_know_count = Following.count({ + followee_id: { $in: myFollowingIds }, + follower_id: _user.id, + deleted_at: { $exists: false } + }); + + // Get followers you know count + _user.followers_you_know_count = Following.count({ + followee_id: _user.id, + follower_id: { $in: myFollowingIds }, + deleted_at: { $exists: false } + }); + } + } + + // resolve promises in _user object + _user = await rap(_user); + + resolve(_user); +}); + +/* +function img(url) { + return { + thumbnail: { + large: `${url}`, + medium: '', + small: '' + } + }; +} +*/ -- cgit v1.2.3-freya From bcd65d290d25219631bb47570478378a698d0fa0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 4 Feb 2018 14:52:33 +0900 Subject: wip --- src/api/endpoints/aggregation/posts/reactions.ts | 11 +++++++---- src/api/endpoints/aggregation/users.ts | 13 ++++++++----- src/api/endpoints/app/create.ts | 3 +-- src/api/endpoints/channels/show.ts | 2 +- src/api/endpoints/drive/files/create.ts | 2 +- src/api/endpoints/drive/files/update.ts | 3 +-- src/api/endpoints/drive/files/upload_from_url.ts | 2 +- src/api/endpoints/drive/folders/create.ts | 3 +-- src/api/endpoints/drive/folders/update.ts | 3 +-- src/api/endpoints/following/create.ts | 7 +++---- src/api/endpoints/following/delete.ts | 5 ++--- src/api/endpoints/i/update.ts | 3 +-- src/api/endpoints/posts/reactions/create.ts | 9 ++++----- src/api/endpoints/users/posts.ts | 4 ++-- src/api/endpoints/users/search.ts | 2 +- src/api/models/app.ts | 1 + src/api/models/drive-file.ts | 1 + src/api/models/post-reaction.ts | 3 +++ src/api/models/post.ts | 4 +++- src/api/models/user.ts | 1 + src/api/private/signup.ts | 3 +-- src/api/service/twitter.ts | 2 +- src/api/stream/home.ts | 4 ++-- 23 files changed, 48 insertions(+), 43 deletions(-) (limited to 'src/api/models/user.ts') diff --git a/src/api/endpoints/aggregation/posts/reactions.ts b/src/api/endpoints/aggregation/posts/reactions.ts index 2cd4588ae1..790b523be9 100644 --- a/src/api/endpoints/aggregation/posts/reactions.ts +++ b/src/api/endpoints/aggregation/posts/reactions.ts @@ -35,10 +35,13 @@ module.exports = (params) => new Promise(async (res, rej) => { { deleted_at: { $gt: startTime } } ] }, { - _id: false, - post_id: false - }, { - sort: { created_at: -1 } + sort: { + _id: -1 + }, + fields: { + _id: false, + post_id: false + } }); const graph = []; diff --git a/src/api/endpoints/aggregation/users.ts b/src/api/endpoints/aggregation/users.ts index 9eb2d035ec..e38ce92ff9 100644 --- a/src/api/endpoints/aggregation/users.ts +++ b/src/api/endpoints/aggregation/users.ts @@ -17,11 +17,14 @@ module.exports = params => new Promise(async (res, rej) => { const users = await User .find({}, { - _id: false, - created_at: true, - deleted_at: true - }, { - sort: { created_at: -1 } + sort: { + _id: -1 + }, + fields: { + _id: false, + created_at: true, + deleted_at: true + } }); const graph = []; diff --git a/src/api/endpoints/app/create.ts b/src/api/endpoints/app/create.ts index 71633f7def..0f688792a7 100644 --- a/src/api/endpoints/app/create.ts +++ b/src/api/endpoints/app/create.ts @@ -3,8 +3,7 @@ */ import rndstr from 'rndstr'; import $ from 'cafy'; -import App from '../../models/app'; -import { isValidNameId }, { pack } from '../../models/app'; +import App, { isValidNameId, pack } from '../../models/app'; /** * @swagger diff --git a/src/api/endpoints/channels/show.ts b/src/api/endpoints/channels/show.ts index 3238616fa5..332da64675 100644 --- a/src/api/endpoints/channels/show.ts +++ b/src/api/endpoints/channels/show.ts @@ -2,7 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import { default as Channel, IChannel }, { pack } from '../../models/channel'; +import Channel, { IChannel, pack } from '../../models/channel'; /** * Show a channel diff --git a/src/api/endpoints/drive/files/create.ts b/src/api/endpoints/drive/files/create.ts index 7b424f3f5a..96bcace886 100644 --- a/src/api/endpoints/drive/files/create.ts +++ b/src/api/endpoints/drive/files/create.ts @@ -2,7 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import { validateFileName }, { pack } from '../../../models/drive-file'; +import { validateFileName, pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; /** diff --git a/src/api/endpoints/drive/files/update.ts b/src/api/endpoints/drive/files/update.ts index ff65a48f71..83da462113 100644 --- a/src/api/endpoints/drive/files/update.ts +++ b/src/api/endpoints/drive/files/update.ts @@ -3,8 +3,7 @@ */ import $ from 'cafy'; import DriveFolder from '../../../models/drive-folder'; -import DriveFile from '../../../models/drive-file'; -import { validateFileName }, { pack } from '../../../models/drive-file'; +import DriveFile, { validateFileName, pack } from '../../../models/drive-file'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/drive/files/upload_from_url.ts b/src/api/endpoints/drive/files/upload_from_url.ts index 009f06aaaf..68428747ef 100644 --- a/src/api/endpoints/drive/files/upload_from_url.ts +++ b/src/api/endpoints/drive/files/upload_from_url.ts @@ -3,7 +3,7 @@ */ import * as URL from 'url'; import $ from 'cafy'; -import { validateFileName }, { pack } from '../../../models/drive-file'; +import { validateFileName, pack } from '../../../models/drive-file'; import create from '../../../common/add-file-to-drive'; import * as debug from 'debug'; import * as tmp from 'tmp'; diff --git a/src/api/endpoints/drive/folders/create.ts b/src/api/endpoints/drive/folders/create.ts index 6543b11274..03f396ddc9 100644 --- a/src/api/endpoints/drive/folders/create.ts +++ b/src/api/endpoints/drive/folders/create.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName }, { pack } from '../../../models/drive-folder'; +import DriveFolder, { isValidFolderName, pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/drive/folders/update.ts b/src/api/endpoints/drive/folders/update.ts index 2adcadcb08..d3df8bdae5 100644 --- a/src/api/endpoints/drive/folders/update.ts +++ b/src/api/endpoints/drive/folders/update.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import DriveFolder from '../../../models/drive-folder'; -import { isValidFolderName }, { pack } from '../../../models/drive-folder'; +import DriveFolder, { isValidFolderName, pack } from '../../../models/drive-folder'; import { publishDriveStream } from '../../../event'; /** diff --git a/src/api/endpoints/following/create.ts b/src/api/endpoints/following/create.ts index b4a2217b16..8e1aa34713 100644 --- a/src/api/endpoints/following/create.ts +++ b/src/api/endpoints/following/create.ts @@ -2,11 +2,10 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; +import User, { pack as packUser } from '../../models/user'; import Following from '../../models/following'; import notify from '../../common/notify'; import event from '../../event'; -import serializeUser from '../../serializers/user'; /** * Follow a user @@ -77,8 +76,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Publish follow event - event(follower._id, 'follow', await serializeUser(followee, follower)); - event(followee._id, 'followed', await serializeUser(follower, followee)); + event(follower._id, 'follow', await packUser(followee, follower)); + event(followee._id, 'followed', await packUser(follower, followee)); // Notify notify(followee._id, follower._id, 'follow'); diff --git a/src/api/endpoints/following/delete.ts b/src/api/endpoints/following/delete.ts index aa1639ef6c..b68cec09dd 100644 --- a/src/api/endpoints/following/delete.ts +++ b/src/api/endpoints/following/delete.ts @@ -2,10 +2,9 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; +import User, { pack as packUser } from '../../models/user'; import Following from '../../models/following'; import event from '../../event'; -import serializeUser from '../../serializers/user'; /** * Unfollow a user @@ -78,5 +77,5 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // Publish follow event - event(follower._id, 'unfollow', await serializeUser(followee, follower)); + event(follower._id, 'unfollow', await packUser(followee, follower)); }); diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts index cd4b1a13f5..7bbbf95900 100644 --- a/src/api/endpoints/i/update.ts +++ b/src/api/endpoints/i/update.ts @@ -2,8 +2,7 @@ * Module dependencies */ import $ from 'cafy'; -import User from '../../models/user'; -import { isValidName, isValidDescription, isValidLocation, isValidBirthday }, { pack } from '../../models/user'; +import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack } from '../../models/user'; import event from '../../event'; import config from '../../../conf'; diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts index d537463dfe..0b0e0e294d 100644 --- a/src/api/endpoints/posts/reactions/create.ts +++ b/src/api/endpoints/posts/reactions/create.ts @@ -3,13 +3,12 @@ */ import $ from 'cafy'; import Reaction from '../../../models/post-reaction'; -import Post from '../../../models/post'; +import Post, { pack as packPost } from '../../../models/post'; +import { pack as packUser } from '../../../models/user'; import Watching from '../../../models/post-watching'; import notify from '../../../common/notify'; import watch from '../../../common/watch-post'; import { publishPostStream, pushSw } from '../../../event'; -import serializePost from '../../../serializers/post'; -import serializeUser from '../../../serializers/user'; /** * React to a post @@ -90,8 +89,8 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); pushSw(post.user_id, 'reaction', { - user: await serializeUser(user, post.user_id), - post: await serializePost(post, post.user_id), + user: await packUser(user, post.user_id), + post: await packPost(post, post.user_id), reaction: reaction }); diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts index 285e5bc46c..0c8bceee3d 100644 --- a/src/api/endpoints/users/posts.ts +++ b/src/api/endpoints/users/posts.ts @@ -2,8 +2,8 @@ * Module dependencies */ import $ from 'cafy'; -import Post from '../../models/post'; -import User, { pack } from '../../models/user'; +import Post, { pack } from '../../models/post'; +import User from '../../models/user'; /** * Get posts of a user diff --git a/src/api/endpoints/users/search.ts b/src/api/endpoints/users/search.ts index 1142db9e9b..39e2ff9890 100644 --- a/src/api/endpoints/users/search.ts +++ b/src/api/endpoints/users/search.ts @@ -51,7 +51,7 @@ async function byNative(res, rej, me, query, offset, max) { // Serialize res(await Promise.all(users.map(async user => - await serialize(user, me, { detail: true })))); + await pack(user, me, { detail: true })))); } // Search by Elasticsearch diff --git a/src/api/models/app.ts b/src/api/models/app.ts index fe9d49ff67..34e9867db7 100644 --- a/src/api/models/app.ts +++ b/src/api/models/app.ts @@ -14,6 +14,7 @@ export type IApp = { _id: mongo.ObjectID; created_at: Date; user_id: mongo.ObjectID; + secret: string; }; export function isValidNameId(nameId: string): boolean { diff --git a/src/api/models/drive-file.ts b/src/api/models/drive-file.ts index 9b9df1dac6..2a46d8dc4d 100644 --- a/src/api/models/drive-file.ts +++ b/src/api/models/drive-file.ts @@ -23,6 +23,7 @@ export type IDriveFile = { uploadDate: Date; md5: string; filename: string; + contentType: string; metadata: { properties: any; user_id: mongodb.ObjectID; diff --git a/src/api/models/post-reaction.ts b/src/api/models/post-reaction.ts index 568bfc89a2..639a70e006 100644 --- a/src/api/models/post-reaction.ts +++ b/src/api/models/post-reaction.ts @@ -9,6 +9,9 @@ export default PostReaction; export interface IPostReaction { _id: mongo.ObjectID; + created_at: Date; + deleted_at: Date; + reaction: string; } /** diff --git a/src/api/models/post.ts b/src/api/models/post.ts index ecc5e1a5e4..0bbacebf66 100644 --- a/src/api/models/post.ts +++ b/src/api/models/post.ts @@ -25,10 +25,12 @@ export type IPost = { media_ids: mongo.ObjectID[]; reply_id: mongo.ObjectID; repost_id: mongo.ObjectID; - poll: {}; // todo + poll: any; // todo text: string; user_id: mongo.ObjectID; app_id: mongo.ObjectID; + category: string; + is_category_verified: boolean; }; /** diff --git a/src/api/models/user.ts b/src/api/models/user.ts index 48a45ac2f7..e92f244dd0 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -42,6 +42,7 @@ export function isValidBirthday(birthday: string): boolean { export type IUser = { _id: mongo.ObjectID; created_at: Date; + deleted_at: Date; email: string; followers_count: number; following_count: number; diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts index 392f3b1fc7..8efdb6db47 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -2,8 +2,7 @@ import * as uuid from 'uuid'; import * as express from 'express'; import * as bcrypt from 'bcryptjs'; import recaptcha = require('recaptcha-promise'); -import { default as User, IUser } from '../models/user'; -import { validateUsername, validatePassword }, { pack } from '../models/user'; +import User, { IUser, validateUsername, validatePassword, pack } from '../models/user'; import generateUserToken from '../common/generate-native-user-token'; import config from '../../conf'; diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts index 7d4964eba6..adcd5ac49b 100644 --- a/src/api/service/twitter.ts +++ b/src/api/service/twitter.ts @@ -163,7 +163,7 @@ module.exports = (app: express.Application) => { res.send(`Twitter: @${result.screenName} を、Misskey: @${user.username} に接続しました!`); // Publish i updated event - event(user._id, 'i_updated', await serialize(user, user, { + event(user._id, 'i_updated', await pack(user, user, { detail: true, includeSecrets: true })); diff --git a/src/api/stream/home.ts b/src/api/stream/home.ts index 7dcdb5ed73..10078337c3 100644 --- a/src/api/stream/home.ts +++ b/src/api/stream/home.ts @@ -4,7 +4,7 @@ import * as debug from 'debug'; import User from '../models/user'; import Mute from '../models/mute'; -import serializePost from '../serializers/post'; +import { pack as packPost } from '../models/post'; import readNotification from '../common/read-notification'; const log = debug('misskey'); @@ -49,7 +49,7 @@ export default async function(request: websocket.request, connection: websocket. case 'post-stream': const postId = channel.split(':')[2]; log(`RECEIVED: ${postId} ${data} by @${user.username}`); - const post = await serializePost(postId, user, { + const post = await packPost(postId, user, { detail: true }); connection.send(JSON.stringify({ -- cgit v1.2.3-freya From 423f73777cd0b8e6ef916f1ad4e6971c1e560bb7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 2 Mar 2018 06:26:31 +0900 Subject: nanka iroiro --- package.json | 7 +++++- src/api/endpoints/i/update.ts | 8 ++++++- src/api/models/user.ts | 1 + src/web/app/common/views/components/poll.vue | 12 ++++++---- src/web/app/config.ts | 2 ++ src/web/app/desktop/script.ts | 1 + src/web/app/desktop/style.styl | 1 - .../desktop/views/components/settings.profile.vue | 9 +++++++ src/web/app/desktop/views/components/settings.vue | 28 ++++++++++++++++------ src/web/app/init.ts | 2 ++ src/web/docs/api/entities/user.yaml | 6 +++++ src/web/element.scss | 12 ++++++++++ webpack/webpack.config.ts | 17 +++++++++++++ 13 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 src/web/element.scss (limited to 'src/api/models/user.ts') diff --git a/package.json b/package.json index 29067b4ea4..f7001725ea 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "deepcopy": "0.6.3", "diskusage": "0.2.4", "elasticsearch": "14.1.0", + "element-ui": "^2.2.0", "emojilib": "^2.2.12", "escape-regexp": "0.0.1", "eslint": "4.18.0", @@ -104,6 +105,7 @@ "eventemitter3": "3.0.1", "exif-js": "2.3.0", "express": "4.16.2", + "file-loader": "^1.1.10", "file-type": "7.6.0", "fuckadblock": "3.2.1", "gm": "1.23.1", @@ -137,6 +139,8 @@ "morgan": "1.9.0", "ms": "2.1.1", "multer": "1.3.0", + "node-sass": "^4.7.2", + "node-sass-json-importer": "^3.1.3", "nprogress": "0.2.0", "os-utils": "0.0.14", "progress-bar-webpack-plugin": "^1.11.0", @@ -152,6 +156,7 @@ "rimraf": "2.6.2", "rndstr": "1.0.0", "s-age": "1.1.2", + "sass-loader": "^6.0.6", "seedrandom": "2.4.3", "serve-favicon": "2.4.5", "speakeasy": "2.0.0", @@ -181,7 +186,7 @@ "vue-template-compiler": "2.5.13", "vuedraggable": "2.16.0", "web-push": "3.3.0", - "webpack": "^3.11.0", + "webpack": "3.11.0", "webpack-cli": "^2.0.8", "webpack-replace-loader": "1.3.0", "websocket": "1.0.25", diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts index 43c5245044..fc12665ad6 100644 --- a/src/api/endpoints/i/update.ts +++ b/src/api/endpoints/i/update.ts @@ -46,13 +46,19 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re if (bannerIdErr) return rej('invalid banner_id param'); if (bannerId) user.banner_id = bannerId; + // Get 'is_bot' parameter + const [isBot, isBotErr] = $(params.is_bot).optional.boolean().$; + if (isBotErr) return rej('invalid is_bot param'); + if (isBot) user.is_bot = isBot; + 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 + profile: user.profile, + is_bot: user.is_bot } }); diff --git a/src/api/models/user.ts b/src/api/models/user.ts index e92f244dd0..278b949db5 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -75,6 +75,7 @@ export type IUser = { last_used_at: Date; latest_post: IPost; pinned_post_id: mongo.ObjectID; + is_bot: boolean; is_pro: boolean; is_suspended: boolean; keywords: string[]; diff --git a/src/web/app/common/views/components/poll.vue b/src/web/app/common/views/components/poll.vue index 7ed5bc6b1e..556d8ebf6c 100644 --- a/src/web/app/common/views/components/poll.vue +++ b/src/web/app/common/views/components/poll.vue @@ -5,14 +5,14 @@
- {{ choice.text }} + {{ choice.text }} ({{ '%i18n:common.tags.mk-poll.vote-count%'.replace('{}', choice.votes) }})

{{ '%i18n:common.tags.mk-poll.total-users%'.replace('{}', total) }} - ・ + {{ showResult ? '%i18n:common.tags.mk-poll.vote%' : '%i18n:common.tags.mk-poll.show-result%' }} %i18n:common.tags.mk-poll.voted%

@@ -98,8 +98,12 @@ export default Vue.extend({ background $theme-color transition width 1s ease - > .votes - margin-left 4px + > span + > [data-fa] + margin-right 4px + + > .votes + margin-left 4px > p a diff --git a/src/web/app/config.ts b/src/web/app/config.ts index 2461b22158..b51279192c 100644 --- a/src/web/app/config.ts +++ b/src/web/app/config.ts @@ -12,6 +12,7 @@ declare const _SW_PUBLICKEY_: string; declare const _THEME_COLOR_: string; declare const _COPYRIGHT_: string; declare const _VERSION_: string; +declare const _LICENSE_: string; export const host = _HOST_; export const url = _URL_; @@ -27,3 +28,4 @@ export const swPublickey = _SW_PUBLICKEY_; export const themeColor = _THEME_COLOR_; export const copyright = _COPYRIGHT_; export const version = _VERSION_; +export const license = _LICENSE_; diff --git a/src/web/app/desktop/script.ts b/src/web/app/desktop/script.ts index f0412805ef..78549741b0 100644 --- a/src/web/app/desktop/script.ts +++ b/src/web/app/desktop/script.ts @@ -4,6 +4,7 @@ // Style import './style.styl'; +import '../../element.scss'; import init from '../init'; import fuckAdBlock from '../common/scripts/fuck-ad-block'; diff --git a/src/web/app/desktop/style.styl b/src/web/app/desktop/style.styl index 4d295035f7..49f71fbde7 100644 --- a/src/web/app/desktop/style.styl +++ b/src/web/app/desktop/style.styl @@ -1,6 +1,5 @@ @import "../app" @import "../reset" -@import "../../../../node_modules/cropperjs/dist/cropper.css" @import "./ui" diff --git a/src/web/app/desktop/views/components/settings.profile.vue b/src/web/app/desktop/views/components/settings.profile.vue index 97a382d798..218da67e81 100644 --- a/src/web/app/desktop/views/components/settings.profile.vue +++ b/src/web/app/desktop/views/components/settings.profile.vue @@ -22,6 +22,10 @@ +
+

その他

+ +
@@ -56,6 +60,11 @@ export default Vue.extend({ }).then(() => { (this as any).apis.notify('プロフィールを更新しました'); }); + }, + onChangeIsBot() { + (this as any).api('i/update', { + is_bot: (this as any).os.i.is_bot + }); } } }); diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue index c210997c38..b65623e33a 100644 --- a/src/web/app/desktop/views/components/settings.vue +++ b/src/web/app/desktop/views/components/settings.vue @@ -23,10 +23,7 @@
- +
@@ -71,7 +68,8 @@

%i18n:desktop.tags.mk-settings.license%

- %license% +
+ サードパーティ
@@ -84,6 +82,7 @@ import XMute from './settings.mute.vue'; import XPassword from './settings.password.vue'; import X2fa from './settings.2fa.vue'; import XApi from './settings.api.vue'; +import { docsUrl, license, lang } from '../../../config'; export default Vue.extend({ components: { @@ -96,10 +95,15 @@ export default Vue.extend({ data() { return { page: 'profile', - + license, showPostFormOnTopOfTl: false }; }, + computed: { + licenseUrl(): string { + return `${docsUrl}/${lang}/license`; + } + }, created() { this.showPostFormOnTopOfTl = (this as any).os.i.client_settings.showPostFormOnTopOfTl; }, @@ -162,13 +166,23 @@ export default Vue.extend({ color #4a535a > h1 - display block margin 0 0 1em 0 padding 0 0 8px 0 font-size 1em color #555 border-bottom solid 1px #eee + &, >>> * + > section + margin 32px 0 + + > h2 + margin 0 0 1em 0 + padding 0 0 8px 0 + font-size 1em + color #555 + border-bottom solid 1px #eee + > .web > div border-bottom solid 1px #eee diff --git a/src/web/app/init.ts b/src/web/app/init.ts index f9855fd5c9..dc3057935f 100644 --- a/src/web/app/init.ts +++ b/src/web/app/init.ts @@ -5,9 +5,11 @@ import Vue from 'vue'; import VueRouter from 'vue-router'; import VModal from 'vue-js-modal'; +import Element from 'element-ui'; Vue.use(VueRouter); Vue.use(VModal); +Vue.use(Element); // Register global directives require('./common/views/directives'); diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml index e62ad84db8..528b9b0e13 100644 --- a/src/web/docs/api/entities/user.yaml +++ b/src/web/docs/api/entities/user.yaml @@ -111,6 +111,12 @@ props: desc: ja: "ドライブの容量(bytes)" en: "The capacity of drive of this user (bytes)" + - name: "is_bot" + type: "boolean" + optional: true + desc: + ja: "botか否か(自己申告であることに留意)" + en: "Whether is bot or not" - name: "twitter" type: "object" optional: true diff --git a/src/web/element.scss b/src/web/element.scss new file mode 100644 index 0000000000..917198e024 --- /dev/null +++ b/src/web/element.scss @@ -0,0 +1,12 @@ +/* Element variable definitons */ +/* SEE: http://element.eleme.io/#/en-US/component/custom-theme */ + +@import '../const.json'; + +/* theme color */ +$--color-primary: $themeColor; + +/* icon font path, required */ +$--font-path: '~element-ui/lib/theme-chalk/fonts'; + +@import "~element-ui/packages/theme-chalk/src/index"; diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts index 775ecbd348..a873419450 100644 --- a/webpack/webpack.config.ts +++ b/webpack/webpack.config.ts @@ -3,6 +3,7 @@ */ import * as fs from 'fs'; +import jsonImporter from 'node-sass-json-importer'; const minify = require('html-minifier').minify; import I18nReplacer from '../src/common/build/i18n'; import { pattern as faPattern, replacement as faReplacement } from '../src/common/build/fa'; @@ -111,12 +112,28 @@ module.exports = Object.keys(langs).map(lang => { { loader: 'css-loader' }, { loader: 'stylus-loader' } ] + }, { + test: /\.scss$/, + exclude: /node_modules/, + use: [{ + loader: 'style-loader' + }, { + loader: 'css-loader' + }, { + loader: 'sass-loader', + options: { + importer: jsonImporter, + } + }] }, { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' } ] + }, { + test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/, + loader: 'file-loader' }, { test: /\.ts$/, exclude: /node_modules/, -- cgit v1.2.3-freya From cb0d237b6a70ad118d3511930ef6cb1bca91cd76 Mon Sep 17 00:00:00 2001 From: syuilo Date: Mon, 5 Mar 2018 08:07:09 +0900 Subject: #1183 --- src/api/endpoints/i/update.ts | 8 +++++++- src/api/endpoints/posts/create.ts | 6 +++--- src/api/endpoints/posts/polls/vote.ts | 6 +++--- src/api/endpoints/posts/reactions/create.ts | 6 +++--- src/api/models/user.ts | 2 ++ src/api/private/signup.ts | 4 +++- src/web/app/desktop/views/components/settings.vue | 17 +++++++++++++++++ 7 files changed, 38 insertions(+), 11 deletions(-) (limited to 'src/api/models/user.ts') diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts index 2a5dce64a8..76bad2d156 100644 --- a/src/api/endpoints/i/update.ts +++ b/src/api/endpoints/i/update.ts @@ -51,6 +51,11 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re if (isBotErr) return rej('invalid is_bot param'); if (isBot != null) user.is_bot = isBot; + // Get 'auto_watch' parameter + const [autoWatch, autoWatchErr] = $(params.auto_watch).optional.boolean().$; + if (autoWatchErr) return rej('invalid auto_watch param'); + if (autoWatch != null) user.settings.auto_watch = autoWatch; + await User.update(user._id, { $set: { name: user.name, @@ -58,7 +63,8 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re avatar_id: user.avatar_id, banner_id: user.banner_id, profile: user.profile, - is_bot: user.is_bot + is_bot: user.is_bot, + settings: user.settings } }); diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 57f98fa811..a9d52fd128 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -377,9 +377,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { }); // この投稿をWatchする - // TODO: ユーザーが「返信したときに自動でWatchする」設定を - // オフにしていた場合はしない - watch(user._id, reply); + if (user.settings.auto_watch !== false) { + watch(user._id, reply); + } // Add mention addMention(reply.user_id, 'reply'); diff --git a/src/api/endpoints/posts/polls/vote.ts b/src/api/endpoints/posts/polls/vote.ts index 5a4fd1c268..8222fe5326 100644 --- a/src/api/endpoints/posts/polls/vote.ts +++ b/src/api/endpoints/posts/polls/vote.ts @@ -100,9 +100,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // この投稿をWatchする - // TODO: ユーザーが「投票したときに自動でWatchする」設定を - // オフにしていた場合はしない - watch(user._id, post); + if (user.settings.auto_watch !== false) { + watch(user._id, post); + } }); function findWithAttr(array, attr, value) { diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts index 0b0e0e294d..93d9756d02 100644 --- a/src/api/endpoints/posts/reactions/create.ts +++ b/src/api/endpoints/posts/reactions/create.ts @@ -116,7 +116,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // この投稿をWatchする - // TODO: ユーザーが「リアクションしたときに自動でWatchする」設定を - // オフにしていた場合はしない - watch(user._id, post); + if (user.settings.auto_watch !== false) { + watch(user._id, post); + } }); diff --git a/src/api/models/user.ts b/src/api/models/user.ts index 278b949db5..2fea0566ba 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -81,6 +81,8 @@ export type IUser = { keywords: string[]; two_factor_secret: string; two_factor_enabled: boolean; + client_settings: any; + settings: any; }; export function init(user): IUser { diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts index 19e3314756..1e3e9fb45f 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -132,7 +132,9 @@ export default async (req: express.Request, res: express.Response) => { location: null, weight: null }, - settings: {}, + settings: { + auto_watch: true + }, client_settings: { home: homeData, show_donation: false diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue index a0ffc4e0aa..0eb18770a5 100644 --- a/src/web/app/desktop/views/components/settings.vue +++ b/src/web/app/desktop/views/components/settings.vue @@ -62,6 +62,13 @@
+
+

通知

+ + リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。 + +
+

%i18n:desktop.tags.mk-settings.drive%

@@ -173,6 +180,7 @@ export default Vue.extend({ version, latestVersion: undefined, checkingForUpdate: false, + autoWatch: true, enableSounds: localStorage.getItem('enableSounds') == 'true', lang: localStorage.getItem('lang') || '', preventUpdate: localStorage.getItem('preventUpdate') == 'true', @@ -206,12 +214,21 @@ export default Vue.extend({ (this as any).os.getMeta().then(meta => { this.meta = meta; }); + + if ((this as any).os.i.settings.auto_watch != null) { + this.autoWatch = (this as any).os.i.settings.auto_watch; + } }, methods: { customizeHome() { this.$router.push('/i/customize-home'); this.$emit('done'); }, + onChangeAutoWatch(v) { + (this as any).api('i/update', { + auto_watch: v + }); + }, onChangeShowPostFormOnTopOfTl(v) { (this as any).api('i/update_client_setting', { name: 'showPostFormOnTopOfTl', -- cgit v1.2.3-freya From e515276e15fdf46a1756aa321701faf0b8d09854 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 6 Mar 2018 08:35:25 +0900 Subject: nanka iroiro Closes #1188 --- package.json | 1 + src/api/models/user.ts | 2 +- src/api/private/signup.ts | 3 +-- src/web/app/common/mios.ts | 10 +++++++- .../app/common/scripts/streaming/home-stream.ts | 7 +++++- .../app/desktop/views/components/post-detail.vue | 26 +++++++++++-------- .../app/desktop/views/components/posts.post.vue | 26 +++++++++++-------- src/web/app/desktop/views/components/settings.vue | 29 ++++++++-------------- .../app/mobile/views/components/post-detail.vue | 26 +++++++++++-------- src/web/app/mobile/views/components/post.vue | 26 +++++++++++-------- 10 files changed, 93 insertions(+), 63 deletions(-) (limited to 'src/api/models/user.ts') diff --git a/package.json b/package.json index bc49382823..4afc84f3e8 100644 --- a/package.json +++ b/package.json @@ -144,6 +144,7 @@ "node-sass": "^4.7.2", "node-sass-json-importer": "^3.1.3", "nprogress": "0.2.0", + "object-assign-deep": "^0.3.1", "on-build-webpack": "^0.1.0", "os-utils": "0.0.14", "progress-bar-webpack-plugin": "^1.11.0", diff --git a/src/api/models/user.ts b/src/api/models/user.ts index 2fea0566ba..ba2765c793 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -118,7 +118,6 @@ export const pack = ( let _user: any; const fields = opts.detail ? { - settings: false } : { settings: false, client_settings: false, @@ -173,6 +172,7 @@ export const pack = ( // Visible via only the official client if (!opts.includeSecrets) { delete _user.email; + delete _user.settings; delete _user.client_settings; } diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts index 1e3e9fb45f..3df00ae426 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -136,8 +136,7 @@ export default async (req: express.Request, res: express.Response) => { auto_watch: true }, client_settings: { - home: homeData, - show_donation: false + home: homeData } }); diff --git a/src/web/app/common/mios.ts b/src/web/app/common/mios.ts index da1d9746a1..bbe28960fd 100644 --- a/src/web/app/common/mios.ts +++ b/src/web/app/common/mios.ts @@ -1,5 +1,6 @@ import Vue from 'vue'; import { EventEmitter } from 'eventemitter3'; +import * as merge from 'object-assign-deep'; import { host, apiUrl, swPublickey, version, lang, googleMapsApiKey } from '../config'; import Progress from './scripts/loading'; @@ -284,6 +285,13 @@ export default class MiOS extends EventEmitter { // フェッチが完了したとき const fetched = me => { if (me) { + // デフォルトの設定をマージ + me.client_settings = Object.assign({ + fetchOnScroll: true, + showMaps: true, + showPostFormOnTopOfTl: false + }, me.client_settings); + // ローカルストレージにキャッシュ localStorage.setItem('me', JSON.stringify(me)); } @@ -313,7 +321,7 @@ export default class MiOS extends EventEmitter { // 後から新鮮なデータをフェッチ fetchme(cachedMe.token, freshData => { - Object.assign(cachedMe, freshData); + merge(cachedMe, freshData); }); } else { // Get token from cookie diff --git a/src/web/app/common/scripts/streaming/home-stream.ts b/src/web/app/common/scripts/streaming/home-stream.ts index 57bf0ec2a6..3516705e22 100644 --- a/src/web/app/common/scripts/streaming/home-stream.ts +++ b/src/web/app/common/scripts/streaming/home-stream.ts @@ -1,3 +1,5 @@ +import * as merge from 'object-assign-deep'; + import Stream from './stream'; import MiOS from '../../mios'; @@ -18,7 +20,10 @@ export default class Connection extends Stream { // 自分の情報が更新されたとき this.on('i_updated', i => { - Object.assign(me, i); + if (os.debug) { + console.log('I updated:', i); + } + merge(me, i); }); // トークンが再生成されたとき diff --git a/src/web/app/desktop/views/components/post-detail.vue b/src/web/app/desktop/views/components/post-detail.vue index e33120c7c0..e454c28702 100644 --- a/src/web/app/desktop/views/components/post-detail.vue +++ b/src/web/app/desktop/views/components/post-detail.vue @@ -148,17 +148,20 @@ export default Vue.extend({ // Draw map if (this.p.geo) { - (this as any).os.getGoogleMaps().then(maps => { - const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); - const map = new maps.Map(this.$refs.map, { - center: uluru, - zoom: 15 + const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true; + if (shouldShowMap) { + (this as any).os.getGoogleMaps().then(maps => { + const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); + const map = new maps.Map(this.$refs.map, { + center: uluru, + zoom: 15 + }); + new maps.Marker({ + position: uluru, + map: map + }); }); - new maps.Marker({ - position: uluru, - map: map - }); - }); + } } }, methods: { @@ -348,6 +351,9 @@ export default Vue.extend({ width 100% height 300px + &:empty + display none + > .mk-url-preview margin-top 8px diff --git a/src/web/app/desktop/views/components/posts.post.vue b/src/web/app/desktop/views/components/posts.post.vue index b88f016ad1..1a5f7c3b09 100644 --- a/src/web/app/desktop/views/components/posts.post.vue +++ b/src/web/app/desktop/views/components/posts.post.vue @@ -162,17 +162,20 @@ export default Vue.extend({ // Draw map if (this.p.geo) { - (this as any).os.getGoogleMaps().then(maps => { - const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); - const map = new maps.Map(this.$refs.map, { - center: uluru, - zoom: 15 + const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true; + if (shouldShowMap) { + (this as any).os.getGoogleMaps().then(maps => { + const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); + const map = new maps.Map(this.$refs.map, { + center: uluru, + zoom: 15 + }); + new maps.Marker({ + position: uluru, + map: map + }); }); - new maps.Marker({ - position: uluru, - map: map - }); - }); + } } }, beforeDestroy() { @@ -467,6 +470,9 @@ export default Vue.extend({ width 100% height 300px + &:empty + display none + > .tags margin 4px 0 0 0 diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue index 3278efb9ca..524e055c3a 100644 --- a/src/web/app/desktop/views/components/settings.vue +++ b/src/web/app/desktop/views/components/settings.vue @@ -20,7 +20,7 @@

動作

- + ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。
@@ -31,6 +31,9 @@ + + 位置情報が添付された投稿のマップを自動的に展開します。 +
@@ -71,7 +74,7 @@

通知

- + リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。
@@ -193,8 +196,6 @@ export default Vue.extend({ version, latestVersion: undefined, checkingForUpdate: false, - fetchOnScroll: true, - autoWatch: true, enableSounds: localStorage.getItem('enableSounds') == 'true', lang: localStorage.getItem('lang') || '', preventUpdate: localStorage.getItem('preventUpdate') == 'true', @@ -228,20 +229,6 @@ export default Vue.extend({ (this as any).os.getMeta().then(meta => { this.meta = meta; }); - - if ((this as any).os.i.settings.auto_watch != null) { - this.autoWatch = (this as any).os.i.settings.auto_watch; - this.$watch('os.i.settings.auto_watch', v => { - this.autoWatch = v; - }); - } - - if ((this as any).os.i.client_settings.fetchOnScroll != null) { - this.fetchOnScroll = (this as any).os.i.client_settings.fetchOnScroll; - this.$watch('os.i.client_settings.fetchOnScroll', v => { - this.fetchOnScroll = v; - }); - } }, methods: { customizeHome() { @@ -265,6 +252,12 @@ export default Vue.extend({ value: v }); }, + onChangeShowMaps(v) { + (this as any).api('i/update_client_setting', { + name: 'showMaps', + value: v + }); + }, onChangeDisableViaMobile(v) { (this as any).api('i/update_client_setting', { name: 'disableViaMobile', diff --git a/src/web/app/mobile/views/components/post-detail.vue b/src/web/app/mobile/views/components/post-detail.vue index bf8ce4f6fa..d51bfbc0e6 100644 --- a/src/web/app/mobile/views/components/post-detail.vue +++ b/src/web/app/mobile/views/components/post-detail.vue @@ -144,17 +144,20 @@ export default Vue.extend({ // Draw map if (this.p.geo) { - (this as any).os.getGoogleMaps().then(maps => { - const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); - const map = new maps.Map(this.$refs.map, { - center: uluru, - zoom: 15 + const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true; + if (shouldShowMap) { + (this as any).os.getGoogleMaps().then(maps => { + const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); + const map = new maps.Map(this.$refs.map, { + center: uluru, + zoom: 15 + }); + new maps.Marker({ + position: uluru, + map: map + }); }); - new maps.Marker({ - position: uluru, - map: map - }); - }); + } } }, methods: { @@ -349,6 +352,9 @@ export default Vue.extend({ width 100% height 200px + &:empty + display none + > .mk-url-preview margin-top 8px diff --git a/src/web/app/mobile/views/components/post.vue b/src/web/app/mobile/views/components/post.vue index 390c6396f2..3b31b827f6 100644 --- a/src/web/app/mobile/views/components/post.vue +++ b/src/web/app/mobile/views/components/post.vue @@ -137,17 +137,20 @@ export default Vue.extend({ // Draw map if (this.p.geo) { - (this as any).os.getGoogleMaps().then(maps => { - const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); - const map = new maps.Map(this.$refs.map, { - center: uluru, - zoom: 15 + const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true; + if (shouldShowMap) { + (this as any).os.getGoogleMaps().then(maps => { + const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude); + const map = new maps.Map(this.$refs.map, { + center: uluru, + zoom: 15 + }); + new maps.Marker({ + position: uluru, + map: map + }); }); - new maps.Marker({ - position: uluru, - map: map - }); - }); + } } }, beforeDestroy() { @@ -448,6 +451,9 @@ export default Vue.extend({ width 100% height 200px + &:empty + display none + > .app font-size 12px color #ccc -- cgit v1.2.3-freya From 19b9cb105d49e2a00ae19e3dc1f2d36dc394f148 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Mon, 26 Mar 2018 00:19:07 +0900 Subject: Introduce account document to user document An account document is attached to a user document if an account of the user is on the server. It may be missing if the user is on a remote server. --- src/api/authenticate.ts | 2 +- src/api/bot/core.ts | 2 +- src/api/bot/interfaces/line.ts | 10 +-- src/api/common/signin.ts | 2 +- src/api/endpoints/auth/accept.ts | 2 +- src/api/endpoints/following/create.ts | 2 +- src/api/endpoints/following/delete.ts | 2 +- src/api/endpoints/i.ts | 2 +- src/api/endpoints/i/2fa/done.ts | 4 +- src/api/endpoints/i/2fa/register.ts | 2 +- src/api/endpoints/i/2fa/unregister.ts | 6 +- src/api/endpoints/i/change_password.ts | 4 +- src/api/endpoints/i/regenerate_token.ts | 4 +- src/api/endpoints/i/update.ts | 14 ++-- src/api/endpoints/i/update_client_setting.ts | 4 +- src/api/endpoints/i/update_home.ts | 6 +- src/api/endpoints/i/update_mobile_home.ts | 6 +- src/api/endpoints/mute/create.ts | 2 +- src/api/endpoints/mute/delete.ts | 2 +- src/api/endpoints/posts/categorize.ts | 2 +- src/api/endpoints/posts/create.ts | 2 +- src/api/endpoints/posts/polls/vote.ts | 2 +- src/api/endpoints/posts/reactions/create.ts | 2 +- src/api/endpoints/users/recommendation.ts | 2 +- src/api/models/user.ts | 88 ++++++++++---------- src/api/private/signin.ts | 8 +- src/api/private/signup.ts | 40 ++++----- src/api/service/twitter.ts | 10 +-- src/api/stream/home.ts | 2 +- src/api/streaming.ts | 2 +- src/common/get-user-summary.ts | 2 +- src/web/app/common/define-widget.ts | 4 +- src/web/app/common/mios.ts | 10 +-- src/web/app/common/scripts/streaming/drive.ts | 2 +- src/web/app/common/scripts/streaming/home.ts | 4 +- .../common/scripts/streaming/messaging-index.ts | 2 +- src/web/app/common/scripts/streaming/messaging.ts | 4 +- .../app/common/scripts/streaming/othello-game.ts | 2 +- src/web/app/common/scripts/streaming/othello.ts | 2 +- src/web/app/common/views/components/signin.vue | 4 +- .../common/views/components/twitter-setting.vue | 12 +-- src/web/app/common/views/components/uploader.vue | 2 +- src/web/app/desktop/api/update-avatar.ts | 2 +- src/web/app/desktop/api/update-banner.ts | 2 +- src/web/app/desktop/views/components/home.vue | 20 ++--- .../app/desktop/views/components/post-detail.vue | 2 +- .../app/desktop/views/components/posts.post.vue | 4 +- .../app/desktop/views/components/settings.2fa.vue | 8 +- .../app/desktop/views/components/settings.api.vue | 2 +- .../desktop/views/components/settings.profile.vue | 8 +- src/web/app/desktop/views/components/settings.vue | 12 +-- src/web/app/desktop/views/components/timeline.vue | 2 +- src/web/app/desktop/views/components/ui.header.vue | 4 +- .../desktop/views/components/widget-container.vue | 4 +- src/web/app/desktop/views/components/window.vue | 4 +- .../app/desktop/views/pages/user/user.header.vue | 2 +- src/web/app/desktop/views/pages/user/user.home.vue | 2 +- .../app/desktop/views/pages/user/user.profile.vue | 10 +-- .../app/mobile/views/components/post-detail.vue | 2 +- src/web/app/mobile/views/components/post-form.vue | 2 +- src/web/app/mobile/views/components/post.vue | 4 +- src/web/app/mobile/views/components/ui.header.vue | 4 +- src/web/app/mobile/views/pages/home.vue | 20 ++--- src/web/app/mobile/views/pages/profile-setting.vue | 4 +- src/web/app/mobile/views/pages/user.vue | 10 +-- src/web/app/mobile/views/pages/user/home.vue | 2 +- src/web/app/mobile/views/pages/welcome.vue | 4 +- src/web/docs/api/entities/user.yaml | 94 ++++++++++++---------- test/api.js | 70 ++++++++++------ tools/migration/shell.1522038492.user-account.js | 41 ++++++++++ 70 files changed, 354 insertions(+), 279 deletions(-) create mode 100644 tools/migration/shell.1522038492.user-account.js (limited to 'src/api/models/user.ts') diff --git a/src/api/authenticate.ts b/src/api/authenticate.ts index b289959ac1..537c3d1e1f 100644 --- a/src/api/authenticate.ts +++ b/src/api/authenticate.ts @@ -34,7 +34,7 @@ export default (req: express.Request) => new Promise(async (resolv if (isNativeToken(token)) { const user: IUser = await User - .findOne({ token: token }); + .findOne({ 'account.token': token }); if (user === null) { return reject('user not found'); diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index 1f07d4eee9..ad29f1003e 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -225,7 +225,7 @@ class SigninContext extends Context { } } else { // Compare password - const same = await bcrypt.compare(query, this.temporaryUser.password); + const same = await bcrypt.compare(query, this.temporaryUser.account.password); if (same) { this.bot.signin(this.temporaryUser); diff --git a/src/api/bot/interfaces/line.ts b/src/api/bot/interfaces/line.ts index 43c25f8032..bf08821594 100644 --- a/src/api/bot/interfaces/line.ts +++ b/src/api/bot/interfaces/line.ts @@ -110,11 +110,11 @@ class LineBot extends BotCore { data: `showtl|${user.id}` }); - if (user.twitter) { + if (user.account.twitter) { actions.push({ type: 'uri', label: 'Twitterアカウントを見る', - uri: `https://twitter.com/${user.twitter.screen_name}` + uri: `https://twitter.com/${user.account.twitter.screen_name}` }); } @@ -171,7 +171,7 @@ module.exports = async (app: express.Application) => { if (session == null) { const user = await User.findOne({ - line: { + 'account.line': { user_id: sourceId } }); @@ -181,7 +181,7 @@ module.exports = async (app: express.Application) => { bot.on('signin', user => { User.update(user._id, { $set: { - line: { + 'account.line': { user_id: sourceId } } @@ -191,7 +191,7 @@ module.exports = async (app: express.Application) => { bot.on('signout', user => { User.update(user._id, { $set: { - line: { + 'account.line': { user_id: null } } diff --git a/src/api/common/signin.ts b/src/api/common/signin.ts index 693e62f39f..c069fa4ec8 100644 --- a/src/api/common/signin.ts +++ b/src/api/common/signin.ts @@ -2,7 +2,7 @@ import config from '../../conf'; export default function(res, user, redirect: boolean) { const expires = 1000 * 60 * 60 * 24 * 365; // One Year - res.cookie('i', user.token, { + res.cookie('i', user.account.token, { path: '/', domain: `.${config.host}`, secure: config.url.substr(0, 5) === 'https', diff --git a/src/api/endpoints/auth/accept.ts b/src/api/endpoints/auth/accept.ts index 4ee20a6d25..8955738ebf 100644 --- a/src/api/endpoints/auth/accept.ts +++ b/src/api/endpoints/auth/accept.ts @@ -45,7 +45,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Fetch token const session = await AuthSess - .findOne({ token: token }); + .findOne({ 'account.token': token }); if (session === null) { return rej('session not found'); diff --git a/src/api/endpoints/following/create.ts b/src/api/endpoints/following/create.ts index 8e1aa34713..767b837b35 100644 --- a/src/api/endpoints/following/create.ts +++ b/src/api/endpoints/following/create.ts @@ -32,7 +32,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }, { fields: { data: false, - profile: false + 'account.profile': false } }); diff --git a/src/api/endpoints/following/delete.ts b/src/api/endpoints/following/delete.ts index b68cec09dd..64b9a8cecb 100644 --- a/src/api/endpoints/following/delete.ts +++ b/src/api/endpoints/following/delete.ts @@ -31,7 +31,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }, { fields: { data: false, - profile: false + 'account.profile': false } }); diff --git a/src/api/endpoints/i.ts b/src/api/endpoints/i.ts index 7efdbcd7c9..32b0382faf 100644 --- a/src/api/endpoints/i.ts +++ b/src/api/endpoints/i.ts @@ -22,7 +22,7 @@ module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) => // Update lastUsedAt User.update({ _id: user._id }, { $set: { - last_used_at: new Date() + 'account.last_used_at': new Date() } }); }); diff --git a/src/api/endpoints/i/2fa/done.ts b/src/api/endpoints/i/2fa/done.ts index 0b36033bb6..0f1db73829 100644 --- a/src/api/endpoints/i/2fa/done.ts +++ b/src/api/endpoints/i/2fa/done.ts @@ -28,8 +28,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { await User.update(user._id, { $set: { - two_factor_secret: user.two_factor_temp_secret, - two_factor_enabled: true + 'account.two_factor_secret': user.two_factor_temp_secret, + 'account.two_factor_enabled': true } }); diff --git a/src/api/endpoints/i/2fa/register.ts b/src/api/endpoints/i/2fa/register.ts index c2b5037a29..24abfcdfc5 100644 --- a/src/api/endpoints/i/2fa/register.ts +++ b/src/api/endpoints/i/2fa/register.ts @@ -14,7 +14,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { if (passwordErr) return rej('invalid password param'); // Compare password - const same = await bcrypt.compare(password, user.password); + const same = await bcrypt.compare(password, user.account.password); if (!same) { return rej('incorrect password'); diff --git a/src/api/endpoints/i/2fa/unregister.ts b/src/api/endpoints/i/2fa/unregister.ts index 6bee6a26f2..c43f9ccc44 100644 --- a/src/api/endpoints/i/2fa/unregister.ts +++ b/src/api/endpoints/i/2fa/unregister.ts @@ -11,7 +11,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { if (passwordErr) return rej('invalid password param'); // Compare password - const same = await bcrypt.compare(password, user.password); + const same = await bcrypt.compare(password, user.account.password); if (!same) { return rej('incorrect password'); @@ -19,8 +19,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { await User.update(user._id, { $set: { - two_factor_secret: null, - two_factor_enabled: false + 'account.two_factor_secret': null, + 'account.two_factor_enabled': false } }); diff --git a/src/api/endpoints/i/change_password.ts b/src/api/endpoints/i/change_password.ts index 16f1a2e4ec..88fb36b1fb 100644 --- a/src/api/endpoints/i/change_password.ts +++ b/src/api/endpoints/i/change_password.ts @@ -22,7 +22,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { if (newPasswordErr) return rej('invalid new_password param'); // Compare password - const same = await bcrypt.compare(currentPassword, user.password); + const same = await bcrypt.compare(currentPassword, user.account.password); if (!same) { return rej('incorrect password'); @@ -34,7 +34,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { await User.update(user._id, { $set: { - password: hash + 'account.password': hash } }); diff --git a/src/api/endpoints/i/regenerate_token.ts b/src/api/endpoints/i/regenerate_token.ts index 653468330f..9ac7b55071 100644 --- a/src/api/endpoints/i/regenerate_token.ts +++ b/src/api/endpoints/i/regenerate_token.ts @@ -20,7 +20,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { if (passwordErr) return rej('invalid password param'); // Compare password - const same = await bcrypt.compare(password, user.password); + const same = await bcrypt.compare(password, user.account.password); if (!same) { return rej('incorrect password'); @@ -31,7 +31,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { await User.update(user._id, { $set: { - token: secret + 'account.token': secret } }); diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts index 76bad2d156..db8a3f25bd 100644 --- a/src/api/endpoints/i/update.ts +++ b/src/api/endpoints/i/update.ts @@ -29,12 +29,12 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re // Get 'location' parameter const [location, locationErr] = $(params.location).optional.nullable.string().pipe(isValidLocation).$; if (locationErr) return rej('invalid location param'); - if (location !== undefined) user.profile.location = location; + if (location !== undefined) user.account.profile.location = location; // Get 'birthday' parameter const [birthday, birthdayErr] = $(params.birthday).optional.nullable.string().pipe(isValidBirthday).$; if (birthdayErr) return rej('invalid birthday param'); - if (birthday !== undefined) user.profile.birthday = birthday; + if (birthday !== undefined) user.account.profile.birthday = birthday; // Get 'avatar_id' parameter const [avatarId, avatarIdErr] = $(params.avatar_id).optional.id().$; @@ -49,12 +49,12 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re // Get 'is_bot' parameter const [isBot, isBotErr] = $(params.is_bot).optional.boolean().$; if (isBotErr) return rej('invalid is_bot param'); - if (isBot != null) user.is_bot = isBot; + if (isBot != null) user.account.is_bot = isBot; // Get 'auto_watch' parameter const [autoWatch, autoWatchErr] = $(params.auto_watch).optional.boolean().$; if (autoWatchErr) return rej('invalid auto_watch param'); - if (autoWatch != null) user.settings.auto_watch = autoWatch; + if (autoWatch != null) user.account.settings.auto_watch = autoWatch; await User.update(user._id, { $set: { @@ -62,9 +62,9 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re description: user.description, avatar_id: user.avatar_id, banner_id: user.banner_id, - profile: user.profile, - is_bot: user.is_bot, - settings: user.settings + 'account.profile': user.account.profile, + 'account.is_bot': user.account.is_bot, + 'account.settings': user.account.settings } }); diff --git a/src/api/endpoints/i/update_client_setting.ts b/src/api/endpoints/i/update_client_setting.ts index b817ff354c..c772ed5dc3 100644 --- a/src/api/endpoints/i/update_client_setting.ts +++ b/src/api/endpoints/i/update_client_setting.ts @@ -22,14 +22,14 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { if (valueErr) return rej('invalid value param'); const x = {}; - x[`client_settings.${name}`] = value; + x[`account.client_settings.${name}`] = value; await User.update(user._id, { $set: x }); // Serialize - user.client_settings[name] = value; + user.account.client_settings[name] = value; const iObj = await pack(user, user, { detail: true, includeSecrets: true diff --git a/src/api/endpoints/i/update_home.ts b/src/api/endpoints/i/update_home.ts index 394686cbd1..9ce44e25ee 100644 --- a/src/api/endpoints/i/update_home.ts +++ b/src/api/endpoints/i/update_home.ts @@ -26,7 +26,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { if (home) { await User.update(user._id, { $set: { - 'client_settings.home': home + 'account.client_settings.home': home } }); @@ -38,7 +38,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { } else { if (id == null && data == null) return rej('you need to set id and data params if home param unset'); - const _home = user.client_settings.home; + const _home = user.account.client_settings.home; const widget = _home.find(w => w.id == id); if (widget == null) return rej('widget not found'); @@ -47,7 +47,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { await User.update(user._id, { $set: { - 'client_settings.home': _home + 'account.client_settings.home': _home } }); diff --git a/src/api/endpoints/i/update_mobile_home.ts b/src/api/endpoints/i/update_mobile_home.ts index 70181431a2..1daddf42b9 100644 --- a/src/api/endpoints/i/update_mobile_home.ts +++ b/src/api/endpoints/i/update_mobile_home.ts @@ -25,7 +25,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { if (home) { await User.update(user._id, { $set: { - 'client_settings.mobile_home': home + 'account.client_settings.mobile_home': home } }); @@ -37,7 +37,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { } else { if (id == null && data == null) return rej('you need to set id and data params if home param unset'); - const _home = user.client_settings.mobile_home || []; + const _home = user.account.client_settings.mobile_home || []; const widget = _home.find(w => w.id == id); if (widget == null) return rej('widget not found'); @@ -46,7 +46,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { await User.update(user._id, { $set: { - 'client_settings.mobile_home': _home + 'account.client_settings.mobile_home': _home } }); diff --git a/src/api/endpoints/mute/create.ts b/src/api/endpoints/mute/create.ts index f44854ab52..f99b40d32e 100644 --- a/src/api/endpoints/mute/create.ts +++ b/src/api/endpoints/mute/create.ts @@ -30,7 +30,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }, { fields: { data: false, - profile: false + 'account.profile': false } }); diff --git a/src/api/endpoints/mute/delete.ts b/src/api/endpoints/mute/delete.ts index d6bff3353a..36e2fd101a 100644 --- a/src/api/endpoints/mute/delete.ts +++ b/src/api/endpoints/mute/delete.ts @@ -30,7 +30,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }, { fields: { data: false, - profile: false + 'account.profile': false } }); diff --git a/src/api/endpoints/posts/categorize.ts b/src/api/endpoints/posts/categorize.ts index 3530ba6bc4..0c85c2b4e0 100644 --- a/src/api/endpoints/posts/categorize.ts +++ b/src/api/endpoints/posts/categorize.ts @@ -12,7 +12,7 @@ import Post from '../../models/post'; * @return {Promise} */ module.exports = (params, user) => new Promise(async (res, rej) => { - if (!user.is_pro) { + if (!user.account.is_pro) { return rej('This endpoint is available only from a Pro account'); } diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 1c3ab53457..f46a84e1f1 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -390,7 +390,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { }); // この投稿をWatchする - if (user.settings.auto_watch !== false) { + if (user.account.settings.auto_watch !== false) { watch(user._id, reply); } diff --git a/src/api/endpoints/posts/polls/vote.ts b/src/api/endpoints/posts/polls/vote.ts index 8222fe5326..16ce76a6fa 100644 --- a/src/api/endpoints/posts/polls/vote.ts +++ b/src/api/endpoints/posts/polls/vote.ts @@ -100,7 +100,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // この投稿をWatchする - if (user.settings.auto_watch !== false) { + if (user.account.settings.auto_watch !== false) { watch(user._id, post); } }); diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts index 93d9756d02..f77afed40c 100644 --- a/src/api/endpoints/posts/reactions/create.ts +++ b/src/api/endpoints/posts/reactions/create.ts @@ -116,7 +116,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { }); // この投稿をWatchする - if (user.settings.auto_watch !== false) { + if (user.account.settings.auto_watch !== false) { watch(user._id, post); } }); diff --git a/src/api/endpoints/users/recommendation.ts b/src/api/endpoints/users/recommendation.ts index 736233b340..f1f5bcd0ac 100644 --- a/src/api/endpoints/users/recommendation.ts +++ b/src/api/endpoints/users/recommendation.ts @@ -30,7 +30,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { _id: { $nin: followingIds }, - last_used_at: { + 'account.last_used_at': { $gte: new Date(Date.now() - ms('7days')) } }, { diff --git a/src/api/models/user.ts b/src/api/models/user.ts index ba2765c793..372e2c5dac 100644 --- a/src/api/models/user.ts +++ b/src/api/models/user.ts @@ -11,7 +11,7 @@ import config from '../../conf'; const User = db.get('users'); User.createIndex('username'); -User.createIndex('token'); +User.createIndex('account.token'); export default User; @@ -43,46 +43,48 @@ export type IUser = { _id: mongo.ObjectID; created_at: Date; deleted_at: Date; - email: string; followers_count: number; following_count: number; - links: string[]; name: string; - password: string; posts_count: number; drive_capacity: number; username: string; username_lower: string; - token: string; avatar_id: mongo.ObjectID; banner_id: mongo.ObjectID; data: any; - twitter: { - access_token: string; - access_token_secret: string; - user_id: string; - screen_name: string; - }; - line: { - user_id: string; - }; description: string; - profile: { - location: string; - birthday: string; // 'YYYY-MM-DD' - tags: string[]; - }; - last_used_at: Date; latest_post: IPost; pinned_post_id: mongo.ObjectID; - is_bot: boolean; - is_pro: boolean; is_suspended: boolean; keywords: string[]; - two_factor_secret: string; - two_factor_enabled: boolean; - client_settings: any; - settings: any; + account: { + email: string; + links: string[]; + password: string; + token: string; + twitter: { + access_token: string; + access_token_secret: string; + user_id: string; + screen_name: string; + }; + line: { + user_id: string; + }; + profile: { + location: string; + birthday: string; // 'YYYY-MM-DD' + tags: string[]; + }; + last_used_at: Date; + is_bot: boolean; + is_pro: boolean; + two_factor_secret: string; + two_factor_enabled: boolean; + client_settings: any; + settings: any; + }; }; export function init(user): IUser { @@ -119,11 +121,11 @@ export const pack = ( const fields = opts.detail ? { } : { - settings: false, - client_settings: false, - profile: false, - keywords: false, - domains: false + 'account.settings': false, + 'account.client_settings': false, + 'account.profile': false, + 'account.keywords': false, + 'account.domains': false }; // Populate the user if 'user' is ID @@ -158,26 +160,26 @@ export const pack = ( delete _user.latest_post; // Remove private properties - delete _user.password; - delete _user.token; - delete _user.two_factor_temp_secret; - delete _user.two_factor_secret; + delete _user.account.password; + delete _user.account.token; + delete _user.account.two_factor_temp_secret; + delete _user.account.two_factor_secret; delete _user.username_lower; - if (_user.twitter) { - delete _user.twitter.access_token; - delete _user.twitter.access_token_secret; + if (_user.account.twitter) { + delete _user.account.twitter.access_token; + delete _user.account.twitter.access_token_secret; } - delete _user.line; + delete _user.account.line; // Visible via only the official client if (!opts.includeSecrets) { - delete _user.email; - delete _user.settings; - delete _user.client_settings; + delete _user.account.email; + delete _user.account.settings; + delete _user.account.client_settings; } if (!opts.detail) { - delete _user.two_factor_enabled; + delete _user.account.two_factor_enabled; } _user.avatar_url = _user.avatar_id != null diff --git a/src/api/private/signin.ts b/src/api/private/signin.ts index b49d25d99a..ae0be03c73 100644 --- a/src/api/private/signin.ts +++ b/src/api/private/signin.ts @@ -36,7 +36,7 @@ export default async (req: express.Request, res: express.Response) => { }, { fields: { data: false, - profile: false + 'account.profile': false } }); @@ -48,12 +48,12 @@ export default async (req: express.Request, res: express.Response) => { } // Compare password - const same = await bcrypt.compare(password, user.password); + const same = await bcrypt.compare(password, user.account.password); if (same) { - if (user.two_factor_enabled) { + if (user.account.two_factor_enabled) { const verified = (speakeasy as any).totp.verify({ - secret: user.two_factor_secret, + secret: user.account.two_factor_secret, encoding: 'base32', token: token }); diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts index 3df00ae426..902642425c 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -105,38 +105,40 @@ export default async (req: express.Request, res: express.Response) => { // Create account const account: IUser = await User.insert({ - token: secret, avatar_id: null, banner_id: null, created_at: new Date(), description: null, - email: null, followers_count: 0, following_count: 0, - links: null, name: name, - password: hash, posts_count: 0, likes_count: 0, liked_count: 0, drive_capacity: 1073741824, // 1GB username: username, username_lower: username.toLowerCase(), - profile: { - bio: null, - birthday: null, - blood: null, - gender: null, - handedness: null, - height: null, - location: null, - weight: null - }, - settings: { - auto_watch: true - }, - client_settings: { - home: homeData + account: { + token: secret, + email: null, + links: null, + password: hash, + profile: { + bio: null, + birthday: null, + blood: null, + gender: null, + handedness: null, + height: null, + location: null, + weight: null + }, + settings: { + auto_watch: true + }, + client_settings: { + home: homeData + } } }); diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts index adcd5ac49b..02b613454c 100644 --- a/src/api/service/twitter.ts +++ b/src/api/service/twitter.ts @@ -39,10 +39,10 @@ module.exports = (app: express.Application) => { if (userToken == null) return res.send('plz signin'); const user = await User.findOneAndUpdate({ - token: userToken + 'account.token': userToken }, { $set: { - twitter: null + 'account.twitter': null } }); @@ -126,7 +126,7 @@ module.exports = (app: express.Application) => { const result = await twAuth.done(JSON.parse(ctx), req.query.oauth_verifier); const user = await User.findOne({ - 'twitter.user_id': result.userId + 'account.twitter.user_id': result.userId }); if (user == null) { @@ -148,10 +148,10 @@ module.exports = (app: express.Application) => { const result = await twAuth.done(JSON.parse(ctx), verifier); const user = await User.findOneAndUpdate({ - token: userToken + 'account.token': userToken }, { $set: { - twitter: { + 'account.twitter': { access_token: result.accessToken, access_token_secret: result.accessTokenSecret, user_id: result.userId, diff --git a/src/api/stream/home.ts b/src/api/stream/home.ts index cc3fb885e4..1ef0f33b4b 100644 --- a/src/api/stream/home.ts +++ b/src/api/stream/home.ts @@ -74,7 +74,7 @@ export default async function(request: websocket.request, connection: websocket. // Update lastUsedAt User.update({ _id: user._id }, { $set: { - last_used_at: new Date() + 'account.last_used_at': new Date() } }); break; diff --git a/src/api/streaming.ts b/src/api/streaming.ts index f56c08092c..427e01afdd 100644 --- a/src/api/streaming.ts +++ b/src/api/streaming.ts @@ -94,7 +94,7 @@ function authenticate(token: string): Promise { // Fetch user const user: IUser = await User .findOne({ - token: token + 'account.token': token }); resolve(user); diff --git a/src/common/get-user-summary.ts b/src/common/get-user-summary.ts index 1bec2f9a26..619814e8a8 100644 --- a/src/common/get-user-summary.ts +++ b/src/common/get-user-summary.ts @@ -7,6 +7,6 @@ import { IUser } from '../api/models/user'; export default function(user: IUser): string { return `${user.name} (@${user.username})\n` + `${user.posts_count}投稿、${user.following_count}フォロー、${user.followers_count}フォロワー\n` + - `場所: ${user.profile.location}、誕生日: ${user.profile.birthday}\n` + + `場所: ${user.account.profile.location}、誕生日: ${user.account.profile.birthday}\n` + `「${user.description}」`; } diff --git a/src/web/app/common/define-widget.ts b/src/web/app/common/define-widget.ts index efce7e813c..d8d29873a4 100644 --- a/src/web/app/common/define-widget.ts +++ b/src/web/app/common/define-widget.ts @@ -56,14 +56,14 @@ export default function(data: { id: this.id, data: newProps }).then(() => { - (this as any).os.i.client_settings.mobile_home.find(w => w.id == this.id).data = newProps; + (this as any).os.i.account.client_settings.mobile_home.find(w => w.id == this.id).data = newProps; }); } else { (this as any).api('i/update_home', { id: this.id, data: newProps }).then(() => { - (this as any).os.i.client_settings.home.find(w => w.id == this.id).data = newProps; + (this as any).os.i.account.client_settings.home.find(w => w.id == this.id).data = newProps; }); } }, { diff --git a/src/web/app/common/mios.ts b/src/web/app/common/mios.ts index 986630da20..1c950c3e79 100644 --- a/src/web/app/common/mios.ts +++ b/src/web/app/common/mios.ts @@ -270,7 +270,7 @@ export default class MiOS extends EventEmitter { // Parse response res.json().then(i => { me = i; - me.token = token; + me.account.token = token; done(); }); }) @@ -294,12 +294,12 @@ export default class MiOS extends EventEmitter { const fetched = me => { if (me) { // デフォルトの設定をマージ - me.client_settings = Object.assign({ + me.account.client_settings = Object.assign({ fetchOnScroll: true, showMaps: true, showPostFormOnTopOfTl: false, gradientWindowHeader: false - }, me.client_settings); + }, me.account.client_settings); // ローカルストレージにキャッシュ localStorage.setItem('me', JSON.stringify(me)); @@ -329,7 +329,7 @@ export default class MiOS extends EventEmitter { fetched(cachedMe); // 後から新鮮なデータをフェッチ - fetchme(cachedMe.token, freshData => { + fetchme(cachedMe.account.token, freshData => { merge(cachedMe, freshData); }); } else { @@ -437,7 +437,7 @@ export default class MiOS extends EventEmitter { } // Append a credential - if (this.isSignedIn) (data as any).i = this.i.token; + if (this.isSignedIn) (data as any).i = this.i.account.token; // TODO //const viaStream = localStorage.getItem('enableExperimental') == 'true'; diff --git a/src/web/app/common/scripts/streaming/drive.ts b/src/web/app/common/scripts/streaming/drive.ts index 7ff85b5946..f11573685e 100644 --- a/src/web/app/common/scripts/streaming/drive.ts +++ b/src/web/app/common/scripts/streaming/drive.ts @@ -8,7 +8,7 @@ import MiOS from '../../mios'; export class DriveStream extends Stream { constructor(os: MiOS, me) { super(os, 'drive', { - i: me.token + i: me.account.token }); } } diff --git a/src/web/app/common/scripts/streaming/home.ts b/src/web/app/common/scripts/streaming/home.ts index 533c232449..ffcf6e5360 100644 --- a/src/web/app/common/scripts/streaming/home.ts +++ b/src/web/app/common/scripts/streaming/home.ts @@ -10,13 +10,13 @@ import MiOS from '../../mios'; export class HomeStream extends Stream { constructor(os: MiOS, me) { super(os, '', { - i: me.token + i: me.account.token }); // 最終利用日時を更新するため定期的にaliveメッセージを送信 setInterval(() => { this.send({ type: 'alive' }); - me.last_used_at = new Date(); + me.account.last_used_at = new Date(); }, 1000 * 60); // 自分の情報が更新されたとき diff --git a/src/web/app/common/scripts/streaming/messaging-index.ts b/src/web/app/common/scripts/streaming/messaging-index.ts index 84e2174ec4..24f0ce0c9f 100644 --- a/src/web/app/common/scripts/streaming/messaging-index.ts +++ b/src/web/app/common/scripts/streaming/messaging-index.ts @@ -8,7 +8,7 @@ import MiOS from '../../mios'; export class MessagingIndexStream extends Stream { constructor(os: MiOS, me) { super(os, 'messaging-index', { - i: me.token + i: me.account.token }); } } diff --git a/src/web/app/common/scripts/streaming/messaging.ts b/src/web/app/common/scripts/streaming/messaging.ts index c1b5875cfb..4c593deb31 100644 --- a/src/web/app/common/scripts/streaming/messaging.ts +++ b/src/web/app/common/scripts/streaming/messaging.ts @@ -7,13 +7,13 @@ import MiOS from '../../mios'; export class MessagingStream extends Stream { constructor(os: MiOS, me, otherparty) { super(os, 'messaging', { - i: me.token, + i: me.account.token, otherparty }); (this as any).on('_connected_', () => { this.send({ - i: me.token + i: me.account.token }); }); } diff --git a/src/web/app/common/scripts/streaming/othello-game.ts b/src/web/app/common/scripts/streaming/othello-game.ts index b85af8f72b..f34ef35147 100644 --- a/src/web/app/common/scripts/streaming/othello-game.ts +++ b/src/web/app/common/scripts/streaming/othello-game.ts @@ -4,7 +4,7 @@ import MiOS from '../../mios'; export class OthelloGameStream extends Stream { constructor(os: MiOS, me, game) { super(os, 'othello-game', { - i: me ? me.token : null, + i: me ? me.account.token : null, game: game.id }); } diff --git a/src/web/app/common/scripts/streaming/othello.ts b/src/web/app/common/scripts/streaming/othello.ts index f5d47431cd..8c6f4b9c3c 100644 --- a/src/web/app/common/scripts/streaming/othello.ts +++ b/src/web/app/common/scripts/streaming/othello.ts @@ -5,7 +5,7 @@ import MiOS from '../../mios'; export class OthelloStream extends Stream { constructor(os: MiOS, me) { super(os, 'othello', { - i: me.token + i: me.account.token }); } } diff --git a/src/web/app/common/views/components/signin.vue b/src/web/app/common/views/components/signin.vue index 1738d0df7d..d8b1357764 100644 --- a/src/web/app/common/views/components/signin.vue +++ b/src/web/app/common/views/components/signin.vue @@ -6,7 +6,7 @@ -