From de0996acef3126e68184efd633d2790f123c02a2 Mon Sep 17 00:00:00 2001 From: Phil Date: Fri, 16 Sep 2022 16:07:11 +0100 Subject: [PATCH] Added confirmation popup to refresh API key. Refreshing API key now requires a user to relink their Twitch account. --- common/user.ts | 1 + web/pages/profile.tsx | 51 ++++++++++++++++++++++++++++++++++++------- web/pages/twitch.tsx | 22 +++++++++++++------ 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/common/user.ts b/common/user.ts index b490ab0c..5ab07d35 100644 --- a/common/user.ts +++ b/common/user.ts @@ -71,6 +71,7 @@ export type PrivateUser = { twitchName: string controlToken: string botEnabled?: boolean + needsRelinking?: boolean } } diff --git a/web/pages/profile.tsx b/web/pages/profile.tsx index c038fd11..2c095db6 100644 --- a/web/pages/profile.tsx +++ b/web/pages/profile.tsx @@ -2,9 +2,11 @@ import { RefreshIcon } from '@heroicons/react/outline' import { PrivateUser, User } from 'common/user' import { cleanDisplayName, cleanUsername } from 'common/util/clean-username' import { formatMoney } from 'common/util/format' +import Link from 'next/link' import React, { useState } from 'react' import Textarea from 'react-expanding-textarea' import { AddFundsButton } from 'web/components/add-funds-button' +import { ConfirmationButton } from 'web/components/confirmation-button' import { Col } from 'web/components/layout/col' import { Row } from 'web/components/layout/row' import { Page } from 'web/components/page' @@ -16,7 +18,11 @@ import { generateNewApiKey } from 'web/lib/api/api-key' import { changeUserInfo } from 'web/lib/firebase/api' import { redirectIfLoggedOut } from 'web/lib/firebase/server-auth' import { uploadImage } from 'web/lib/firebase/storage' -import { getUserAndPrivateUser, updateUser } from 'web/lib/firebase/users' +import { + getUserAndPrivateUser, + updatePrivateUser, + updateUser, +} from 'web/lib/firebase/users' export const getServerSideProps = redirectIfLoggedOut('/', async (_, creds) => { return { props: { auth: await getUserAndPrivateUser(creds.uid) } } @@ -91,10 +97,15 @@ export default function ProfilePage(props: { } } - const updateApiKey = async (e: React.MouseEvent) => { + const updateApiKey = async (e?: React.MouseEvent) => { const newApiKey = await generateNewApiKey(user.id) setApiKey(newApiKey ?? '') - e.preventDefault() + e?.preventDefault() + + if (!privateUser.twitchInfo) return + await updatePrivateUser(privateUser.id, { + twitchInfo: { ...privateUser.twitchInfo, needsRelinking: true }, + }) } const fileHandler = async (event: any) => { @@ -227,12 +238,36 @@ export default function ProfilePage(props: { value={apiKey} readOnly /> - + + + <div> + Updating your API key will break any existing applications + connected to your account, <b>including the Twitch bot</b>. + You will need to go to the{' '} + <Link href="/twitch"> + <a className="underline focus:outline-none"> + Twitch page + </a> + </Link>{' '} + to relink your account. + </div> + </Col> + </ConfirmationButton> </div> </div> </Col> diff --git a/web/pages/twitch.tsx b/web/pages/twitch.tsx index 49b004fa..46856eaf 100644 --- a/web/pages/twitch.tsx +++ b/web/pages/twitch.tsx @@ -40,6 +40,9 @@ function ButtonGetStarted(props: { const { user, privateUser, buttonClass, spinnerClass } = props const [isLoading, setLoading] = useState(false) + const needsRelink = + privateUser?.twitchInfo?.twitchName && + privateUser?.twitchInfo?.needsRelinking const callback = user && privateUser @@ -77,11 +80,11 @@ function ButtonGetStarted(props: { ) : ( <Button size="xl" - color="gradient" + color={needsRelink ? 'red' : 'gradient'} className={clsx('my-4 self-center !px-16', buttonClass)} onClick={getStarted} > - Start playing + {needsRelink ? 'API key updated: relink Twitch' : 'Start playing'} </Button> ) } @@ -92,7 +95,8 @@ function TwitchPlaysManifoldMarkets(props: { }) { const { user, privateUser } = props - const twitchUser = privateUser?.twitchInfo?.twitchName + const twitchInfo = privateUser?.twitchInfo + const twitchUser = twitchInfo?.twitchName return ( <div> @@ -120,7 +124,7 @@ function TwitchPlaysManifoldMarkets(props: { receive their profit. </div> Start playing now by logging in with Google and typing commands in chat! - {twitchUser ? ( + {twitchUser && !twitchInfo.needsRelinking ? ( <Button size="xl" color="green" @@ -280,7 +284,7 @@ function BotConnectButton(props: { <Button color="red" onClick={updateBotConnected(false)} - className={clsx(loading && '!btn-disabled', '')} + className={clsx(loading && '!btn-disabled', 'border-none')} > {loading ? ( <LoadingIndicator spinnerClassName="!h-5 !w-5 border-white !border-2" /> @@ -292,7 +296,7 @@ function BotConnectButton(props: { <Button color="green" onClick={updateBotConnected(true)} - className={clsx(loading && '!btn-disabled', '')} + className={clsx(loading && '!btn-disabled', 'border-none')} > {loading ? ( <LoadingIndicator spinnerClassName="!h-5 !w-5 border-white !border-2" /> @@ -310,7 +314,11 @@ function SetUpBot(props: { privateUser?: PrivateUser | null }) { const { user, privateUser } = props - const twitchLinked = privateUser?.twitchInfo?.twitchName + const twitchLinked = + privateUser?.twitchInfo?.twitchName && + !privateUser?.twitchInfo?.needsRelinking + ? true + : undefined const toastTheme = { className: '!bg-primary !text-white', icon: <LinkIcon className="mr-2 h-6 w-6" aria-hidden="true" />,