summaryrefslogtreecommitdiff
path: root/src/server/web/app/auth
diff options
context:
space:
mode:
authorAkihiko Odaki <nekomanma@pixiv.co.jp>2018-03-29 01:20:40 +0900
committerAkihiko Odaki <nekomanma@pixiv.co.jp>2018-03-29 01:54:41 +0900
commit90f8fe7e538bb7e52d2558152a0390e693f39b11 (patch)
tree0f830887053c8f352b1cd0c13ca715fd14c1f030 /src/server/web/app/auth
parentImplement remote account resolution (diff)
downloadsharkey-90f8fe7e538bb7e52d2558152a0390e693f39b11.tar.gz
sharkey-90f8fe7e538bb7e52d2558152a0390e693f39b11.tar.bz2
sharkey-90f8fe7e538bb7e52d2558152a0390e693f39b11.zip
Introduce processor
Diffstat (limited to 'src/server/web/app/auth')
-rw-r--r--src/server/web/app/auth/assets/logo.svg7
-rw-r--r--src/server/web/app/auth/script.ts25
-rw-r--r--src/server/web/app/auth/style.styl15
-rw-r--r--src/server/web/app/auth/views/form.vue141
-rw-r--r--src/server/web/app/auth/views/index.vue149
5 files changed, 337 insertions, 0 deletions
diff --git a/src/server/web/app/auth/assets/logo.svg b/src/server/web/app/auth/assets/logo.svg
new file mode 100644
index 0000000000..19b8a2737e
--- /dev/null
+++ b/src/server/web/app/auth/assets/logo.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
+ y="0px" width="1024px" height="512px" viewBox="0 256 1024 512" enable-background="new 0 256 1024 512" xml:space="preserve">
+<polyline opacity="0.5" fill="none" stroke="#000000" stroke-width="34" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 896.5,608.5 800.5,416.5 704.5,608.5 608.5,416.5 512.5,608.5 416.5,416.5 320.5,608.5 224.5,416.5 128.5,608.5 "/>
+</svg>
diff --git a/src/server/web/app/auth/script.ts b/src/server/web/app/auth/script.ts
new file mode 100644
index 0000000000..31c758ebc2
--- /dev/null
+++ b/src/server/web/app/auth/script.ts
@@ -0,0 +1,25 @@
+/**
+ * Authorize Form
+ */
+
+// Style
+import './style.styl';
+
+import init from '../init';
+
+import Index from './views/index.vue';
+
+/**
+ * init
+ */
+init(async (launch) => {
+ document.title = 'Misskey | アプリの連携';
+
+ // Launch the app
+ const [app] = launch();
+
+ // Routing
+ app.$router.addRoutes([
+ { path: '/:token', component: Index },
+ ]);
+});
diff --git a/src/server/web/app/auth/style.styl b/src/server/web/app/auth/style.styl
new file mode 100644
index 0000000000..bd25e1b572
--- /dev/null
+++ b/src/server/web/app/auth/style.styl
@@ -0,0 +1,15 @@
+@import "../app"
+@import "../reset"
+
+html
+ background #eee
+
+ @media (max-width 600px)
+ background #fff
+
+body
+ margin 0
+ padding 32px 0
+
+ @media (max-width 600px)
+ padding 0
diff --git a/src/server/web/app/auth/views/form.vue b/src/server/web/app/auth/views/form.vue
new file mode 100644
index 0000000000..d86ed58b38
--- /dev/null
+++ b/src/server/web/app/auth/views/form.vue
@@ -0,0 +1,141 @@
+<template>
+<div class="form">
+ <header>
+ <h1><i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?</h1>
+ <img :src="`${app.icon_url}?thumbnail&size=64`"/>
+ </header>
+ <div class="app">
+ <section>
+ <h2>{{ app.name }}</h2>
+ <p class="nid">{{ app.name_id }}</p>
+ <p class="description">{{ app.description }}</p>
+ </section>
+ <section>
+ <h2>このアプリは次の権限を要求しています:</h2>
+ <ul>
+ <template v-for="p in app.permission">
+ <li v-if="p == 'account-read'">アカウントの情報を見る。</li>
+ <li v-if="p == 'account-write'">アカウントの情報を操作する。</li>
+ <li v-if="p == 'post-write'">投稿する。</li>
+ <li v-if="p == 'like-write'">いいねしたりいいね解除する。</li>
+ <li v-if="p == 'following-write'">フォローしたりフォロー解除する。</li>
+ <li v-if="p == 'drive-read'">ドライブを見る。</li>
+ <li v-if="p == 'drive-write'">ドライブを操作する。</li>
+ <li v-if="p == 'notification-read'">通知を見る。</li>
+ <li v-if="p == 'notification-write'">通知を操作する。</li>
+ </template>
+ </ul>
+ </section>
+ </div>
+ <div class="action">
+ <button @click="cancel">キャンセル</button>
+ <button @click="accept">アクセスを許可</button>
+ </div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+ props: ['session'],
+ computed: {
+ app(): any {
+ return this.session.app;
+ }
+ },
+ methods: {
+ cancel() {
+ (this as any).api('auth/deny', {
+ token: this.session.token
+ }).then(() => {
+ this.$emit('denied');
+ });
+ },
+
+ accept() {
+ (this as any).api('auth/accept', {
+ token: this.session.token
+ }).then(() => {
+ this.$emit('accepted');
+ });
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.form
+
+ > header
+ > h1
+ margin 0
+ padding 32px 32px 20px 32px
+ font-size 24px
+ font-weight normal
+ color #777
+
+ i
+ color #77aeca
+
+ &:before
+ content '「'
+
+ &:after
+ content '」'
+
+ b
+ color #666
+
+ > img
+ display block
+ z-index 1
+ width 84px
+ height 84px
+ margin 0 auto -38px auto
+ border solid 5px #fff
+ border-radius 100%
+ box-shadow 0 2px 2px rgba(0, 0, 0, 0.1)
+
+ > .app
+ padding 44px 16px 0 16px
+ color #555
+ background #eee
+ box-shadow 0 2px 2px rgba(0, 0, 0, 0.1) inset
+
+ &:after
+ content ''
+ display block
+ clear both
+
+ > section
+ float left
+ width 50%
+ padding 8px
+ text-align left
+
+ > h2
+ margin 0
+ font-size 16px
+ color #777
+
+ > .action
+ padding 16px
+
+ > button
+ margin 0 8px
+ padding 0
+
+ @media (max-width 600px)
+ > header
+ > img
+ box-shadow none
+
+ > .app
+ box-shadow none
+
+ @media (max-width 500px)
+ > header
+ > h1
+ font-size 16px
+
+</style>
diff --git a/src/server/web/app/auth/views/index.vue b/src/server/web/app/auth/views/index.vue
new file mode 100644
index 0000000000..17e5cc6108
--- /dev/null
+++ b/src/server/web/app/auth/views/index.vue
@@ -0,0 +1,149 @@
+<template>
+<div class="index">
+ <main v-if="os.isSignedIn">
+ <p class="fetching" v-if="fetching">読み込み中<mk-ellipsis/></p>
+ <x-form
+ ref="form"
+ v-if="state == 'waiting'"
+ :session="session"
+ @denied="state = 'denied'"
+ @accepted="accepted"
+ />
+ <div class="denied" v-if="state == 'denied'">
+ <h1>アプリケーションの連携をキャンセルしました。</h1>
+ <p>このアプリがあなたのアカウントにアクセスすることはありません。</p>
+ </div>
+ <div class="accepted" v-if="state == 'accepted'">
+ <h1>{{ session.app.is_authorized ? 'このアプリは既に連携済みです' : 'アプリケーションの連携を許可しました'}}</h1>
+ <p v-if="session.app.callback_url">アプリケーションに戻っています<mk-ellipsis/></p>
+ <p v-if="!session.app.callback_url">アプリケーションに戻って、やっていってください。</p>
+ </div>
+ <div class="error" v-if="state == 'fetch-session-error'">
+ <p>セッションが存在しません。</p>
+ </div>
+ </main>
+ <main class="signin" v-if="!os.isSignedIn">
+ <h1>サインインしてください</h1>
+ <mk-signin/>
+ </main>
+ <footer><img src="/assets/auth/logo.svg" alt="Misskey"/></footer>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import XForm from './form.vue';
+
+export default Vue.extend({
+ components: {
+ XForm
+ },
+ data() {
+ return {
+ state: null,
+ session: null,
+ fetching: true
+ };
+ },
+ computed: {
+ token(): string {
+ return this.$route.params.token;
+ }
+ },
+ mounted() {
+ if (!this.$root.$data.os.isSignedIn) return;
+
+ // Fetch session
+ (this as any).api('auth/session/show', {
+ token: this.token
+ }).then(session => {
+ this.session = session;
+ this.fetching = false;
+
+ // 既に連携していた場合
+ if (this.session.app.is_authorized) {
+ this.$root.$data.os.api('auth/accept', {
+ token: this.session.token
+ }).then(() => {
+ this.accepted();
+ });
+ } else {
+ this.state = 'waiting';
+ }
+ }).catch(error => {
+ this.state = 'fetch-session-error';
+ });
+ },
+ methods: {
+ accepted() {
+ this.state = 'accepted';
+ if (this.session.app.callback_url) {
+ location.href = this.session.app.callback_url + '?token=' + this.session.token;
+ }
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.index
+
+ > main
+ width 100%
+ max-width 500px
+ margin 0 auto
+ text-align center
+ background #fff
+ box-shadow 0px 4px 16px rgba(0, 0, 0, 0.2)
+
+ > .fetching
+ margin 0
+ padding 32px
+ color #555
+
+ > div
+ padding 64px
+
+ > h1
+ margin 0 0 8px 0
+ padding 0
+ font-size 20px
+ font-weight normal
+
+ > p
+ margin 0
+ color #555
+
+ &.denied > h1
+ color #e65050
+
+ &.accepted > h1
+ color #54af7c
+
+ &.signin
+ padding 32px 32px 16px 32px
+
+ > h1
+ margin 0 0 22px 0
+ padding 0
+ font-size 20px
+ font-weight normal
+ color #555
+
+ @media (max-width 600px)
+ max-width none
+ box-shadow none
+
+ @media (max-width 500px)
+ > div
+ > h1
+ font-size 16px
+
+ > footer
+ > img
+ display block
+ width 64px
+ height 64px
+ margin 0 auto
+
+</style>