feat: トークン手動発行機能
This commit is contained in:
		
							parent
							
								
									0a4499fd03
								
							
						
					
					
						commit
						0c1de7b1b6
					
				
					 7 changed files with 117 additions and 6 deletions
				
			
		|  | @ -529,6 +529,10 @@ pluginInstallWarn: "信頼できないプラグインはインストールしな | ||||||
| deck: "デッキ" | deck: "デッキ" | ||||||
| undeck: "デッキ解除" | undeck: "デッキ解除" | ||||||
| useBlurEffectForModal: "モーダルにぼかし効果を使用" | useBlurEffectForModal: "モーダルにぼかし効果を使用" | ||||||
|  | generateAccessToken: "アクセストークンの発行" | ||||||
|  | permission: "権限" | ||||||
|  | enableAll: "全て有効にする" | ||||||
|  | disableAll: "全て無効にする" | ||||||
| 
 | 
 | ||||||
| _theme: | _theme: | ||||||
|   explore: "テーマを探す" |   explore: "テーマを探す" | ||||||
|  |  | ||||||
							
								
								
									
										89
									
								
								src/client/components/token-generate-window.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/client/components/token-generate-window.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | ||||||
|  | <template> | ||||||
|  | <x-window ref="window" :width="400" :height="450" :no-padding="true" @closed="() => { $emit('closed'); destroyDom(); }" :with-ok-button="true" :ok-button-disabled="false" @ok="ok()" :can-close="false"> | ||||||
|  | 	<template #header>{{ title || $t('generateAccessToken') }}</template> | ||||||
|  | 	<div class="ugkkpisj"> | ||||||
|  | 		<div> | ||||||
|  | 			<mk-input v-model="name">{{ $t('name') }}</mk-input> | ||||||
|  | 		</div> | ||||||
|  | 		<div> | ||||||
|  | 			<div style="margin-bottom: 16px;"><b>{{ $t('permission') }}</b></div> | ||||||
|  | 			<mk-button inline @click="disableAll">{{ $t('disableAll') }}</mk-button> | ||||||
|  | 			<mk-button inline @click="enableAll">{{ $t('enableAll') }}</mk-button> | ||||||
|  | 			<mk-switch v-for="kind in kinds" :key="kind" v-model="permissions[kind]">{{ $t(`_permissions.${kind}`) }}</mk-switch> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </x-window> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | import Vue from 'vue'; | ||||||
|  | import { kinds } from '../../misc/api-permissions'; | ||||||
|  | import XWindow from './window.vue'; | ||||||
|  | import MkInput from './ui/input.vue'; | ||||||
|  | import MkTextarea from './ui/textarea.vue'; | ||||||
|  | import MkSwitch from './ui/switch.vue'; | ||||||
|  | import MkButton from './ui/button.vue'; | ||||||
|  | 
 | ||||||
|  | export default Vue.extend({ | ||||||
|  | 	components: { | ||||||
|  | 		XWindow, | ||||||
|  | 		MkInput, | ||||||
|  | 		MkTextarea, | ||||||
|  | 		MkSwitch, | ||||||
|  | 		MkButton, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	props: { | ||||||
|  | 		title: { | ||||||
|  | 			type: String, | ||||||
|  | 			required: false, | ||||||
|  | 			default: null | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			name: null, | ||||||
|  | 			permissions: {}, | ||||||
|  | 			kinds | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	created() { | ||||||
|  | 		for (const kind of this.kinds) { | ||||||
|  | 			Vue.set(this.permissions, kind, false); | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	methods: { | ||||||
|  | 		ok() { | ||||||
|  | 			this.$emit('ok', { | ||||||
|  | 				name: this.name, | ||||||
|  | 				permissions: Object.keys(this.permissions).filter(p => this.permissions[p]) | ||||||
|  | 			}); | ||||||
|  | 			this.$refs.window.close(); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		disableAll() { | ||||||
|  | 			for (const p in this.permissions) { | ||||||
|  | 				this.permissions[p] = false; | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		enableAll() { | ||||||
|  | 			for (const p in this.permissions) { | ||||||
|  | 				this.permissions[p] = true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .ugkkpisj { | ||||||
|  | 	> div { | ||||||
|  | 		padding: 24px; | ||||||
|  | 		border-top: solid 1px var(--divider); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | @ -2,9 +2,7 @@ | ||||||
| <section class="_card"> | <section class="_card"> | ||||||
| 	<div class="_title"><fa :icon="faKey"/> API</div> | 	<div class="_title"><fa :icon="faKey"/> API</div> | ||||||
| 	<div class="_content"> | 	<div class="_content"> | ||||||
| 		<mk-input :value="$store.state.i.token" readonly> | 		<mk-button @click="generateToken">{{ $t('generateAccessToken') }}</mk-button> | ||||||
| 			<span>{{ $t('token') }}</span> |  | ||||||
| 		</mk-input> |  | ||||||
| 		<mk-button @click="regenerateToken"><fa :icon="faSyncAlt"/> {{ $t('regenerate') }}</mk-button> | 		<mk-button @click="regenerateToken"><fa :icon="faSyncAlt"/> {{ $t('regenerate') }}</mk-button> | ||||||
| 	</div> | 	</div> | ||||||
| </section> | </section> | ||||||
|  | @ -26,6 +24,22 @@ export default Vue.extend({ | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| 	methods: { | 	methods: { | ||||||
|  | 		async generateToken() { | ||||||
|  | 			this.$root.new(await import('../../components/token-generate-window.vue').then(m => m.default), { | ||||||
|  | 			}).$on('ok', async ({ name, permissions }) => { | ||||||
|  | 				const { token } = await this.$root.api('miauth/gen-token', { | ||||||
|  | 					session: null, | ||||||
|  | 					name: name, | ||||||
|  | 					permission: permissions, | ||||||
|  | 				}); | ||||||
|  | 
 | ||||||
|  | 				this.$root.dialog({ | ||||||
|  | 					type: 'success', | ||||||
|  | 					title: this.$t('token'), | ||||||
|  | 					text: token | ||||||
|  | 				}); | ||||||
|  | 			}); | ||||||
|  | 		}, | ||||||
| 		regenerateToken() { | 		regenerateToken() { | ||||||
| 			this.$root.dialog({ | 			this.$root.dialog({ | ||||||
| 				title: this.$t('password'), | 				title: this.$t('password'), | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ export const meta = { | ||||||
| 
 | 
 | ||||||
| 	params: { | 	params: { | ||||||
| 		session: { | 		session: { | ||||||
| 			validator: $.str | 			validator: $.nullable.str | ||||||
| 		}, | 		}, | ||||||
| 
 | 
 | ||||||
| 		name: { | 		name: { | ||||||
|  | @ -52,4 +52,8 @@ export default define(meta, async (ps, user) => { | ||||||
| 		iconUrl: ps.iconUrl, | 		iconUrl: ps.iconUrl, | ||||||
| 		permission: ps.permission, | 		permission: ps.permission, | ||||||
| 	}); | 	}); | ||||||
|  | 
 | ||||||
|  | 	return { | ||||||
|  | 		token: accessToken | ||||||
|  | 	}; | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -78,7 +78,7 @@ router.post('/miauth/:session/check', async ctx => { | ||||||
| 		session: ctx.params.session | 		session: ctx.params.session | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	if (token && !token.fetched) { | 	if (token && token.session != null && !token.fetched) { | ||||||
| 		AccessTokens.update(token.id, { | 		AccessTokens.update(token.id, { | ||||||
| 			fetched: true | 			fetched: true | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import endpoints from '../endpoints'; | import endpoints from '../endpoints'; | ||||||
| import * as locale from '../../../../locales/'; | import * as locale from '../../../../locales/'; | ||||||
| import { kinds as kindsList } from '../kinds'; | import { kinds as kindsList } from '../../../misc/api-permissions'; | ||||||
| 
 | 
 | ||||||
| export interface IKindInfo { | export interface IKindInfo { | ||||||
| 	endpoints: string[]; | 	endpoints: string[]; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue