Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 로그인 미들웨어, 로그아웃 #1

Merged
merged 5 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/crgpt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ jobs:
fetch-depth: 0

- name: Code Review GPT
uses: mattzcarey/[email protected].5
uses: mattzcarey/[email protected].8
with:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
MODEL: 'gpt-3.5-turbo'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MODEL: 'gpt-4o'
GITHUB_TOKEN: ${{ github.token }}
23 changes: 23 additions & 0 deletions prisma/migrations/20240526080214_add_provider/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
Warnings:

- Added the required column `provider` to the `AuthToken` table without a default value. This is not possible if the table is not empty.

*/
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_AuthToken" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"token" TEXT NOT NULL,
"user_id" INTEGER NOT NULL,
"provider" TEXT NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DATETIME NOT NULL,
CONSTRAINT "AuthToken_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_AuthToken" ("created_at", "id", "token", "updated_at", "user_id") SELECT "created_at", "id", "token", "updated_at", "user_id" FROM "AuthToken";
DROP TABLE "AuthToken";
ALTER TABLE "new_AuthToken" RENAME TO "AuthToken";
CREATE UNIQUE INDEX "AuthToken_token_key" ON "AuthToken"("token");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_User" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"username" TEXT,
"email" TEXT,
"password" TEXT,
"phone" TEXT,
"avatar" TEXT,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DATETIME NOT NULL
);
INSERT INTO "new_User" ("avatar", "created_at", "email", "id", "password", "phone", "updated_at", "username") SELECT "avatar", "created_at", "email", "id", "password", "phone", "updated_at", "username" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
CREATE UNIQUE INDEX "User_phone_key" ON "User"("phone");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
3 changes: 2 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ datasource db {

model User{
id Int @id @default(autoincrement())
username String @unique
username String? @unique
email String? @unique
password String?
phone String? @unique
Expand All @@ -32,6 +32,7 @@ model AuthToken{
token String @unique
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
user_id Int
provider String
created_at DateTime @default(now())
updated_at DateTime @updatedAt
}
21 changes: 20 additions & 1 deletion src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
"use client";

import { Button } from "@material-tailwind/react";
import React from "react";
import { signOut } from "next-auth/react";

export default function Home() {
return <div>home</div>;
return (
<div className="py-10 flex flex-col items-center h-svh justify-evenly">
<h1>HOME</h1>
<Button
onClick={() =>
signOut({
redirect: true,
callbackUrl: "/sign-in",
})
}
size="lg"
color="white"
className="w-80 flex justify-center hover:opacity-80 transition mt-4"
>
로그아웃
</Button>
</div>
);
}
8 changes: 5 additions & 3 deletions src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import GoogleProvider from "next-auth/providers/google";
import KakaoProvider from "next-auth/providers/kakao";
import NextAuth from "next-auth";
import { createUser } from "@/app/sign-in/actions";
import getSession from "@/utils/session";

const handler = NextAuth({
Expand All @@ -11,11 +12,12 @@ const handler = NextAuth({
},
},
callbacks: {
async signIn() {
async signIn({ user, account }) {
const cookie = await getSession();
// TODO db에 token 저장
// cookie.token = token;

cookie.id = user.id;
await cookie.save();
await createUser({ provider: account?.provider ?? "" });
return true;
},
},
Expand Down
27 changes: 19 additions & 8 deletions src/app/sign-in/actions.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
"use server";

import db from "@/db";
import getSession from "@/utils/session";

export async function createUser({ provider }: { provider: string }) {
const cookie = await getSession();

export async function checkSignInToken(token: string) {
const user = await db.user.findUnique({
const user = await db.authToken.findUnique({
where: {
username: "test",
// AuthToken: {
// some: {
// token,
// },
// },
token: cookie.id,
},
select: {
id: true,
},
});
/// 유저가 존재하면 리턴
if (user) return;

/// 없으면 유저 생성
await db.authToken.create({
data: {
token: cookie.id,
provider,
user: {},
},
});
}
12 changes: 8 additions & 4 deletions src/app/sign-in/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React, { useState } from "react";
"use client";

import { Button } from "@material-tailwind/react";
import { LoginProvider } from "@/utils/type";
import { signIn } from "next-auth/react";
import { useState } from "react";

export default function SignIn() {
const [loading, setLoading] = useState(false);
const handleLogin = async (loginProvider: "kakao" | "google") => {
const [provider, setProvider] = useState<LoginProvider | null>(null);
const handleLogin = async (loginProvider: LoginProvider) => {
setProvider(loginProvider);
try {
setLoading(true);
await signIn(loginProvider, {
Expand All @@ -25,15 +29,15 @@ export default function SignIn() {
<div className="flex flex-col">
<Button
onClick={() => handleLogin("kakao")}
loading={loading}
loading={loading && provider === "kakao"}
size="lg"
className="w-80 flex justify-center bg-[#FAE54D] text-black hover:opacity-80 transition"
>
카카오 로그인
</Button>
<Button
onClick={() => handleLogin("google")}
loading={loading}
loading={loading && provider === "google"}
size="lg"
color="white"
className="w-80 flex justify-center hover:opacity-80 transition mt-4"
Expand Down
14 changes: 14 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { NextRequest } from "next/server";
import getSession from "./utils/session";

export async function middleware(request: NextRequest) {
const cookie = await getSession();

if (request.nextUrl.pathname === "/" && cookie.id === undefined) {
return Response.redirect(new URL("/sign-in", request.url));
}

if (request.nextUrl.pathname === "/sign-in" && cookie.id !== undefined) {
return Response.redirect(new URL("/", request.url));
}
}
2 changes: 1 addition & 1 deletion src/utils/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { cookies } from "next/headers";
import { getIronSession } from "iron-session";

export interface SessionContent {
token: string;
id: string;
}

export default async function getSession() {
Expand Down
3 changes: 3 additions & 0 deletions src/utils/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type LoginProvider = "kakao" | "google";

export type { LoginProvider };
Loading