🗝️

The Password Gameのパクリをつくる

2023/08/06に公開

The Password Gameとは

多種多様なパスワード要件を全て満たし正しいパスワードを作るゲームです。
セキュリティ芸人のYoutuberの方(脆弱エンジニアの日常)が取り上げていて、面白いと思ったのでパクりました。
https://neal.fun/password-game/
https://www.youtube.com/watch?v=0SGca2EVdII

使用技術

  • Next.js v13.4.12
  • TypeScript v5.1.6
  • Chakra UI v2.8.0

実際にやってみる

1.フォームの作成

ChakraUIにはInputというコンポーネントが用意されてるのでこれを使います。

page.tsx
"use client";

import {
    Box,
    FormControl,
    FormLabel,
    Heading,
    Input,
    Spacer,
    VStack,
} from "@chakra-ui/react";
import { useState } from "react";

const Home = () => {
    const [password, setPassword] = useState<string>("");

    return (
        <VStack>
            <VStack spacing={10} w="30vw">
                <Spacer />
                <Heading>The Password Game</Heading>
                <FormControl>
                    <FormLabel>Password</FormLabel>
                    <Input
                        id="password"
                        placeholder="password"
                        value={password}
                        borderColor="black"
                        onChange={(e) => setPassword(e.target.value)}
                    />
                </FormControl>
            </VStack>
        </VStack>
    );
};

export default Home;

useState()によってフォームに入力されるたびにpasswordを更新しています。

2.エラーメッセージを追加してみる

ChakraUIには<FormErrorMessage>というコンポーネントも用意されています。これは<FormContorl>のpropsであるisInvalidに条件式を代入することで、条件式がtrueの場合表示させることができるものです。試しにパスワードが空(Empty)であるかを判定します。

エラーメッセージを表示させることができました。

3.複数のエラーを追加する

条件式とエラーメッセージに対応するinterfaceを作成します。
errorには「errorになる場合」の条件を書きます。
(idはkeyに当てるために使います)

interface PasswordValidator {
    error: boolean;
    message: string;
    id: number;
}
  • 8文字以上である
  • 大文字を含む
    の2つの条件を格納するPasswordValidatorを定義します。
    (先程のisPasswordEmptyも書き直します)
const isPasswordEmpty: PasswordValidator = {
    error: password === "",
    message: "パスワードを入力してください",
    id: 0,
};
const hasPasswordEnoughCharacters: PasswordValidator = {
    error: password.length < 8,
    message: "パスワードは8文字以上である必要があります。",
    id: 1,
};
const hasPasswordUppercase: PasswordValidator = {
    error: /\[A-Z]/g.test(password),
    message: "パスワードは大文字を含む必要があります",
    id: 2,
};
const AllValidator = [
    isPasswordEmpty,
    hasPasswordEnoughCharacters,
    hasPasswordUppercase,
];

hasPasswordUppercaseでは正規表現を使って大文字判定をしています。
次に、isInvalidに「AllValidatorのうち1つでもtrueならtrueを返す」式を入れます。

<FormControl isInvalid={AllValidator.some((e) => e.error)}>

JavaScriptのArray.prototype.some()では全ての要素に対してフィルタリングを行い、一つでもtrueであった場合trueが返されます。これで1つでもエラーが起きた場合エラーメッセージが表示されます。

4.対応するエラーメッセージを追加する

<FormErrorMessage>
	{isPasswordEmpty.message}
</FormErrorMessage>           
<FormErrorMessage>
	{hasPasswordEnoughCharacters.message}
</FormErrorMessage>
<FormErrorMessage>
	{hasPasswordUppercase.message}
</FormErrorMessage>

先程のようにFormErrorMessageを追加してみます。
おや...?

大文字を入力したのにエラ〜メッセージが消えていません。
当たり前です。他のエラー(この場合hasPasswordEnoughCharacters)がtrueなのでそれに釣られてこのエラーメッセージも表示されてしまいます。なのでif文を使って対応するエラーに応じて表示/非表示を切り替えられるようにします。

{AllValidator.map((validate) => {
    if (validate.error) {
        return (
            <FormErrorMessage>
                {validate.message}
            </FormErrorMessage>
        );
    }
})}


存在するエラーメッセージのみ表示されるようになりました。あとはPasswordValidatorを好きなだけ増やせば自分だけのThe Password Gameが作れます。
ということで条件を増やしまくりました。

Vercelにデプロイしたので遊んでみてください。ボタンは飾りです。
https://www.nyaruko.xyz/

Discussion