diff --git a/apps/server/src/middlewares/user-auth.ts b/apps/server/src/middlewares/user-auth.ts index 9ae7e2cc..317b2aa4 100644 --- a/apps/server/src/middlewares/user-auth.ts +++ b/apps/server/src/middlewares/user-auth.ts @@ -2,13 +2,13 @@ import type { Middleware } from 'koa'; import { users } from '../models'; export const middlewareAuthorizeUser: Middleware = async (ctx, next) => { - const userId = ctx.state.userId as number; + const userId = ctx.state.userId as number | undefined; const user = await users.get(userId); if (!user) { ctx.status = 401; ctx.body = { - errorCode: 'user_not_found' + errorCode: 'unauthorized' }; return; } diff --git a/apps/server/src/models/user.ts b/apps/server/src/models/user.ts index c108c831..a9ad32d4 100644 --- a/apps/server/src/models/user.ts +++ b/apps/server/src/models/user.ts @@ -48,6 +48,9 @@ export const Users = (prismaUser: PrismaClient['user']) => if (account) { account = account.toLowerCase(); } + if (!id && !account) { + return undefined; + } const user = await prismaUser.findUnique({ where: { diff --git a/apps/web/locales/en.json b/apps/web/locales/en.json index 51b71a52..2cc641d2 100644 --- a/apps/web/locales/en.json +++ b/apps/web/locales/en.json @@ -7,6 +7,7 @@ "navbar.logout": "Logout", "auth.toast.login": "Successfully logged in", "auth.toast.logout": "Successfully logged out", + "auth.toast.invalid-domain": "Invalid domain. The domain must be specified as \"example.com\" without any slashes.", "toast.api-error.title": "An error has occurred", "api-error.unauthorized": "Authentication failed: trying to re-login...", "api-error.invalid_request": "Internal error: Invalid request. Please contact the administrator for more information.", diff --git a/apps/web/locales/ja.json b/apps/web/locales/ja.json index 39c39f2a..a000f52d 100644 --- a/apps/web/locales/ja.json +++ b/apps/web/locales/ja.json @@ -7,6 +7,7 @@ "navbar.logout": "ログアウト", "auth.toast.login": "ログインしました", "auth.toast.logout": "ログアウトしました", + "auth.toast.invalid-domain": "無効なドメインです。ドメインは「example.com」のように、スラッシュなどは含めずに指定してください。", "toast.api-error.title": "エラーが発生しました", "api-error.unauthorized": "認証に失敗しました: 再ログインしています...", "api-error.invalid_request": "内部エラー: 不正なリクエストです。詳しくは管理者にお問い合わせください", diff --git a/apps/web/organisms/navbar/login-modal.tsx b/apps/web/organisms/navbar/login-modal.tsx index 369ef082..9db11250 100644 --- a/apps/web/organisms/navbar/login-modal.tsx +++ b/apps/web/organisms/navbar/login-modal.tsx @@ -16,8 +16,10 @@ import { Link, useDisclosure, Spinner, - Collapse + Collapse, + useToast } from '@chakra-ui/react'; +import isValidDomain from 'is-valid-domain'; import { ExternalLinkIcon } from '@chakra-ui/icons'; import { FormattedMessage, useIntl } from 'react-intl'; import { getDocsUrl } from '~/utils/constants'; @@ -48,6 +50,7 @@ const placeholderDomain: Record = { export const LoginModal: FC = ({ isOpen, onClose }) => { const { signIn } = useAuth(); const intl = useIntl(); + const toast = useToast(); const { isOpen: isOpeningSignIn, onOpen: onOpenSignIn, @@ -66,6 +69,14 @@ export const LoginModal: FC = ({ isOpen, onClose }) => { setHasNotDomain(true); return; } + if (!isValidDomain(domain)) { + toast({ + title: intl.formatMessage({ id: 'auth.toast.invalid-domain' }), + status: 'error', + isClosable: true + }); + return; + } onOpenSignIn(); if (serverType === ServerType.Mastodon) { @@ -75,7 +86,7 @@ export const LoginModal: FC = ({ isOpen, onClose }) => { } onClose(); })(); - }, [onOpenSignIn, onClose, signIn, domain, serverType]); + }, [signIn, domain, onOpenSignIn, serverType, onClose, toast, intl]); useEffect(() => { if (!isOpen) { @@ -103,6 +114,12 @@ export const LoginModal: FC = ({ isOpen, onClose }) => { } }, [domain]); + useEffect(() => { + setServerType(undefined); + setDomain(''); + setHasNotDomain(false); + }, [isOpen]); + return (