nameId廃止 & アプリ作成時にシークレットを返すように

This commit is contained in:
syuilo 2018-08-19 18:38:02 +09:00
parent e6b8ad56ef
commit eaa3cbc9ab
6 changed files with 7 additions and 103 deletions

View file

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

View file

@ -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~zA~Z0~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

View file

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

View file

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

View file

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

View file

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