mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-25 07:32:19 -05:00
Show dialog for failed login attempts
This commit is contained in:
parent
cf704c3ec4
commit
ab98a106bb
|
|
@ -1,9 +1,10 @@
|
|||
import { Link } from "@remix-run/react";
|
||||
import { Link, useSearchParams } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useUser } from "~/modules/auth";
|
||||
import { LOG_IN_URL, LOG_OUT_URL, userPage } from "~/utils/urls";
|
||||
import { Avatar } from "../Avatar";
|
||||
import { Button } from "../Button";
|
||||
import { Dialog } from "../Dialog";
|
||||
import { DiscordIcon } from "../icons/Discord";
|
||||
import { LogOutIcon } from "../icons/LogOut";
|
||||
import { UserIcon } from "../icons/User";
|
||||
|
|
@ -12,8 +13,9 @@ import { Popover } from "../Popover";
|
|||
export function UserItem() {
|
||||
const { t } = useTranslation();
|
||||
const user = useUser();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
if (user)
|
||||
if (user) {
|
||||
return (
|
||||
<Popover
|
||||
buttonChildren={
|
||||
|
|
@ -45,16 +47,56 @@ export function UserItem() {
|
|||
</div>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
const authError = searchParams.get("authError");
|
||||
const closeAuthErrorDialog = () => {
|
||||
const newSearchParams = new URLSearchParams(searchParams);
|
||||
newSearchParams.delete("authError");
|
||||
setSearchParams(newSearchParams);
|
||||
};
|
||||
|
||||
return (
|
||||
<form action={LOG_IN_URL} method="post" data-cy="log-in-form">
|
||||
<button
|
||||
type="submit"
|
||||
className="layout__log-in-button"
|
||||
data-cy="log-in-button"
|
||||
>
|
||||
<DiscordIcon /> {t("header.login")}
|
||||
</button>
|
||||
</form>
|
||||
<>
|
||||
<form action={LOG_IN_URL} method="post" data-cy="log-in-form">
|
||||
<button
|
||||
type="submit"
|
||||
className="layout__log-in-button"
|
||||
data-cy="log-in-button"
|
||||
>
|
||||
<DiscordIcon /> {t("header.login")}
|
||||
</button>
|
||||
</form>
|
||||
{authError != null && (
|
||||
<Dialog isOpen close={closeAuthErrorDialog}>
|
||||
<div className="stack md">
|
||||
<AuthenticationErrorHelp errorCode={authError} />
|
||||
<Button onClick={closeAuthErrorDialog}>{t("actions.close")}</Button>
|
||||
</div>
|
||||
</Dialog>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AuthenticationErrorHelp({ errorCode }: { errorCode: string }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
switch (errorCode) {
|
||||
case "aborted":
|
||||
return (
|
||||
<>
|
||||
<h2 className="text-lg text-center">{t("auth.errors.aborted")}</h2>
|
||||
{t("auth.errors.discordPermissions")}
|
||||
</>
|
||||
);
|
||||
case "unknown":
|
||||
default:
|
||||
return (
|
||||
<>
|
||||
<h2 className="text-lg text-center">{t("auth.errors.failed")}</h2>
|
||||
{t("auth.errors.unknown")}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
app/modules/auth/errors.ts
Normal file
1
app/modules/auth/errors.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export type AuthErrorCode = "aborted" | "unknown";
|
||||
|
|
@ -9,3 +9,5 @@ export {
|
|||
export { getUser, requireUser } from "./user.server";
|
||||
|
||||
export { useUser } from "./user";
|
||||
|
||||
export { AuthErrorCode } from "./errors";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { ActionFunction, LoaderFunction } from "@remix-run/node";
|
||||
import { redirect } from "@remix-run/node";
|
||||
import { canPerformAdminActions } from "~/permissions";
|
||||
import { ADMIN_PAGE } from "~/utils/urls";
|
||||
import { ADMIN_PAGE, authErrorUrl } from "~/utils/urls";
|
||||
import {
|
||||
authenticator,
|
||||
DISCORD_AUTH_KEY,
|
||||
|
|
@ -11,11 +11,19 @@ import { authSessionStorage } from "./session.server";
|
|||
import { getUser } from "./user.server";
|
||||
|
||||
export const callbackLoader: LoaderFunction = async ({ request }) => {
|
||||
const url = new URL(request.url);
|
||||
if (url.searchParams.get("error") === "access_denied") {
|
||||
// The user denied the authentication request
|
||||
// This is part of the oauth2 protocol, but remix-auth-oauth2 doesn't do
|
||||
// nice error handling for this case.
|
||||
// https://www.oauth.com/oauth2-servers/server-side-apps/possible-errors/
|
||||
|
||||
return redirect(authErrorUrl("aborted"));
|
||||
}
|
||||
|
||||
await authenticator.authenticate(DISCORD_AUTH_KEY, request, {
|
||||
successRedirect: "/",
|
||||
// TODO: should include query param that displays an error banner explaining that log in went wrong
|
||||
// and where to get help for that
|
||||
failureRedirect: "/",
|
||||
failureRedirect: authErrorUrl("unknown"),
|
||||
});
|
||||
|
||||
throw new Response("Unknown authentication state", { status: 500 });
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import type {
|
|||
SubWeaponId,
|
||||
} from "~/modules/in-game-lists/types";
|
||||
import type navItems from "~/components/layout/nav-items.json";
|
||||
import { type AuthErrorCode } from "~/modules/auth";
|
||||
|
||||
export const SPLATOON_2_SENDOU_IN_URL = "https://spl2.sendou.ink";
|
||||
export const PLUS_SERVER_DISCORD_URL = "https://discord.gg/FW4dKrY";
|
||||
|
|
@ -59,6 +60,8 @@ export const userResultsEditHighlightsPage = (user: UserLinkArgs) =>
|
|||
export const userNewBuildPage = (user: UserLinkArgs) =>
|
||||
`${userBuildsPage(user)}/new`;
|
||||
|
||||
export const authErrorUrl = (errorCode: AuthErrorCode) =>
|
||||
`/?authError=${errorCode}`;
|
||||
export const impersonateUrl = (idToLogInAs: number) =>
|
||||
`/auth/impersonate?id=${idToLogInAs}`;
|
||||
export const badgePage = (badgeId: number) => `${BADGES_PAGE}/${badgeId}`;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
"actions.remove": "Entfernen",
|
||||
"actions.delete": "Löschen",
|
||||
"actions.loadMore": "Mehr laden",
|
||||
"actions.close": "Schließen",
|
||||
|
||||
"results": "Ergebnisse",
|
||||
|
||||
|
|
@ -54,5 +55,10 @@
|
|||
"weapon.category.DUALIES": "Doppler",
|
||||
"weapon.category.BRELLAS": "Pluviatoren",
|
||||
"weapon.category.STRINGERS": "Stringer",
|
||||
"weapon.category.SPLATANAS": "Splatanas"
|
||||
"weapon.category.SPLATANAS": "Splatanas",
|
||||
|
||||
"auth.errors.aborted": "Login Abgebrochen",
|
||||
"auth.errors.failed": "Login Fehlgeschlagen",
|
||||
"auth.errors.discordPermissions": "Für dein sendou.ink Profil braucht die Seite die Erlaubnis deinen Discord-Namen, Avatar, und verbundene Social Accounts auszulesen.",
|
||||
"auth.errors.unknown": "Der Login via Discord ist aus unbekannten Gründen fehlgeschlagen. Falls dies wiederholt auftritt, kontaktiere uns bitte."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@
|
|||
"header.logout": "Log out",
|
||||
"header.login": "Log in",
|
||||
|
||||
"auth.errors.aborted": "Login Aborted",
|
||||
"auth.errors.failed": "Login Failed",
|
||||
"auth.errors.discordPermissions": "For your sendou.ink profile, the site needs access to your Discord profile's name, avatar and social connections.",
|
||||
"auth.errors.unknown": "The login via Discord failed for an unknown reason. If this keeps happening, please reach out for help.",
|
||||
|
||||
"footer.github.subtitle": "Source code",
|
||||
"footer.twitter.subtitle": "Updates",
|
||||
"footer.discord.subtitle": "Help & feedback",
|
||||
|
|
@ -29,6 +34,7 @@
|
|||
"actions.delete": "Delete",
|
||||
"actions.loadMore": "Load more",
|
||||
"actions.copyToClipboard": "Copy to clipboard",
|
||||
"actions.close": "Close",
|
||||
|
||||
"maps.createMapList": "Create map list",
|
||||
"maps.halfSz": "50% SZ",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,68 @@
|
|||
# Translation Progress
|
||||
|
||||
## /da (🟢 Done)
|
||||
## /da (🟡 In progress)
|
||||
|
||||
### 🟢 analyzer.json
|
||||
|
||||
**94/94**
|
||||
|
||||
### 🟢 badges.json
|
||||
|
||||
**7/7**
|
||||
|
||||
### 🟢 builds.json
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 calendar.json
|
||||
|
||||
**46/46**
|
||||
|
||||
### 🟡 common.json
|
||||
|
||||
**55/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.close
|
||||
|
||||
</details>
|
||||
|
||||
### 🟢 contributions.json
|
||||
|
||||
**6/6**
|
||||
|
||||
### 🟢 faq.json
|
||||
|
||||
**6/6**
|
||||
|
||||
### 🟢 front.json
|
||||
|
||||
**11/11**
|
||||
|
||||
### 🟢 game-misc.json
|
||||
|
||||
**17/17**
|
||||
|
||||
### 🟡 user.json
|
||||
|
||||
**20/25**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- results.title
|
||||
- results.highlights
|
||||
- results.nonHighlights
|
||||
- results.highlights.choose
|
||||
- results.highlights.explanation
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -32,7 +94,7 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**49/55**
|
||||
**54/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
|
@ -123,14 +185,19 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**48/55**
|
||||
**48/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.s2
|
||||
- pages.maps
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.copyToClipboard
|
||||
- actions.close
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
|
|
@ -239,7 +306,7 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**46/55**
|
||||
**46/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
|
@ -247,8 +314,13 @@
|
|||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- actions.close
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
|
|
@ -350,7 +422,7 @@
|
|||
|
||||
### 🔴 common.json
|
||||
|
||||
**0/55**
|
||||
**0/60**
|
||||
|
||||
### 🔴 contributions.json
|
||||
|
||||
|
|
@ -501,7 +573,7 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**46/55**
|
||||
**46/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
|
@ -509,8 +581,13 @@
|
|||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- actions.close
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
|
|
@ -619,7 +696,7 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**35/55**
|
||||
**35/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
|
@ -627,8 +704,13 @@
|
|||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- actions.close
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
|
|
@ -748,14 +830,19 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**48/55**
|
||||
**48/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.copyToClipboard
|
||||
- actions.close
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
|
|
@ -843,7 +930,7 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**35/55**
|
||||
**35/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
|
@ -851,8 +938,13 @@
|
|||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- actions.close
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
|
|
@ -972,7 +1064,7 @@
|
|||
|
||||
### 🟡 common.json
|
||||
|
||||
**35/55**
|
||||
**35/60**
|
||||
|
||||
<details>
|
||||
<summary>Missing</summary>
|
||||
|
|
@ -980,8 +1072,13 @@
|
|||
- pages.s2
|
||||
- pages.analyzer
|
||||
- pages.maps
|
||||
- auth.errors.aborted
|
||||
- auth.errors.failed
|
||||
- auth.errors.discordPermissions
|
||||
- auth.errors.unknown
|
||||
- actions.loadMore
|
||||
- actions.copyToClipboard
|
||||
- actions.close
|
||||
- maps.createMapList
|
||||
- maps.halfSz
|
||||
- maps.mapPool
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user