From 06b66f020916eb73919c64278e07fe51d80ecc3e Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 7 Nov 2018 01:12:26 +0900
Subject: [PATCH] =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=86=E3=83=8A=E6=83=85?=
 =?UTF-8?q?=E5=A0=B1=E3=82=92DB=E3=81=AB=E4=BF=9D=E5=AD=98=E3=81=99?=
 =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .config/example.yml                           |  7 -----
 locales/ja-JP.yml                             |  3 ++
 src/client/app/admin/views/instance.vue       | 11 +++++++
 .../app/common/views/components/signup.vue    |  2 +-
 .../app/common/views/widgets/donation.vue     |  2 +-
 .../app/common/views/widgets/server.info.vue  |  2 +-
 .../app/desktop/views/components/settings.vue |  2 +-
 .../app/desktop/views/pages/welcome.vue       |  2 +-
 src/client/app/mobile/views/pages/welcome.vue |  2 +-
 src/config/types.ts                           | 18 ++----------
 src/models/meta.ts                            | 29 +++++++++++++++++++
 src/push-sw.ts                                |  2 +-
 src/server/api/endpoints/admin/update-meta.ts | 24 ++++++++++++++-
 src/server/api/endpoints/meta.ts              |  2 +-
 src/server/api/mastodon/index.ts              |  2 +-
 15 files changed, 77 insertions(+), 33 deletions(-)

diff --git a/.config/example.yml b/.config/example.yml
index 2fd57094b6..072885af05 100644
--- a/.config/example.yml
+++ b/.config/example.yml
@@ -1,10 +1,3 @@
-maintainer:
-  name: example-maitainer-name # Your name
-  url: http://example.com/ # Your contact (http or mailto)
-  repository_url: https://github.com/syuilo/misskey # Repository URL
-  feedback_url: https://github.com/syuilo/misskey/issues # Feedback URL (e.g. github issue)
-
-
 # Final accessible URL seen by a user.
 url: https://example.tld/
 
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 2d0cf60bc6..b94fea1dad 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1079,6 +1079,9 @@ admin/views/instance.vue:
   instance-name: "インスタンス名"
   instance-description: "インスタンスの紹介"
   banner-url: "バナー画像URL"
+  maintainer-config: "管理者情報"
+  maintainer-name: "管理者名"
+  maintainer-email: "管理者の連絡先"
   drive-config: "ドライブの設定"
   cache-remote-files: "リモートのファイルをキャッシュする"
   cache-remote-files-desc: "この設定を無効にすると、リモートファイルをキャッシュせず直リンクするようになります。そのためサーバーのストレージを節約できますが、プライバシー設定で直リンクを無効にしているユーザーにはファイルが見えなくなったり、サムネイルが生成されないので通信量が増加します。通常はこの設定をオンにしておくことをおすすめします。"
diff --git a/src/client/app/admin/views/instance.vue b/src/client/app/admin/views/instance.vue
index 5acb493332..c92326aa07 100644
--- a/src/client/app/admin/views/instance.vue
+++ b/src/client/app/admin/views/instance.vue
@@ -7,6 +7,11 @@
 			<ui-textarea v-model="description">%i18n:@instance-description%</ui-textarea>
 			<ui-input v-model="bannerUrl"><i slot="icon"><fa icon="link"/></i>%i18n:@banner-url%</ui-input>
 		</section>
+		<section class="fit-bottom">
+			<header><fa icon="headset"/> %i18n:@maintainer-config%</header>
+			<ui-input v-model="maintainerName">%i18n:@maintainer-name%</ui-input>
+			<ui-input v-model="maintainerEmail">%i18n:@maintainer-email%</ui-input>
+		</section>
 		<section class="fit-top fit-bottom">
 			<ui-input v-model="maxNoteTextLength">%i18n:@max-note-text-length%</ui-input>
 		</section>
@@ -56,6 +61,8 @@ import Vue from "vue";
 export default Vue.extend({
 	data() {
 		return {
+			maintainerName: null,
+			maintainerEmail: null,
 			disableRegistration: false,
 			disableLocalTimeline: false,
 			bannerUrl: null,
@@ -75,6 +82,8 @@ export default Vue.extend({
 
 	created() {
 		(this as any).os.getMeta().then(meta => {
+			this.maintainerName = meta.maintainer.name;
+			this.maintainerEmail = meta.maintainer.email;
 			this.bannerUrl = meta.bannerUrl;
 			this.name = meta.name;
 			this.description = meta.description;
@@ -103,6 +112,8 @@ export default Vue.extend({
 
 		updateMeta() {
 			(this as any).api('admin/update-meta', {
+				maintainerName: this.maintainerName,
+				maintainerEmail: this.maintainerEmail,
 				disableRegistration: this.disableRegistration,
 				disableLocalTimeline: this.disableLocalTimeline,
 				bannerUrl: this.bannerUrl,
diff --git a/src/client/app/common/views/components/signup.vue b/src/client/app/common/views/components/signup.vue
index 91a09e14fb..d743202c27 100644
--- a/src/client/app/common/views/components/signup.vue
+++ b/src/client/app/common/views/components/signup.vue
@@ -4,7 +4,7 @@
 		<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required styl="fill">
 			<span>%i18n:@invitation-code%</span>
 			<span slot="prefix"><fa icon="id-card-alt"/></span>
-			<p slot="desc" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p>
+			<p slot="desc" v-html="'%i18n:@invitation-info%'.replace('{}', 'mailto:' + meta.maintainer.email)"></p>
 		</ui-input>
 		<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername" styl="fill">
 			<span>%i18n:@username%</span>
diff --git a/src/client/app/common/views/widgets/donation.vue b/src/client/app/common/views/widgets/donation.vue
index 4ef1557f97..3321b768e1 100644
--- a/src/client/app/common/views/widgets/donation.vue
+++ b/src/client/app/common/views/widgets/donation.vue
@@ -5,7 +5,7 @@
 			<h1><fa icon="heart"/>%i18n:@title%</h1>
 			<p v-if="meta">
 				{{ '%i18n:@text%'.substr(0, '%i18n:@text%'.indexOf('{')) }}
-				<a :href="meta.maintainer.url">{{ meta.maintainer.name }}</a>
+				<a :href="'mailto:' + meta.maintainer.email">{{ meta.maintainer.name }}</a>
 				{{ '%i18n:@text%'.substr('%i18n:@text%'.indexOf('}') + 1) }}
 			</p>
 		</article>
diff --git a/src/client/app/common/views/widgets/server.info.vue b/src/client/app/common/views/widgets/server.info.vue
index d243629506..3cb1748128 100644
--- a/src/client/app/common/views/widgets/server.info.vue
+++ b/src/client/app/common/views/widgets/server.info.vue
@@ -1,6 +1,6 @@
 <template>
 <div class="info">
-	<p>Maintainer: <b><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></b></p>
+	<p>Maintainer: <b><a :href="'mailto:' + meta.maintainer.email" target="_blank">{{ meta.maintainer.name }}</a></b></p>
 	<p>Machine: {{ meta.machine }}</p>
 	<p>Node: {{ meta.node }}</p>
 </div>
diff --git a/src/client/app/desktop/views/components/settings.vue b/src/client/app/desktop/views/components/settings.vue
index 6aa047d015..95965e245c 100644
--- a/src/client/app/desktop/views/components/settings.vue
+++ b/src/client/app/desktop/views/components/settings.vue
@@ -247,7 +247,7 @@
 		<ui-card class="other" v-show="page == 'other'">
 			<div slot="title"><fa icon="info-circle"/> %i18n:@about%</div>
 			<section>
-				<p v-if="meta">%i18n:@operator%: <i><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></i></p>
+				<p v-if="meta">%i18n:@operator%: <i><a :href="'mailto:' + meta.maintainer.email" target="_blank">{{ meta.maintainer.name }}</a></i></p>
 			</section>
 		</ui-card>
 
diff --git a/src/client/app/desktop/views/pages/welcome.vue b/src/client/app/desktop/views/pages/welcome.vue
index fbb20f4057..8825e518d7 100644
--- a/src/client/app/desktop/views/pages/welcome.vue
+++ b/src/client/app/desktop/views/pages/welcome.vue
@@ -87,7 +87,7 @@
 					<div>
 						<div v-if="meta" class="body">
 							<p>Version: <b>{{ meta.version }}</b></p>
-							<p>Maintainer: <b><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></b></p>
+							<p>Maintainer: <b><a :href="'mailto:' + meta.maintainer.email" target="_blank">{{ meta.maintainer.name }}</a></b></p>
 						</div>
 					</div>
 				</div>
diff --git a/src/client/app/mobile/views/pages/welcome.vue b/src/client/app/mobile/views/pages/welcome.vue
index 4babc47a7a..c235cac690 100644
--- a/src/client/app/mobile/views/pages/welcome.vue
+++ b/src/client/app/mobile/views/pages/welcome.vue
@@ -62,7 +62,7 @@
 		</article>
 		<div class="info" v-if="meta">
 			<p>Version: <b>{{ meta.version }}</b></p>
-			<p>Maintainer: <b><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></b></p>
+			<p>Maintainer: <b><a :href="'mailto:' + meta.maintainer.email" target="_blank">{{ meta.maintainer.name }}</a></b></p>
 		</div>
 		<footer>
 			<small>{{ copyright }}</small>
diff --git a/src/config/types.ts b/src/config/types.ts
index 1e44c4061e..fb7d652ef1 100644
--- a/src/config/types.ts
+++ b/src/config/types.ts
@@ -2,22 +2,8 @@
  * ユーザーが設定する必要のある情報
  */
 export type Source = {
-	/**
-	 * メンテナ情報
-	 */
-	maintainer: {
-		/**
-		 * メンテナの名前
-		 */
-		name: string;
-		/**
-		 * メンテナの連絡先(URLかmailto形式のURL)
-		 */
-		url: string;
-		email?: string;
-		repository_url?: string;
-		feedback_url?: string;
-	};
+	repository_url?: string;
+	feedback_url?: string;
 	languages?: string[];
 	url: string;
 	port: number;
diff --git a/src/models/meta.ts b/src/models/meta.ts
index 5d03d94181..8d3a917dfb 100644
--- a/src/models/meta.ts
+++ b/src/models/meta.ts
@@ -88,17 +88,46 @@ if ((config as any).ghost) {
 		}
 	});
 }
+if ((config as any).maintainer) {
+	Meta.findOne({}).then(m => {
+		if (m != null && m.maintainer == null) {
+			Meta.update({}, {
+				$set: {
+					maintainer: (config as any).maintainer
+				}
+			});
+		}
+	});
+}
 
 export type IMeta = {
 	name?: string;
 	description?: string;
+
+	/**
+	 * メンテナ情報
+	 */
+	maintainer: {
+		/**
+		 * メンテナの名前
+		 */
+		name: string;
+
+		/**
+		 * メンテナの連絡先
+		 */
+		email?: string;
+	};
+
 	broadcasts?: any[];
+
 	stats?: {
 		notesCount: number;
 		originalNotesCount: number;
 		usersCount: number;
 		originalUsersCount: number;
 	};
+
 	disableRegistration?: boolean;
 	disableLocalTimeline?: boolean;
 	hidedTags?: string[];
diff --git a/src/push-sw.ts b/src/push-sw.ts
index cfed5f03cd..d30965f800 100644
--- a/src/push-sw.ts
+++ b/src/push-sw.ts
@@ -6,7 +6,7 @@ import config from './config';
 if (config.sw) {
 	// アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録
 	push.setVapidDetails(
-		config.maintainer.url,
+		config.url,
 		config.sw.public_key,
 		config.sw.private_key);
 }
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index f541409274..bcfa420ed8 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -114,7 +114,21 @@ export const meta = {
 		proxyAccount: {
 			validator: $.str.optional.nullable,
 			desc: {
-				'ja-JP': 'Proxy account username'
+				'ja-JP': 'プロキシアカウントのユーザー名'
+			}
+		},
+
+		maintainerName: {
+			validator: $.str.optional,
+			desc: {
+				'ja-JP': 'インスタンスの管理者名'
+			}
+		},
+
+		maintainerEmail: {
+			validator: $.str.optional.nullable,
+			desc: {
+				'ja-JP': 'インスタンス管理者の連絡先メールアドレス'
 			}
 		}
 	}
@@ -183,6 +197,14 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
 		set.proxyAccount = ps.proxyAccount;
 	}
 
+	if (ps.maintainerName !== undefined) {
+		set['maintainer.name'] = ps.maintainerName;
+	}
+
+	if (ps.maintainerEmail !== undefined) {
+		set['maintainer.email'] = ps.maintainerEmail;
+	}
+
 	await Meta.update({}, {
 		$set: set
 	}, { upsert: true });
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index 03d2d9c6eb..ae07b944c2 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -36,7 +36,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 	});
 
 	const response: any = {
-		maintainer: config.maintainer,
+		maintainer: instance.maintainer,
 
 		version: pkg.version,
 		clientVersion: client.version,
diff --git a/src/server/api/mastodon/index.ts b/src/server/api/mastodon/index.ts
index 98e9c20be1..0e9203aa5a 100644
--- a/src/server/api/mastodon/index.ts
+++ b/src/server/api/mastodon/index.ts
@@ -48,7 +48,7 @@ router.get('/v1/instance', async ctx => { // TODO: This is a temporary implement
 		uri: config.hostname,
 		title: meta.name || 'Misskey',
 		description: meta.description || '',
-		email: config.maintainer.email || config.maintainer.url.startsWith('mailto:') ? config.maintainer.url.slice(7) : '',
+		email: meta.maintainer.email,
 		version: `0.0.0:compatible:misskey:${pkg.version}`, // TODO: How to tell about that this is an api for compatibility?
 		thumbnail: meta.bannerUrl,
 		/*