From eb443709bfcda81c329b51f95bf02cef85932456 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Wed, 28 Mar 2018 13:05:30 +0900 Subject: [PATCH] #1294 --- locales/ja.yml | 2 +- src/api/bot/core.ts | 2 +- .../app/common/views/components/signin.vue | 2 +- .../app/common/views/components/signup.vue | 2 +- .../common/views/directives/autocomplete.ts | 2 +- src/web/app/dev/views/new-app.vue | 4 +- src/web/app/mobile/views/pages/welcome.vue | 2 +- tools/migration/node.2018-03-28.appname.js | 40 +++++++++++++++++++ tools/migration/node.2018-03-28.username.js | 40 +++++++++++++++++++ 9 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 tools/migration/node.2018-03-28.appname.js create mode 100644 tools/migration/node.2018-03-28.username.js diff --git a/locales/ja.yml b/locales/ja.yml index f826b1b6ca..fd140ecc30 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -147,7 +147,7 @@ common: available: "利用できます" unavailable: "既に利用されています" error: "通信エラー" - invalid-format: "a~z、A~Z、0~9、-(ハイフン)が使えます" + invalid-format: "a~z、A~Z、0~9、_が使えます" too-short: "3文字以上でお願いします!" too-long: "20文字以内でお願いします" password: "パスワード" diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts index 77a68aaee6..d6706e9a1c 100644 --- a/src/api/bot/core.ts +++ b/src/api/bot/core.ts @@ -67,7 +67,7 @@ export default class BotCore extends EventEmitter { return await this.context.q(query); } - if (/^@[a-zA-Z0-9-]+$/.test(query)) { + if (/^@[a-zA-Z0-9_]+$/.test(query)) { return await this.showUserCommand(query); } diff --git a/src/web/app/common/views/components/signin.vue b/src/web/app/common/views/components/signin.vue index 2434684085..273143262b 100644 --- a/src/web/app/common/views/components/signin.vue +++ b/src/web/app/common/views/components/signin.vue @@ -1,7 +1,7 @@ <template> <form class="mk-signin" :class="{ signing }" @submit.prevent="onSubmit"> <label class="user-name"> - <input v-model="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="%i18n:common.tags.mk-signin.username%" autofocus required @change="onUsernameChange"/>%fa:at% + <input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="%i18n:common.tags.mk-signin.username%" autofocus required @change="onUsernameChange"/>%fa:at% </label> <label class="password"> <input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signin.password%" required/>%fa:lock% diff --git a/src/web/app/common/views/components/signup.vue b/src/web/app/common/views/components/signup.vue index c2e78aa8a3..e77d849ade 100644 --- a/src/web/app/common/views/components/signup.vue +++ b/src/web/app/common/views/components/signup.vue @@ -2,7 +2,7 @@ <form class="mk-signup" @submit.prevent="onSubmit" autocomplete="off"> <label class="username"> <p class="caption">%fa:at%%i18n:common.tags.mk-signup.username%</p> - <input v-model="username" type="text" pattern="^[a-zA-Z0-9-]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/> + <input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{3,20}$" placeholder="a~z、A~Z、0~9、-" autocomplete="off" required @input="onChangeUsername"/> <p class="profile-page-url-preview" v-if="shouldShowProfileUrl">{{ `${url}/@${username}` }}</p> <p class="info" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%%i18n:common.tags.mk-signup.checking%</p> <p class="info" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw%%i18n:common.tags.mk-signup.available%</p> diff --git a/src/web/app/common/views/directives/autocomplete.ts b/src/web/app/common/views/directives/autocomplete.ts index 3440c4212a..94635d301a 100644 --- a/src/web/app/common/views/directives/autocomplete.ts +++ b/src/web/app/common/views/directives/autocomplete.ts @@ -77,7 +77,7 @@ class Autocomplete { if (mentionIndex != -1 && mentionIndex > emojiIndex) { const username = text.substr(mentionIndex + 1); - if (username != '' && username.match(/^[a-zA-Z0-9-]+$/)) { + if (username != '' && username.match(/^[a-zA-Z0-9_]+$/)) { this.open('user', username); opened = true; } diff --git a/src/web/app/dev/views/new-app.vue b/src/web/app/dev/views/new-app.vue index 344e8468f9..1a796299cb 100644 --- a/src/web/app/dev/views/new-app.vue +++ b/src/web/app/dev/views/new-app.vue @@ -6,12 +6,12 @@ <b-form-input v-model="name" type="text" placeholder="ex) Misskey for iOS" autocomplete="off" required/> </b-form-group> <b-form-group label="ID" description="あなたのアプリのID。"> - <b-input v-model="nid" type="text" pattern="^[a-zA-Z0-9-]{3,30}$" placeholder="ex) misskey-for-ios" autocomplete="off" required/> + <b-input v-model="nid" type="text" pattern="^[a-zA-Z0-9_]{3,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~z、A~Z、0~9、-(ハイフン)が使えます</p> + <p class="info" v-if="nidState == 'invalid-format'" style="color:#FF1161">%fa:fw exclamation-triangle%a~z、A~Z、0~9、_が使えます</p> <p class="info" v-if="nidState == 'min-range'" style="color:#FF1161">%fa:fw exclamation-triangle%3文字以上でお願いします!</p> <p class="info" v-if="nidState == 'max-range'" style="color:#FF1161">%fa:fw exclamation-triangle%30文字以内でお願いします</p> </b-form-group> diff --git a/src/web/app/mobile/views/pages/welcome.vue b/src/web/app/mobile/views/pages/welcome.vue index 3384ee6997..8557448346 100644 --- a/src/web/app/mobile/views/pages/welcome.vue +++ b/src/web/app/mobile/views/pages/welcome.vue @@ -6,7 +6,7 @@ <p>%fa:lock% ログイン</p> <div> <form @submit.prevent="onSubmit"> - <input v-model="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/> + <input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/> <input v-model="password" type="password" placeholder="パスワード" required/> <input v-if="user && user.account.two_factor_enabled" v-model="token" type="number" placeholder="トークン" required/> <button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</button> diff --git a/tools/migration/node.2018-03-28.appname.js b/tools/migration/node.2018-03-28.appname.js new file mode 100644 index 0000000000..9f16e47202 --- /dev/null +++ b/tools/migration/node.2018-03-28.appname.js @@ -0,0 +1,40 @@ +// for Node.js interpret + +const { default: App } = require('../../built/api/models/app'); +const { generate } = require('../../built/crypto_key'); +const { default: zip } = require('@prezzemolo/zip') + +const migrate = async (app) => { + const result = await User.update(app._id, { + $set: { + 'name_id': app.name_id.replace(/\-/g, '_'), + 'name_id_lower': app.name_id_lower.replace(/\-/g, '_') + } + }); + return result.ok === 1; +} + +async function main() { + const count = await App.count({}); + + const dop = Number.parseInt(process.argv[2]) || 5 + const idop = ((count - (count % dop)) / dop) + 1 + + return zip( + 1, + async (time) => { + console.log(`${time} / ${idop}`) + const doc = await App.find({}, { + limit: dop, skip: time * dop + }) + return Promise.all(doc.map(migrate)) + }, + idop + ).then(a => { + const rv = [] + a.forEach(e => rv.push(...e)) + return rv + }) +} + +main().then(console.dir).catch(console.error) diff --git a/tools/migration/node.2018-03-28.username.js b/tools/migration/node.2018-03-28.username.js new file mode 100644 index 0000000000..2222152101 --- /dev/null +++ b/tools/migration/node.2018-03-28.username.js @@ -0,0 +1,40 @@ +// for Node.js interpret + +const { default: User } = require('../../built/api/models/user'); +const { generate } = require('../../built/crypto_key'); +const { default: zip } = require('@prezzemolo/zip') + +const migrate = async (user) => { + const result = await User.update(user._id, { + $set: { + 'username': user.username.replace(/\-/g, '_'), + 'username_lower': user.username_lower.replace(/\-/g, '_') + } + }); + return result.ok === 1; +} + +async function main() { + const count = await User.count({}); + + const dop = Number.parseInt(process.argv[2]) || 5 + const idop = ((count - (count % dop)) / dop) + 1 + + return zip( + 1, + async (time) => { + console.log(`${time} / ${idop}`) + const doc = await User.find({}, { + limit: dop, skip: time * dop + }) + return Promise.all(doc.map(migrate)) + }, + idop + ).then(a => { + const rv = [] + a.forEach(e => rv.push(...e)) + return rv + }) +} + +main().then(console.dir).catch(console.error)