This commit is contained in:
		
							parent
							
								
									f546edb810
								
							
						
					
					
						commit
						ffaec0b971
					
				
					 14 changed files with 137 additions and 33 deletions
				
			
		|  | @ -2,6 +2,10 @@ ChangeLog | |||
| ========= | ||||
| 主に notable な changes を書いていきます | ||||
| 
 | ||||
| unlereased | ||||
| ---------- | ||||
| * New: トークンを再生成できるように (#497) | ||||
| 
 | ||||
| 2461 (2017/08/28) | ||||
| ----------------- | ||||
| * Fix: モバイル版からアバターとバナーの設定を行えなかった問題を修正 | ||||
|  | @ -11,8 +15,8 @@ ChangeLog | |||
| ----------------- | ||||
| * New: モバイル版からプロフィールを設定できるように | ||||
| * New: モバイル版からサインアウトを行えるように | ||||
| * Improve: 投稿ページに次の投稿/前の投稿リンクを作成 (#734) | ||||
| * Improve: タイムラインの投稿をダブルクリックすることで詳細な情報が見れるように | ||||
| * New: 投稿ページに次の投稿/前の投稿リンクを作成 (#734) | ||||
| * New: タイムラインの投稿をダブルクリックすることで詳細な情報が見れるように | ||||
| * Fix: モバイル版でおすすめユーザーをフォローしてもタイムラインが更新されない (#736) | ||||
| * Fix: モバイル版で設定にアクセスできない | ||||
| * デザインの調整 | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ common: | |||
|   loading: "Loading" | ||||
|   ok: "OK" | ||||
|   update-available: "New version of Misskey is now available({newer}, current is {current}). Reload page to apply update." | ||||
|   my-token-regenerated: "Your token is just regenerated, so you will signout." | ||||
| 
 | ||||
|   tags: | ||||
|     mk-messaging-form: | ||||
|  | @ -129,6 +130,9 @@ common: | |||
| 
 | ||||
| desktop: | ||||
|   tags: | ||||
|     mk-api-info: | ||||
|       regenerate-token: "Please enter the password" | ||||
| 
 | ||||
|     mk-drive-browser-base-contextmenu: | ||||
|       create-folder: "Create a folder" | ||||
|       upload: "Upload a file" | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ common: | |||
|   loading: "読み込み中" | ||||
|   ok: "わかった" | ||||
|   update-available: "Misskeyの新しいバージョンがあります({newer}。現在{current}を利用中)。ページを再度読み込みすると更新が適用されます。" | ||||
|   my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" | ||||
| 
 | ||||
|   tags: | ||||
|     mk-messaging-form: | ||||
|  | @ -129,6 +130,9 @@ common: | |||
| 
 | ||||
| desktop: | ||||
|   tags: | ||||
|     mk-api-info: | ||||
|       regenerate-token: "パスワードを入力してください" | ||||
| 
 | ||||
|     mk-drive-browser-base-contextmenu: | ||||
|       create-folder: "フォルダーを作成" | ||||
|       upload: "ファイルをアップロード" | ||||
|  |  | |||
							
								
								
									
										3
									
								
								src/api/common/generate-native-user-token.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/api/common/generate-native-user-token.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| import rndstr from 'rndstr'; | ||||
| 
 | ||||
| export default () => `!${rndstr('a-zA-Z0-9', 32)}`; | ||||
|  | @ -159,6 +159,10 @@ const endpoints: Endpoint[] = [ | |||
| 		}, | ||||
| 		kind: 'account-write' | ||||
| 	}, | ||||
| 	{ | ||||
| 		name: 'i/regenerate_token', | ||||
| 		withCredential: true | ||||
| 	}, | ||||
| 	{ | ||||
| 		name: 'i/appdata/get', | ||||
| 		withCredential: true | ||||
|  |  | |||
							
								
								
									
										42
									
								
								src/api/endpoints/i/regenerate_token.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/api/endpoints/i/regenerate_token.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| /** | ||||
|  * Module dependencies | ||||
|  */ | ||||
| import $ from 'cafy'; | ||||
| import * as bcrypt from 'bcryptjs'; | ||||
| import User from '../../models/user'; | ||||
| import event from '../../event'; | ||||
| import generateUserToken from '../../common/generate-native-user-token'; | ||||
| 
 | ||||
| /** | ||||
|  * Regenerate native token | ||||
|  * | ||||
|  * @param {any} params | ||||
|  * @param {any} user | ||||
|  * @return {Promise<any>} | ||||
|  */ | ||||
| module.exports = async (params, user) => new Promise(async (res, rej) => { | ||||
| 	// Get 'password' parameter
 | ||||
| 	const [password, passwordErr] = $(params.password).string().$; | ||||
| 	if (passwordErr) return rej('invalid password param'); | ||||
| 
 | ||||
| 	// Compare password
 | ||||
| 	const same = bcrypt.compareSync(password, user.password); | ||||
| 
 | ||||
| 	if (!same) { | ||||
| 		return rej('incorrect password'); | ||||
| 	} | ||||
| 
 | ||||
| 	// Generate secret
 | ||||
| 	const secret = generateUserToken(); | ||||
| 
 | ||||
| 	await User.update(user._id, { | ||||
| 		$set: { | ||||
| 			token: secret | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	res(); | ||||
| 
 | ||||
| 	// Publish i updated event
 | ||||
| 	event(user._id, 'my_token_regenerated'); | ||||
| }); | ||||
|  | @ -1,10 +1,10 @@ | |||
| import * as express from 'express'; | ||||
| import * as bcrypt from 'bcryptjs'; | ||||
| import rndstr from 'rndstr'; | ||||
| import recaptcha = require('recaptcha-promise'); | ||||
| import User from '../models/user'; | ||||
| import { validateUsername, validatePassword } from '../models/user'; | ||||
| import serialize from '../serializers/user'; | ||||
| import generateUserToken from '../common/generate-native-user-token'; | ||||
| import config from '../../conf'; | ||||
| 
 | ||||
| recaptcha.init({ | ||||
|  | @ -58,7 +58,7 @@ export default async (req: express.Request, res: express.Response) => { | |||
| 	const hash = bcrypt.hashSync(password, salt); | ||||
| 
 | ||||
| 	// Generate secret
 | ||||
| 	const secret = `!${rndstr('a-zA-Z0-9', 32)}`; | ||||
| 	const secret = generateUserToken(); | ||||
| 
 | ||||
| 	// Create account
 | ||||
| 	const account = await User.insert({ | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| 'use strict'; | ||||
| 
 | ||||
| import Stream from './stream'; | ||||
| import signout from './signout'; | ||||
| 
 | ||||
| /** | ||||
|  * Home stream connection | ||||
|  | @ -12,6 +13,11 @@ class Connection extends Stream { | |||
| 		}); | ||||
| 
 | ||||
| 		this.on('i_updated', me.update); | ||||
| 
 | ||||
| 		this.on('my_token_regenerated', () => { | ||||
| 			alert('%i18n:common.my-token-regenerated%'); | ||||
| 			signout(); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,27 +0,0 @@ | |||
| <mk-api-info> | ||||
| 	<p>Token:<code>{ I.token }</code></p> | ||||
| 	<p>APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。</p> | ||||
| 	<p>アカウントを乗っ取られてしまう可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。</p> | ||||
| 	<p>万が一このトークンが漏れたりその可能性がある場合は | ||||
| 		<button class="regenerate" onclick={ regenerateToken }>トークンを再生成</button>できます。(副作用として、ログインしているすべてのデバイスでログアウトが発生します) | ||||
| 	</p> | ||||
| 	<style> | ||||
| 		:scope | ||||
| 			display block | ||||
| 			color #4a535a | ||||
| 
 | ||||
| 			code | ||||
| 				padding 4px | ||||
| 				background #eee | ||||
| 
 | ||||
| 			.regenerate | ||||
| 				display inline | ||||
| 				color $theme-color | ||||
| 
 | ||||
| 				&:hover | ||||
| 					text-decoration underline | ||||
| 	</style> | ||||
| 	<script> | ||||
| 		this.mixin('i'); | ||||
| 	</script> | ||||
| </mk-api-info> | ||||
|  | @ -14,7 +14,6 @@ require('./forkit.tag'); | |||
| require('./introduction.tag'); | ||||
| require('./copyright.tag'); | ||||
| require('./signin-history.tag'); | ||||
| require('./api-info.tag'); | ||||
| require('./twitter-setting.tag'); | ||||
| require('./authorized-apps.tag'); | ||||
| require('./poll.tag'); | ||||
|  |  | |||
							
								
								
									
										11
									
								
								src/web/app/desktop/scripts/password-dialog.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/web/app/desktop/scripts/password-dialog.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| import * as riot from 'riot'; | ||||
| 
 | ||||
| export default (title, onOk, onCancel) => { | ||||
| 	const dialog = document.body.appendChild(document.createElement('mk-input-dialog')); | ||||
| 	return riot.mount(dialog, { | ||||
| 		title: title, | ||||
| 		type: 'password', | ||||
| 		onOk: onOk, | ||||
| 		onCancel: onCancel | ||||
| 	}); | ||||
| }; | ||||
|  | @ -5,7 +5,7 @@ | |||
| 		</yield> | ||||
| 		<yield to="content"> | ||||
| 			<div class="body"> | ||||
| 				<input ref="text" oninput={ parent.update } onkeydown={ parent.onKeydown } placeholder={ parent.placeholder }/> | ||||
| 				<input ref="text" type={ parent.type } oninput={ parent.onInput } onkeydown={ parent.onKeydown } placeholder={ parent.placeholder }/> | ||||
| 			</div> | ||||
| 			<div class="action"> | ||||
| 				<button class="cancel" onclick={ parent.cancel }>キャンセル</button> | ||||
|  | @ -126,6 +126,7 @@ | |||
| 		this.placeholder = this.opts.placeholder; | ||||
| 		this.default = this.opts.default; | ||||
| 		this.allowEmpty = this.opts.allowEmpty != null ? this.opts.allowEmpty : true; | ||||
| 		this.type = this.opts.type ? this.opts.type : 'text'; | ||||
| 
 | ||||
| 		this.on('mount', () => { | ||||
| 			this.text = this.refs.window.refs.text; | ||||
|  | @ -156,6 +157,10 @@ | |||
| 			this.refs.window.close(); | ||||
| 		}; | ||||
| 
 | ||||
| 		this.onInput = () => { | ||||
| 			this.update(); | ||||
| 		}; | ||||
| 
 | ||||
| 		this.onKeydown = e => { | ||||
| 			if (e.which == 13) { // Enter | ||||
| 				e.preventDefault(); | ||||
|  |  | |||
|  | @ -211,3 +211,33 @@ | |||
| 		}; | ||||
| 	</script> | ||||
| </mk-settings> | ||||
| 
 | ||||
| <mk-api-info> | ||||
| 	<p>Token:<code>{ I.token }</code></p> | ||||
| 	<p>APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。</p> | ||||
| 	<p>アカウントを乗っ取られてしまう可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。</p> | ||||
| 	<p>万が一このトークンが漏れたりその可能性がある場合は<a class="regenerate" onclick={ regenerateToken }>トークンを再生成</a>できます。(副作用として、ログインしているすべてのデバイスでログアウトが発生します)</p> | ||||
| 	<style> | ||||
| 		:scope | ||||
| 			display block | ||||
| 			color #4a535a | ||||
| 
 | ||||
| 			code | ||||
| 				padding 4px | ||||
| 				background #eee | ||||
| 	</style> | ||||
| 	<script> | ||||
| 		import passwordDialog from '../scripts/password-dialog'; | ||||
| 
 | ||||
| 		this.mixin('i'); | ||||
| 		this.mixin('api'); | ||||
| 
 | ||||
| 		this.regenerateToken = () => { | ||||
| 			passwordDialog('%i18n:desktop.tags.mk-api-info.regenerate-token%', password => { | ||||
| 				this.api('i/regenerate_token', { | ||||
| 					password: password | ||||
| 				}) | ||||
| 			}); | ||||
| 		}; | ||||
| 	</script> | ||||
| </mk-api-info> | ||||
|  |  | |||
|  | @ -15,3 +15,22 @@ | |||
| 		}); | ||||
| 	</script> | ||||
| </mk-api-info-page> | ||||
| 
 | ||||
| <mk-api-info> | ||||
| 	<p>Token:<code>{ I.token }</code></p> | ||||
| 	<p>APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。</p> | ||||
| 	<p>アカウントを乗っ取られてしまう可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。</p> | ||||
| 	<p>万が一このトークンが漏れたりその可能性がある場合はデスクトップ版Misskeyから再生成できます。</p> | ||||
| 	<style> | ||||
| 		:scope | ||||
| 			display block | ||||
| 			color #4a535a | ||||
| 
 | ||||
| 			code | ||||
| 				padding 4px | ||||
| 				background #eee | ||||
| 	</style> | ||||
| 	<script> | ||||
| 		this.mixin('i'); | ||||
| 	</script> | ||||
| </mk-api-info> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue