nameId廃止 & アプリ作成時にシークレットを返すように
This commit is contained in:
		
							parent
							
								
									d60c3c4ee3
								
							
						
					
					
						commit
						bb7b335491
					
				src
client/app
models
server/api/endpoints/app
|  | @ -7,7 +7,7 @@ | ||||||
| 	<div class="app"> | 	<div class="app"> | ||||||
| 		<section> | 		<section> | ||||||
| 			<h2>{{ app.name }}</h2> | 			<h2>{{ app.name }}</h2> | ||||||
| 			<p class="nid">{{ app.nameId }}</p> | 			<p class="id">{{ app.id }}</p> | ||||||
| 			<p class="description">{{ app.description }}</p> | 			<p class="description">{{ app.description }}</p> | ||||||
| 		</section> | 		</section> | ||||||
| 		<section> | 		<section> | ||||||
|  |  | ||||||
|  | @ -5,16 +5,6 @@ | ||||||
| 			<b-form-group label="アプリケーション名" description="あなたのアプリの名称。"> | 			<b-form-group label="アプリケーション名" description="あなたのアプリの名称。"> | ||||||
| 				<b-form-input v-model="name" type="text" placeholder="ex) Misskey for iOS" autocomplete="off" required/> | 				<b-form-input v-model="name" type="text" placeholder="ex) Misskey for iOS" autocomplete="off" required/> | ||||||
| 			</b-form-group> | 			</b-form-group> | ||||||
| 			<b-form-group label="ID" description="あなたのアプリのID。"> |  | ||||||
| 				<b-input v-model="nid" type="text" pattern="^[a-zA-Z0-9_]{1,30}$" placeholder="ex) misskey-for-ios" autocomplete="off" required/> |  | ||||||
| 				<p class="info" v-if="nidState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%確認しています...</p> |  | ||||||
| 				<p class="info" v-if="nidState == 'ok'" style="color:#3CB7B5">%fa:fw check%利用できます</p> |  | ||||||
| 				<p class="info" v-if="nidState == 'unavailable'" style="color:#FF1161">%fa:fw exclamation-triangle%既に利用されています</p> |  | ||||||
| 				<p class="info" v-if="nidState == 'error'" style="color:#FF1161">%fa:fw exclamation-triangle%通信エラー</p> |  | ||||||
| 				<p class="info" v-if="nidState == 'invalid-format'" style="color:#FF1161">%fa:fw exclamation-triangle%a~z、A~Z、0~9、_が使えます</p> |  | ||||||
| 				<p class="info" v-if="nidState == 'min-range'" style="color:#FF1161">%fa:fw exclamation-triangle%1文字以上でお願いします!</p> |  | ||||||
| 				<p class="info" v-if="nidState == 'max-range'" style="color:#FF1161">%fa:fw exclamation-triangle%30文字以内でお願いします</p> |  | ||||||
| 			</b-form-group> |  | ||||||
| 			<b-form-group label="アプリの概要" description="あなたのアプリの簡単な説明や紹介。"> | 			<b-form-group label="アプリの概要" description="あなたのアプリの簡単な説明や紹介。"> | ||||||
| 				<b-textarea v-model="description" placeholder="ex) Misskey iOSクライアント。" autocomplete="off" required></b-textarea> | 				<b-textarea v-model="description" placeholder="ex) Misskey iOSクライアント。" autocomplete="off" required></b-textarea> | ||||||
| 			</b-form-group> | 			</b-form-group> | ||||||
|  | @ -50,47 +40,16 @@ export default Vue.extend({ | ||||||
| 	data() { | 	data() { | ||||||
| 		return { | 		return { | ||||||
| 			name: '', | 			name: '', | ||||||
| 			nid: '', |  | ||||||
| 			description: '', | 			description: '', | ||||||
| 			cb: '', | 			cb: '', | ||||||
| 			nidState: null, | 			nidState: null, | ||||||
| 			permission: [] | 			permission: [] | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| 	watch: { |  | ||||||
| 		nid() { |  | ||||||
| 			if (this.nid == null || this.nid == '') { |  | ||||||
| 				this.nidState = null; |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			const err = |  | ||||||
| 				!this.nid.match(/^[a-zA-Z0-9_]+$/) ? 'invalid-format' : |  | ||||||
| 				this.nid.length < 1                 ? 'min-range' : |  | ||||||
| 				this.nid.length > 30                ? 'max-range' : |  | ||||||
| 				null; |  | ||||||
| 
 |  | ||||||
| 			if (err) { |  | ||||||
| 				this.nidState = err; |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			this.nidState = 'wait'; |  | ||||||
| 
 |  | ||||||
| 			(this as any).api('app/name_id/available', { |  | ||||||
| 				nameId: this.nid |  | ||||||
| 			}).then(result => { |  | ||||||
| 				this.nidState = result.available ? 'ok' : 'unavailable'; |  | ||||||
| 			}).catch(err => { |  | ||||||
| 				this.nidState = 'error'; |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	methods: { | 	methods: { | ||||||
| 		onSubmit() { | 		onSubmit() { | ||||||
| 			(this as any).api('app/create', { | 			(this as any).api('app/create', { | ||||||
| 				name: this.name, | 				name: this.name, | ||||||
| 				nameId: this.nid, |  | ||||||
| 				description: this.description, | 				description: this.description, | ||||||
| 				callbackUrl: this.cb, | 				callbackUrl: this.cb, | ||||||
| 				permission: this.permission | 				permission: this.permission | ||||||
|  |  | ||||||
|  | @ -5,8 +5,6 @@ import db from '../db/mongodb'; | ||||||
| import config from '../config'; | import config from '../config'; | ||||||
| 
 | 
 | ||||||
| const App = db.get<IApp>('apps'); | const App = db.get<IApp>('apps'); | ||||||
| App.createIndex('nameId'); |  | ||||||
| App.createIndex('nameIdLower'); |  | ||||||
| App.createIndex('secret'); | App.createIndex('secret'); | ||||||
| export default App; | export default App; | ||||||
| 
 | 
 | ||||||
|  | @ -16,17 +14,11 @@ export type IApp = { | ||||||
| 	userId: mongo.ObjectID | null; | 	userId: mongo.ObjectID | null; | ||||||
| 	secret: string; | 	secret: string; | ||||||
| 	name: string; | 	name: string; | ||||||
| 	nameId: string; |  | ||||||
| 	nameIdLower: string; |  | ||||||
| 	description: string; | 	description: string; | ||||||
| 	permission: string[]; | 	permission: string[]; | ||||||
| 	callbackUrl: string; | 	callbackUrl: string; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export function isValidNameId(nameId: string): boolean { |  | ||||||
| 	return typeof nameId == 'string' && /^[a-zA-Z0-9_]{1,30}$/.test(nameId); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Pack an app for API response |  * Pack an app for API response | ||||||
|  * |  * | ||||||
|  | @ -76,8 +68,6 @@ export const pack = ( | ||||||
| 	_app.id = _app._id; | 	_app.id = _app._id; | ||||||
| 	delete _app._id; | 	delete _app._id; | ||||||
| 
 | 
 | ||||||
| 	delete _app.nameIdLower; |  | ||||||
| 
 |  | ||||||
| 	// Visible by only owner
 | 	// Visible by only owner
 | ||||||
| 	if (!opts.includeSecret) { | 	if (!opts.includeSecret) { | ||||||
| 		delete _app.secret; | 		delete _app.secret; | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import rndstr from 'rndstr'; | import rndstr from 'rndstr'; | ||||||
| import $ from 'cafy'; | import $ from 'cafy'; | ||||||
| import App, { isValidNameId, pack } from '../../../../models/app'; | import App, { pack } from '../../../../models/app'; | ||||||
| import { ILocalUser } from '../../../../models/user'; | import { ILocalUser } from '../../../../models/user'; | ||||||
| 
 | 
 | ||||||
| export const meta = { | export const meta = { | ||||||
|  | @ -11,10 +11,6 @@ export const meta = { | ||||||
|  * Create an app |  * Create an app | ||||||
|  */ |  */ | ||||||
| export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { | export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => { | ||||||
| 	// Get 'nameId' parameter
 |  | ||||||
| 	const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId); |  | ||||||
| 	if (nameIdErr) return rej('invalid nameId param'); |  | ||||||
| 
 |  | ||||||
| 	// Get 'name' parameter
 | 	// Get 'name' parameter
 | ||||||
| 	const [name, nameErr] = $.str.get(params.name); | 	const [name, nameErr] = $.str.get(params.name); | ||||||
| 	if (nameErr) return rej('invalid name param'); | 	if (nameErr) return rej('invalid name param'); | ||||||
|  | @ -40,8 +36,6 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res, | ||||||
| 		createdAt: new Date(), | 		createdAt: new Date(), | ||||||
| 		userId: user && user._id, | 		userId: user && user._id, | ||||||
| 		name: name, | 		name: name, | ||||||
| 		nameId: nameId, |  | ||||||
| 		nameIdLower: nameId.toLowerCase(), |  | ||||||
| 		description: description, | 		description: description, | ||||||
| 		permission: permission, | 		permission: permission, | ||||||
| 		callbackUrl: callbackUrl, | 		callbackUrl: callbackUrl, | ||||||
|  | @ -49,5 +43,7 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res, | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	// Response
 | 	// Response
 | ||||||
| 	res(await pack(app)); | 	res(await pack(app, null, { | ||||||
|  | 		includeSecret: true | ||||||
|  | 	})); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -1,31 +0,0 @@ | ||||||
| /** |  | ||||||
|  * Module dependencies |  | ||||||
|  */ |  | ||||||
| import $ from 'cafy'; |  | ||||||
| import App from '../../../../../models/app'; |  | ||||||
| import { isValidNameId } from '../../../../../models/app'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Check available nameId of app |  | ||||||
|  * |  | ||||||
|  * @param {any} params |  | ||||||
|  * @return {Promise<any>} |  | ||||||
|  */ |  | ||||||
| export default async (params: any) => new Promise(async (res, rej) => { |  | ||||||
| 	// Get 'nameId' parameter
 |  | ||||||
| 	const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId); |  | ||||||
| 	if (nameIdErr) return rej('invalid nameId param'); |  | ||||||
| 
 |  | ||||||
| 	// Get exist
 |  | ||||||
| 	const exist = await App |  | ||||||
| 		.count({ |  | ||||||
| 			nameIdLower: nameId.toLowerCase() |  | ||||||
| 		}, { |  | ||||||
| 			limit: 1 |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 	// Reply
 |  | ||||||
| 	res({ |  | ||||||
| 		available: exist === 0 |  | ||||||
| 	}); |  | ||||||
| }); |  | ||||||
|  | @ -9,21 +9,11 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async ( | ||||||
| 	const isSecure = user != null && app == null; | 	const isSecure = user != null && app == null; | ||||||
| 
 | 
 | ||||||
| 	// Get 'appId' parameter
 | 	// Get 'appId' parameter
 | ||||||
| 	const [appId, appIdErr] = $.type(ID).optional.get(params.appId); | 	const [appId, appIdErr] = $.type(ID).get(params.appId); | ||||||
| 	if (appIdErr) return rej('invalid appId param'); | 	if (appIdErr) return rej('invalid appId param'); | ||||||
| 
 | 
 | ||||||
| 	// Get 'nameId' parameter
 |  | ||||||
| 	const [nameId, nameIdErr] = $.str.optional.get(params.nameId); |  | ||||||
| 	if (nameIdErr) return rej('invalid nameId param'); |  | ||||||
| 
 |  | ||||||
| 	if (appId === undefined && nameId === undefined) { |  | ||||||
| 		return rej('appId or nameId is required'); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Lookup app
 | 	// Lookup app
 | ||||||
| 	const ap = appId !== undefined | 	const ap = await App.findOne({ _id: appId }); | ||||||
| 		? await App.findOne({ _id: appId }) |  | ||||||
| 		: await App.findOne({ nameIdLower: nameId.toLowerCase() }); |  | ||||||
| 
 | 
 | ||||||
| 	if (ap === null) { | 	if (ap === null) { | ||||||
| 		return rej('app not found'); | 		return rej('app not found'); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue