Merge branch 'develop' of https://github.com/syuilo/misskey into develop
This commit is contained in:
		
						commit
						31c26354c5
					
				
					 19 changed files with 183 additions and 49 deletions
				
			
		| 
						 | 
					@ -74,10 +74,26 @@ common:
 | 
				
			||||||
  favorites: "お気に入り"
 | 
					  favorites: "お気に入り"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  permissions:
 | 
					  permissions:
 | 
				
			||||||
    'read:account': "アカウントの情報を見る"
 | 
					    "read:account": "アカウントの情報を見る"
 | 
				
			||||||
    'write:account': "アカウントの情報を変更する"
 | 
					    "write:account": "アカウントの情報を変更する"
 | 
				
			||||||
    'read:drive': "ドライブを見る"
 | 
					    "read:blocks": "ブロックを見る"
 | 
				
			||||||
    'write:drive': "ドライブを操作する"
 | 
					    "write:blocks": "ブロックを操作する"
 | 
				
			||||||
 | 
					    "read:drive": "ドライブを見る"
 | 
				
			||||||
 | 
					    "write:drive": "ドライブを操作する"
 | 
				
			||||||
 | 
					    "read:favorites": "お気に入りを見る"
 | 
				
			||||||
 | 
					    "write:favorites": "お気に入りを操作する"
 | 
				
			||||||
 | 
					    "read:following": "フォローの情報を見る"
 | 
				
			||||||
 | 
					    "write:following": "フォロー・フォロー解除する"
 | 
				
			||||||
 | 
					    "read:messaging": "トークを見る"
 | 
				
			||||||
 | 
					    "write:messaging": "トークを操作する"
 | 
				
			||||||
 | 
					    "read:mutes": "ミュートを見る"
 | 
				
			||||||
 | 
					    "write:mutes": "ミュートを操作する"
 | 
				
			||||||
 | 
					    "write:notes": "投稿を作成・削除する"
 | 
				
			||||||
 | 
					    "read:notifications": "通知を見る"
 | 
				
			||||||
 | 
					    "write:notifications": "通知を操作する"
 | 
				
			||||||
 | 
					    "read:reactions": "リアクションを見る"
 | 
				
			||||||
 | 
					    "write:reactions": "リアクションを操作する"
 | 
				
			||||||
 | 
					    "write:votes": "投票する"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  empty-timeline-info:
 | 
					  empty-timeline-info:
 | 
				
			||||||
    follow-users-to-make-your-timeline: "ユーザーをフォローすると投稿がタイムラインに表示されます。"
 | 
					    follow-users-to-make-your-timeline: "ユーザーをフォローすると投稿がタイムラインに表示されます。"
 | 
				
			||||||
| 
						 | 
					@ -1804,14 +1820,17 @@ dev/views/apps.vue:
 | 
				
			||||||
  app-missing: "アプリなし"
 | 
					  app-missing: "アプリなし"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev/views/new-app.vue:
 | 
					dev/views/new-app.vue:
 | 
				
			||||||
 | 
					  new-app: "新しいアプリケーション"
 | 
				
			||||||
 | 
					  new-app-info: "アプリケーションはAPIからでも作成できます。 (app/create)"
 | 
				
			||||||
  create-app: "アプリケーションの作成"
 | 
					  create-app: "アプリケーションの作成"
 | 
				
			||||||
  app-name: "アプリケーション名"
 | 
					  app-name: "アプリケーション名"
 | 
				
			||||||
 | 
					  app-name-placeholder: "ex) Misskey for iOS"
 | 
				
			||||||
  app-name-desc: "あなたのアプリの名称。"
 | 
					  app-name-desc: "あなたのアプリの名称。"
 | 
				
			||||||
  app-name-ex: "ex) Misskey for iOS"
 | 
					 | 
				
			||||||
  app-overview: "アプリの概要"
 | 
					  app-overview: "アプリの概要"
 | 
				
			||||||
  app-desc: "あなたのアプリの簡単な説明や紹介。"
 | 
					  app-overview-placeholder: " ex) Misskey iOSクライアント。"
 | 
				
			||||||
  app-desc-ex: "ex) Misskey iOSクライアント。"
 | 
					  app-overview-desc: "あなたのアプリの簡単な説明や紹介。"
 | 
				
			||||||
  callback-url: "コールバックURL (オプション)"
 | 
					  callback-url: "コールバックURL (オプション)"
 | 
				
			||||||
 | 
					  callback-url-placeholder: "ex) https://your.app.example.com/callback.php"
 | 
				
			||||||
  callback-url-desc: "ユーザーが認証フォームで認証した際にリダイレクトするURLを設定できます。"
 | 
					  callback-url-desc: "ユーザーが認証フォームで認証した際にリダイレクトするURLを設定できます。"
 | 
				
			||||||
  authority: "権限"
 | 
					  authority: "権限"
 | 
				
			||||||
  authority-desc: "ここで要求した機能だけがAPIからアクセスできます。"
 | 
					  authority-desc: "ここで要求した機能だけがAPIからアクセスできます。"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<mk-ui>
 | 
					<mk-ui>
 | 
				
			||||||
	<b-card :header="$t('header')">
 | 
						<b-card :header="$t('manage-apps')">
 | 
				
			||||||
		<b-button to="/app/new" variant="primary">{{ $t('create-app') }}</b-button>
 | 
							<b-button to="/app/new" variant="primary">{{ $t('create-app') }}</b-button>
 | 
				
			||||||
		<hr>
 | 
							<hr>
 | 
				
			||||||
		<div class="apps">
 | 
							<div class="apps">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,35 +1,22 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<mk-ui>
 | 
					<mk-ui>
 | 
				
			||||||
	<b-card :header="$t('header')">
 | 
						<b-card :header="$t('new-app')">
 | 
				
			||||||
 | 
							<b-alert show variant="info"><fa icon="info-circle"/> {{ $t('new-app-info') }}</b-alert>
 | 
				
			||||||
		<b-form @submit.prevent="onSubmit" autocomplete="off">
 | 
							<b-form @submit.prevent="onSubmit" autocomplete="off">
 | 
				
			||||||
			<b-form-group :label="$t('app-name')" :description="$t('description')">
 | 
								<b-form-group :label="$t('app-name')" :description="$t('app-name-desc')">
 | 
				
			||||||
				<b-form-input v-model="name" type="text" :placeholder="$t('placeholder')" autocomplete="off" required/>
 | 
									<b-form-input v-model="name" type="text" :placeholder="$t('app-name-placeholder')" autocomplete="off" required/>
 | 
				
			||||||
			</b-form-group>
 | 
								</b-form-group>
 | 
				
			||||||
			<b-form-group :label="$t('app-overview')" :description="$t('description')">
 | 
								<b-form-group :label="$t('app-overview')" :description="$t('app-overview-desc')">
 | 
				
			||||||
				<b-textarea v-model="description" :placeholder="$t('placeholder')" autocomplete="off" required></b-textarea>
 | 
									<b-textarea v-model="description" :placeholder="$t('app-overview-placeholder')" autocomplete="off" required></b-textarea>
 | 
				
			||||||
			</b-form-group>
 | 
								</b-form-group>
 | 
				
			||||||
			<b-form-group :label="$t('callback-url')" :description="$t('description')">
 | 
								<b-form-group :label="$t('callback-url')" :description="$t('callback-url-desc')">
 | 
				
			||||||
				<b-input v-model="cb" type="url" placeholder="ex) https://your.app.example.com/callback.php" autocomplete="off"/>
 | 
									<b-input v-model="cb" type="url" :placeholder="$t('callback-url-placeholder')" autocomplete="off"/>
 | 
				
			||||||
			</b-form-group>
 | 
								</b-form-group>
 | 
				
			||||||
			<b-card :header="$t('header')">
 | 
								<b-card :header="$t('authority')">
 | 
				
			||||||
				<b-form-group :description="$t('description')">
 | 
									<b-form-group :description="$t('authority-desc')">
 | 
				
			||||||
					<b-alert show variant="warning"><fa icon="exclamation-triangle"/> {{ $t('authority-warning') }}</b-alert>
 | 
										<b-alert show variant="warning"><fa icon="exclamation-triangle"/> {{ $t('authority-warning') }}</b-alert>
 | 
				
			||||||
					<b-form-checkbox-group v-model="permission" stacked>
 | 
										<b-form-checkbox-group v-model="permission" stacked>
 | 
				
			||||||
						<b-form-checkbox value="read:account">{{ $t('read:account') }}</b-form-checkbox>
 | 
											<b-form-checkbox v-for="v in permissionsList" :value="v" :key="v">{{ $t(`@.permissions.${v}`) }} ({{ v }})</b-form-checkbox>
 | 
				
			||||||
						<b-form-checkbox value="write:account">{{ $t('write:account') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="write:notes">{{ $t('write:notes') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="read:reactions">{{ $t('read:reactions') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="write:reactions">{{ $t('write:reactions') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="read:following">{{ $t('read:following') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="write:following">{{ $t('write:following') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="read:mutes">{{ $t('read:mutes') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="write:mutes">{{ $t('write:mutes') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="read:blocks">{{ $t('read:blocks') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="write:blocks">{{ $t('write:blocks') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="read:drive">{{ $t('read:drive') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="write:drive">{{ $t('write:drive') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="read:notifications">{{ $t('read:notifications') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
						<b-form-checkbox value="write:notifications">{{ $t('write:notifications') }}</b-form-checkbox>
 | 
					 | 
				
			||||||
					</b-form-checkbox-group>
 | 
										</b-form-checkbox-group>
 | 
				
			||||||
				</b-form-group>
 | 
									</b-form-group>
 | 
				
			||||||
			</b-card>
 | 
								</b-card>
 | 
				
			||||||
| 
						 | 
					@ -43,6 +30,7 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
import i18n from '../../i18n';
 | 
					import i18n from '../../i18n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	i18n: i18n('dev/views/new-app.vue'),
 | 
						i18n: i18n('dev/views/new-app.vue'),
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
| 
						 | 
					@ -51,9 +39,15 @@ export default Vue.extend({
 | 
				
			||||||
			description: '',
 | 
								description: '',
 | 
				
			||||||
			cb: '',
 | 
								cb: '',
 | 
				
			||||||
			nidState: null,
 | 
								nidState: null,
 | 
				
			||||||
			permission: []
 | 
								permission: [],
 | 
				
			||||||
 | 
								permissionsList: []
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						created() {
 | 
				
			||||||
 | 
							this.$root.api('permissions').then(permissions => {
 | 
				
			||||||
 | 
								this.permissionsList = permissions
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		onSubmit() {
 | 
							onSubmit() {
 | 
				
			||||||
			this.$root.api('app/create', {
 | 
								this.$root.api('app/create', {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,3 +115,8 @@ export function cumulativeSum(xs: number[]): number[] {
 | 
				
			||||||
	for (let i = 1; i < ys.length; i++) ys[i] += ys[i - 1];
 | 
						for (let i = 1; i < ys.length; i++) ys[i] += ys[i - 1];
 | 
				
			||||||
	return ys;
 | 
						return ys;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Object.fromEntries()
 | 
				
			||||||
 | 
					export function fromEntries(xs: [string, any][]): { [x: string]: any; } {
 | 
				
			||||||
 | 
						return xs.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {} as { [x: string]: any; });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'favorites-read',
 | 
						kind: 'read:favorites',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		limit: {
 | 
							limit: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'messaging-read',
 | 
						kind: 'read:messaging',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		limit: {
 | 
							limit: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'messaging-read',
 | 
						kind: 'read:messaging',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		userId: {
 | 
							userId: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'messaging-write',
 | 
						kind: 'write:messaging',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		userId: {
 | 
							userId: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'messaging-write',
 | 
						kind: 'write:messaging',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	limit: {
 | 
						limit: {
 | 
				
			||||||
		duration: ms('1hour'),
 | 
							duration: ms('1hour'),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'messaging-write',
 | 
						kind: 'write:messaging',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		messageId: {
 | 
							messageId: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'favorite-write',
 | 
						kind: 'write:favorites',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		noteId: {
 | 
							noteId: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'favorite-write',
 | 
						kind: 'write:favorites',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		noteId: {
 | 
							noteId: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@ export const meta = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requireCredential: true,
 | 
						requireCredential: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kind: 'vote-write',
 | 
						kind: 'write:votes',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params: {
 | 
						params: {
 | 
				
			||||||
		noteId: {
 | 
							noteId: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/server/api/endpoints/permissions.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/server/api/endpoints/permissions.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					import define from '../define';
 | 
				
			||||||
 | 
					import { kindsList } from '../kinds';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const meta = {
 | 
				
			||||||
 | 
						stability: 'stable',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						desc: {
 | 
				
			||||||
 | 
							'ja-JP': 'パーミッションの一覧を返します。',
 | 
				
			||||||
 | 
							'en-US': 'Get the list of permissons.'
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tags: ['meta'],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						requireCredential: false,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						params: {
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res: {
 | 
				
			||||||
 | 
							type: 'array',
 | 
				
			||||||
 | 
							items: {
 | 
				
			||||||
 | 
								type: 'string',
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default define(meta, async () => {
 | 
				
			||||||
 | 
						return kindsList;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										58
									
								
								src/server/api/kinds.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/server/api/kinds.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,58 @@
 | 
				
			||||||
 | 
					import endpoints from './endpoints';
 | 
				
			||||||
 | 
					import * as locale from '../../../locales/';
 | 
				
			||||||
 | 
					import { fromEntries } from '../../prelude/array';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const kindsList = [
 | 
				
			||||||
 | 
						'read:account',
 | 
				
			||||||
 | 
						'write:account',
 | 
				
			||||||
 | 
						'read:blocks',
 | 
				
			||||||
 | 
						'write:blocks',
 | 
				
			||||||
 | 
						'read:drive',
 | 
				
			||||||
 | 
						'write:drive',
 | 
				
			||||||
 | 
						'read:favorites',
 | 
				
			||||||
 | 
						'write:favorites',
 | 
				
			||||||
 | 
						'read:following',
 | 
				
			||||||
 | 
						'write:following',
 | 
				
			||||||
 | 
						'read:messaging',
 | 
				
			||||||
 | 
						'write:messaging',
 | 
				
			||||||
 | 
						'read:mutes',
 | 
				
			||||||
 | 
						'write:mutes',
 | 
				
			||||||
 | 
						'write:notes',
 | 
				
			||||||
 | 
						'read:notifications',
 | 
				
			||||||
 | 
						'write:notifications',
 | 
				
			||||||
 | 
						'read:reactions',
 | 
				
			||||||
 | 
						'write:reactions',
 | 
				
			||||||
 | 
						'write:votes'
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IKindInfo {
 | 
				
			||||||
 | 
						endpoints: string[];
 | 
				
			||||||
 | 
						descs: { [x: string]: string; };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function kinds() {
 | 
				
			||||||
 | 
						const kinds = fromEntries(
 | 
				
			||||||
 | 
							kindsList
 | 
				
			||||||
 | 
								.map(k => [k, {
 | 
				
			||||||
 | 
										endpoints: [],
 | 
				
			||||||
 | 
										descs: fromEntries(
 | 
				
			||||||
 | 
											Object.keys(locale)
 | 
				
			||||||
 | 
												.map(l => [l, locale[l].common.permissions[k] as string] as [string, string])
 | 
				
			||||||
 | 
											) as { [x: string]: string; }
 | 
				
			||||||
 | 
									}] as [ string, IKindInfo ])
 | 
				
			||||||
 | 
								) as { [x: string]: IKindInfo; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const errors = [] as string[][];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (const endpoint of endpoints.filter(ep => !ep.meta.secure)) {
 | 
				
			||||||
 | 
							if (endpoint.meta.kind) {
 | 
				
			||||||
 | 
								const kind = endpoint.meta.kind;
 | 
				
			||||||
 | 
								if (kind in kinds) kinds[kind].endpoints.push(endpoint.name);
 | 
				
			||||||
 | 
								else errors.push([kind, endpoint.name]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (errors.length > 0) throw Error('\n  ' + errors.map((e) => `Unknown kind (permission) "${e[0]}" found at ${e[1]}.`).join('\n  '));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return kinds;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,14 @@
 | 
				
			||||||
import config from '../../../config';
 | 
					import config from '../../../config';
 | 
				
			||||||
 | 
					import { IKindInfo, kinds } from '../kinds';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getDescription(lang = 'ja-JP'): string {
 | 
				
			||||||
 | 
						const permissionTable = (Object.entries(kinds()) as [string, IKindInfo][])
 | 
				
			||||||
 | 
							.map(e => `|${e[0]}|${e[1].descs[lang]}|${e[1].endpoints.map(f => `[${f}](#operation/${f})`).join(', ')}|`)
 | 
				
			||||||
 | 
							.join('\n');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const descriptions = {
 | 
				
			||||||
 | 
							'ja-JP': `**Misskey is a decentralized microblogging platform.**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const description = `
 | 
					 | 
				
			||||||
## Usage
 | 
					## Usage
 | 
				
			||||||
**APIはすべてPOSTでリクエスト/レスポンスともにJSON形式です。**
 | 
					**APIはすべてPOSTでリクエスト/レスポンスともにJSON形式です。**
 | 
				
			||||||
一部のAPIはリクエストに認証情報(APIキー)が必要です。リクエストの際に\`i\`というパラメータでAPIキーを添付してください。
 | 
					一部のAPIはリクエストに認証情報(APIキー)が必要です。リクエストの際に\`i\`というパラメータでAPIキーを添付してください。
 | 
				
			||||||
| 
						 | 
					@ -44,4 +52,12 @@ APIキーの生成方法を擬似コードで表すと次のようになりま
 | 
				
			||||||
\`\`\` js
 | 
					\`\`\` js
 | 
				
			||||||
const i = sha256(userToken + secretKey);
 | 
					const i = sha256(userToken + secretKey);
 | 
				
			||||||
\`\`\`
 | 
					\`\`\`
 | 
				
			||||||
`;
 | 
					
 | 
				
			||||||
 | 
					## Permissions
 | 
				
			||||||
 | 
					|Permisson (kind)|Description|Endpoints|
 | 
				
			||||||
 | 
					|:--|:--|:--|
 | 
				
			||||||
 | 
					${permissionTable}
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
						} as { [x: string]: string };
 | 
				
			||||||
 | 
						return lang in descriptions ? descriptions[lang] : descriptions['ja-JP'];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import { Context } from 'cafy';
 | 
				
			||||||
import config from '../../../config';
 | 
					import config from '../../../config';
 | 
				
			||||||
import { errors as basicErrors } from './errors';
 | 
					import { errors as basicErrors } from './errors';
 | 
				
			||||||
import { schemas } from './schemas';
 | 
					import { schemas } from './schemas';
 | 
				
			||||||
import { description } from './description';
 | 
					import { getDescription } from './description';
 | 
				
			||||||
import { convertOpenApiSchema } from '../../../misc/schema';
 | 
					import { convertOpenApiSchema } from '../../../misc/schema';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function genOpenapiSpec(lang = 'ja-JP') {
 | 
					export function genOpenapiSpec(lang = 'ja-JP') {
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ export function genOpenapiSpec(lang = 'ja-JP') {
 | 
				
			||||||
		info: {
 | 
							info: {
 | 
				
			||||||
			version: 'v1',
 | 
								version: 'v1',
 | 
				
			||||||
			title: 'Misskey API',
 | 
								title: 'Misskey API',
 | 
				
			||||||
			description: '**Misskey is a decentralized microblogging platform.**\n\n' + description,
 | 
								description: getDescription(lang),
 | 
				
			||||||
			'x-logo': { url: '/assets/api-doc.png' }
 | 
								'x-logo': { url: '/assets/api-doc.png' }
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,10 @@ export function genOpenapiSpec(lang = 'ja-JP') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : 'No description provided.') + '\n\n';
 | 
							let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : 'No description provided.') + '\n\n';
 | 
				
			||||||
		desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`;
 | 
							desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`;
 | 
				
			||||||
		if (endpoint.meta.kind) desc += ` / **Permission**: *${endpoint.meta.kind}*`;
 | 
							if (endpoint.meta.kind) {
 | 
				
			||||||
 | 
								const kind = endpoint.meta.kind;
 | 
				
			||||||
 | 
								desc += ` / **Permission**: *${kind}*`;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const info = {
 | 
							const info = {
 | 
				
			||||||
			operationId: endpoint.name,
 | 
								operationId: endpoint.name,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								test/api.ts
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								test/api.ts
									
										
									
									
									
								
							| 
						 | 
					@ -18,6 +18,8 @@ import * as assert from 'assert';
 | 
				
			||||||
import * as childProcess from 'child_process';
 | 
					import * as childProcess from 'child_process';
 | 
				
			||||||
import { async, signup, request, post, react, uploadFile } from './utils';
 | 
					import { async, signup, request, post, react, uploadFile } from './utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { kinds } from '../src/server/api/kinds';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('API', () => {
 | 
					describe('API', () => {
 | 
				
			||||||
	let p: childProcess.ChildProcess;
 | 
						let p: childProcess.ChildProcess;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -792,7 +794,7 @@ describe('API', () => {
 | 
				
			||||||
				parentId: folderA.id
 | 
									parentId: folderA.id
 | 
				
			||||||
			}, arisugawa);
 | 
								}, arisugawa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			expect(res).have.status(400);
 | 
								assert.strictEqual(res.status, 400);
 | 
				
			||||||
		}));
 | 
							}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		it('存在しない親フォルダを設定できない', async(async () => {
 | 
							it('存在しない親フォルダを設定できない', async(async () => {
 | 
				
			||||||
| 
						 | 
					@ -965,5 +967,13 @@ describe('API', () => {
 | 
				
			||||||
			assert.strictEqual(res.body[0].id, alicePost.id);
 | 
								assert.strictEqual(res.body[0].id, alicePost.id);
 | 
				
			||||||
		}));
 | 
							}));
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						describe('kinds', () => {
 | 
				
			||||||
 | 
							it('登録されていないパーミッションを利用しているAPIがない', () => {
 | 
				
			||||||
 | 
								const res = kinds();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								assert.strictEqual(typeof res === 'object', true);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1141,7 +1141,7 @@ describe('MFM', () => {
 | 
				
			||||||
			it('exlude emotes', () => {
 | 
								it('exlude emotes', () => {
 | 
				
			||||||
				const tokens = parse('*.*');
 | 
									const tokens = parse('*.*');
 | 
				
			||||||
				assert.deepStrictEqual(tokens, [
 | 
									assert.deepStrictEqual(tokens, [
 | 
				
			||||||
					text("*.*"),
 | 
										text('*.*'),
 | 
				
			||||||
				]);
 | 
									]);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue