feat: Add prisma
This commit is contained in:
parent
e12a923186
commit
fcca20d14f
@ -2,4 +2,6 @@ NEXT_PUBLIC_TEST="테스트변수입니다. development"
|
||||
|
||||
NEXT_PUBLIC_API_SERVER_PATH="http://localhost:8080"
|
||||
|
||||
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=sa;password=Qwertqaz!@#45;trustServerCertificate=true"
|
||||
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true"
|
||||
|
||||
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
||||
@ -2,4 +2,6 @@ NEXT_PUBLIC_TEST="테스트변수입니다. production"
|
||||
|
||||
NEXT_PUBLIC_API_SERVER_PATH="http://localhost:8080"
|
||||
|
||||
DATABASE_URL=""
|
||||
DATABASE_URL=""
|
||||
|
||||
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
||||
@ -15,6 +15,7 @@
|
||||
"axios": "^1.7.3",
|
||||
"fabric": "^5.3.0",
|
||||
"framer-motion": "^11.2.13",
|
||||
"iron-session": "^8.0.2",
|
||||
"mathjs": "^13.0.2",
|
||||
"mssql": "^11.0.1",
|
||||
"next": "14.2.3",
|
||||
|
||||
@ -1,91 +1,9 @@
|
||||
export default function page() {
|
||||
import Login from '@/components/auth/Login'
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col align-center h-screen">
|
||||
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
|
||||
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<img
|
||||
alt="Your Company"
|
||||
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
|
||||
className="mx-auto h-10 w-auto"
|
||||
/>
|
||||
<h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
|
||||
Sign in to your account
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<form action="#" method="POST" className="space-y-6">
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-medium leading-6 text-gray-900"
|
||||
>
|
||||
Email address
|
||||
</label>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
required
|
||||
autoComplete="email"
|
||||
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="block text-sm font-medium leading-6 text-gray-900"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
<div className="text-sm">
|
||||
<a
|
||||
href="#"
|
||||
className="font-semibold text-indigo-600 hover:text-indigo-500"
|
||||
>
|
||||
Forgot password?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
required
|
||||
autoComplete="current-password"
|
||||
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p className="mt-10 text-center text-sm text-gray-500">
|
||||
Not a member?{' '}
|
||||
<a
|
||||
href="#"
|
||||
className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500"
|
||||
>
|
||||
Start a 14 day free trial
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Login />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
import MainPage from '@/components/Main'
|
||||
import { getSession } from '@/lib/authActions'
|
||||
import { getCurrentLocale } from '@/locales/server'
|
||||
|
||||
export default function page() {
|
||||
export default async function page() {
|
||||
const session = await getSession()
|
||||
|
||||
const currentLocale = getCurrentLocale()
|
||||
|
||||
const mainPageProps = {
|
||||
currentLocale,
|
||||
isLoggedIn: session?.isLoggedIn,
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
'use client'
|
||||
|
||||
import { logout } from '@/lib/authActions'
|
||||
import { useChangeLocale, useI18n } from '@/locales/client'
|
||||
import { Button, Chip } from '@nextui-org/react'
|
||||
|
||||
export default function MainPage(props) {
|
||||
const { currentLocale } = props
|
||||
const { currentLocale, isLoggedIn } = props
|
||||
const t = useI18n()
|
||||
const changeLocale = useChangeLocale()
|
||||
|
||||
@ -12,7 +13,11 @@ export default function MainPage(props) {
|
||||
currentLocale === 'ja' ? changeLocale('ko') : changeLocale('ja')
|
||||
}
|
||||
|
||||
console.log('MainPage', currentLocale)
|
||||
// console.log('MainPage', currentLocale)
|
||||
|
||||
const handleLogout = async () => {
|
||||
await logout()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -22,6 +27,13 @@ export default function MainPage(props) {
|
||||
<div>
|
||||
<Button onClick={handleChangeLocale}>Change Locale</Button>
|
||||
</div>
|
||||
{isLoggedIn && (
|
||||
<div className="my-4">
|
||||
<Button color="primary" onClick={handleLogout}>
|
||||
로그아웃
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
75
src/components/auth/Login.jsx
Normal file
75
src/components/auth/Login.jsx
Normal file
@ -0,0 +1,75 @@
|
||||
'use client'
|
||||
|
||||
import { login } from '@/lib/authActions'
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<div className="flex flex-col align-center h-screen">
|
||||
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
|
||||
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<img alt="Your Company" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600" className="mx-auto h-10 w-auto" />
|
||||
<h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">Sign in to your account</h2>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<form action={login} method="POST" className="space-y-6">
|
||||
<div>
|
||||
<label htmlFor="userId" className="block text-sm font-medium leading-6 text-gray-900">
|
||||
User ID
|
||||
</label>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="userId"
|
||||
name="id"
|
||||
type="text"
|
||||
required
|
||||
// autoComplete="email"
|
||||
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<label htmlFor="password" className="block text-sm font-medium leading-6 text-gray-900">
|
||||
Password
|
||||
</label>
|
||||
<div className="text-sm">
|
||||
<a href="#" className="font-semibold text-indigo-600 hover:text-indigo-500">
|
||||
Forgot password?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
required
|
||||
autoComplete="current-password"
|
||||
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p className="mt-10 text-center text-sm text-gray-500">
|
||||
Not a member?{' '}
|
||||
<a href="#" className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500">
|
||||
Start a 14 day free trial
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
61
src/lib/authActions.js
Normal file
61
src/lib/authActions.js
Normal file
@ -0,0 +1,61 @@
|
||||
'use server'
|
||||
|
||||
import { cookies } from 'next/headers'
|
||||
import { redirect } from 'next/navigation'
|
||||
|
||||
import { getIronSession } from 'iron-session'
|
||||
|
||||
import { getUserByIdAndPassword } from './user'
|
||||
import { defaultSession, sessionOptions } from './session'
|
||||
|
||||
export async function logout() {
|
||||
const session = await getSession()
|
||||
session.destroy()
|
||||
redirect('/login')
|
||||
}
|
||||
|
||||
export async function getSession() {
|
||||
let session
|
||||
session = await getIronSession(cookies(), sessionOptions)
|
||||
|
||||
console.log('session:', session)
|
||||
if (!session.isLoggedIn) {
|
||||
session.isLoggedIn = defaultSession.isLoggedIn
|
||||
}
|
||||
|
||||
return session
|
||||
}
|
||||
|
||||
export async function login(formData) {
|
||||
const session = await getSession()
|
||||
|
||||
const userId = formData.get('id')
|
||||
const password = formData.get('password')
|
||||
|
||||
console.log('id:', userId)
|
||||
console.log('password:', password)
|
||||
|
||||
// const user = {
|
||||
// id: 1,
|
||||
// name: 'jinsoo Kim',
|
||||
// email: 'jinsoo.kim@example.com',
|
||||
// }
|
||||
const loginUser = await getUserByIdAndPassword({ userId, password })
|
||||
console.log('loginUser:', loginUser)
|
||||
|
||||
if (!loginUser) {
|
||||
throw Error('Wrong Credentials!')
|
||||
}
|
||||
|
||||
// session.id = user.id
|
||||
// session.email = user.email
|
||||
session.userId = loginUser.USER_ID
|
||||
session.saleStoreId = loginUser.SALE_STORE_ID
|
||||
session.name = loginUser.NAME
|
||||
session.mail = loginUser.MAIL
|
||||
session.isLoggedIn = true
|
||||
console.log('session:', session)
|
||||
|
||||
await session.save()
|
||||
redirect('/')
|
||||
}
|
||||
16
src/lib/session.js
Normal file
16
src/lib/session.js
Normal file
@ -0,0 +1,16 @@
|
||||
export const defaultSession = {
|
||||
userId: null,
|
||||
saleStoreId: null,
|
||||
name: null,
|
||||
mail: null,
|
||||
isLoggedIn: false,
|
||||
}
|
||||
|
||||
export const sessionOptions = {
|
||||
password: process.env.SESSION_SECRET,
|
||||
cookieName: 'lama-session',
|
||||
cookieOptions: {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
},
|
||||
}
|
||||
@ -4,9 +4,9 @@ const { PrismaClient } = require('@prisma/client')
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
export async function createUser({ userId, password }) {
|
||||
return prisma.m_USER.create({
|
||||
data: {
|
||||
export async function getUserByIdAndPassword({ userId, password }) {
|
||||
return prisma.m_USER.findFirst({
|
||||
where: {
|
||||
USER_ID: userId,
|
||||
PASSWORD: password,
|
||||
},
|
||||
|
||||
24
yarn.lock
24
yarn.lock
@ -2645,6 +2645,11 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
|
||||
|
||||
cookie@0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
|
||||
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
|
||||
|
||||
cross-spawn@^7.0.0:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz"
|
||||
@ -3091,6 +3096,20 @@ invariant@^2.2.4:
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
iron-session@^8.0.2:
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/iron-session/-/iron-session-8.0.2.tgz#9802e080206a8ba41911b53d29ff7de11161d036"
|
||||
integrity sha512-p4Yf1moQr6gnCcXu5vCaxVKRKDmR9PZcQDfp7ZOgbsSHUsgaNti6OgDB2BdgxC2aS6V/6Hu4O0wYlj92sbdIJg==
|
||||
dependencies:
|
||||
cookie "0.6.0"
|
||||
iron-webcrypto "1.2.1"
|
||||
uncrypto "0.1.3"
|
||||
|
||||
iron-webcrypto@1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz#aa60ff2aa10550630f4c0b11fd2442becdb35a6f"
|
||||
integrity sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==
|
||||
|
||||
is-arrayish@^0.3.1:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
|
||||
@ -4288,6 +4307,11 @@ typed-function@^4.2.1:
|
||||
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-4.2.1.tgz#19aa51847aa2dea9ef5e7fb7641c060179a74426"
|
||||
integrity sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==
|
||||
|
||||
uncrypto@0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b"
|
||||
integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==
|
||||
|
||||
undici-types@~6.13.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.13.0.tgz#e3e79220ab8c81ed1496b5812471afd7cf075ea5"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user