前回は、Prisma を使って、PostgresSQL データを追加や削除、更新しました。

【GraphQL】Prismaを使って、PostgresSQLデータを追加・削除・更新をする
今回は、ユーザー登録します。
コードは、前回のコードを使用します。
ユーザーデータを PostgresSQL に登録する
まずは、User のモデルを作成します。
prisma フォルダの schema.prisma を開きます。
Book と同様に、User モデルを作成します。
内容は、ID、E-mail、パスワード、作成日、更新日を指定します。
また、E-mail はユーザー間で重複することがないので、uniqueを設定します。
model User {
id Int @id @default(autoincrement())
email String @unique
password String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
モデルが完成したので、ターミナルで、npx prisma db pushを実行します。
モデルをプッシュすることができたら、npx prisma studioで確認します。
『+』ボタンをクリックして、User を追加します。


User の空データが追加されました。
次に、スキーマを作成します。
schema.ts でUserスキーマを作成します。
ts
type User {
id: Int!
email: String!
password: String!
}
ユーザー登録のための Mutation を作成します。
signupを作成し、emailとpasswordを指定します。
型は、Userとします。
ts
type Mutation {
addBook(input: AddBookInput!): BookPayload!
deleteBook(id: Int!): BookPayload!
updateBook(id: Int!, input: UpdateBookInput!): BookPayload!
signup(email: String!, password: String!): User
}
スキーマが完成したので、リゾルバーを作成します。
resolvers フォルダの Mutation.ts を開きます。
signup を作成します。
args には email と password、context には prisma を指定します。
ts
signup: async (_, { email, password }, { prisma }) => {};
User の型を作成します。
ts
type MutationUser = {
email: string;
password: string;
};
ts
signup: async (
_: any,
{ email, password }: MutationUser,
{ prisma }: Context
) => {};
prisma のcreateで、emailとpasswordのデータを追加するように設定します。
ts
signup: async (
_: any,
{ email, password }: MutationUser,
{ prisma }: Context
) => {
return prisma.user.create({
data: {
email,
password,
},
});
};
リゾルバーが完成したので、ブラウザでユーザーを登録してみましょう。
graphql
mutation Signup($email: String!, $password: String!) {
signup(email: $email, password: $password) {
email
password
}
}

Variables に email と password を入力します。
Signup をクリックすると、

データが送信できました。
Prisma Studio で確認しましょう。

email と password が追加されました。
E-mail とパスワードを検証する
データを追加することができましたが、email と password は、どんな文字列でも追加できてしまいます。
email は E-mail の内容になっているか、パスワードは何文字以上かを検証するために、validator というライブラリを使用します。
ターミナルで、npm install --save validator @types/validatorを実行します。
次に、エラーメッセージのスキーマを作成します。
schema.ts にAuthPayloadを作成します。
ts
type AuthPayload {
errors: [Error!]!
user: User
}
Mutationのsignupの型をUserからAuthPayloadへ変更します。
ts
type Mutation {
addBook(input: AddBookInput!): BookPayload!
deleteBook(id: Int!): BookPayload!
updateBook(id: Int!, input: UpdateBookInput!): BookPayload!
signup(email: String!, password: String!): AuthPayload
}
スキーマが完成したので、リゾルバーを修正します。
resolvers の Mutation.ts を開きます。
validator をインポートします。
ts
import validator from "validator";
Signup の型を作成しておきます。
ts
type UserPayload = {
errors: {
message: string;
}[];
user: User | null;
};
validator のisEmailを使って、emailが E-mail として正しいかどうか検証します。
isEmailが正しくない場合、エラーメッセージを返すようにしましょう。
ts
signup: async (
_: any,
{ email, password }: MutationUser,
{ prisma }: Context
): Promise<UserPayload> => {
const isEmail = validator.isEmail(email);
if (!isEmail) {
return {
errors: [
{
message: "emailが正しくありません",
},
],
user: null,
};
}
return prisma.user.create({
data: {
email,
password,
},
});
};
何文字以上のパスワードを有効にするかは、validator のisLengthを使用します。
今回は、4 文字以上を有効にします。
また、isPasswordが正しくない場合、エラーメッセージを返すようにしましょう。
ts
signup: async (
_: any,
{ email, password }: MutationUser,
{ prisma }: Context
): Promise<UserPayload> => {
const isEmail = validator.isEmail(email);
if (!isEmail) {
return {
errors: [
{
message: "emailが正しくありません",
},
],
user: null,
};
}
const isPassword = validator.isLength(password, {
min: 4,
});
if (!isPassword) {
return {
errors: [
{
message: "4文字上のパスワードを入力してください",
},
],
user: null,
};
}
return prisma.user.create({
data: {
email,
password,
},
});
};
エラーメッセージを返すように修正します。
ts
signup: async (
_: any,
{ email, password }: MutationUser,
{ prisma }: Context
): Promise<UserPayload> => {
const isEmail = validator.isEmail(email);
if (!isEmail) {
return {
errors: [
{
message: "emailが正しくありません",
},
],
user: null,
};
}
const isPassword = validator.isLength(password, {
min: 4,
});
if (!isPassword) {
return {
errors: [
{
message: "4文字上のパスワードを入力してください",
},
],
user: null,
};
}
const newUser = await prisma.user.create({
data: {
email,
password,
},
});
return {
errors: [],
user: newUser,
};
};
リゾルバーが完成したので、ブラウザで確認しましょう。
graphql
mutation Signup($email: String!, $password: String!) {
signup(email: $email, password: $password) {
errors {
message
}
user {
email
password
}
}
}
試しに、適当な email にしてみます。

Signup ボタンをクリックすると、

エラーメッセージが返ってきました。
次に、パスワードを 1 文字にしてみます。

Signup ボタンをクリックすると、

こちらもエラーメッセージが返ってきました。
正しい email と password では、

正常に登録できました。
Prisma Studio で確認すると、

正しいデータのみ PostgresSQL に追加することができました。
コードの全文は、以下の通りです。
次回は、パスワードをハッシュ化します。

【GraphQL】パスワードをハッシュ化する