feat: 完整注册登录注销流程
This commit is contained in:
parent
de010862f4
commit
5c6b5b9761
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"typescript.suggest.paths": false,
|
||||||
|
"javascript.suggest.paths": false,
|
||||||
|
}
|
11
app/components/signout-button.tsx
Normal file
11
app/components/signout-button.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
'use client';
|
||||||
|
import { signout } from '@/app/lib/actions';
|
||||||
|
|
||||||
|
export default function SignoutButton() {
|
||||||
|
return <button onClick={async () => {
|
||||||
|
|
||||||
|
await signout();
|
||||||
|
}}>
|
||||||
|
注销
|
||||||
|
</button>
|
||||||
|
};
|
@ -2,7 +2,7 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
:root {
|
/* :root {
|
||||||
--foreground-rgb: 0, 0, 0;
|
--foreground-rgb: 0, 0, 0;
|
||||||
--background-start-rgb: 214, 219, 220;
|
--background-start-rgb: 214, 219, 220;
|
||||||
--background-end-rgb: 255, 255, 255;
|
--background-end-rgb: 255, 255, 255;
|
||||||
@ -30,4 +30,4 @@ body {
|
|||||||
.text-balance {
|
.text-balance {
|
||||||
text-wrap: balance;
|
text-wrap: balance;
|
||||||
}
|
}
|
||||||
}
|
} */
|
@ -1,12 +1,55 @@
|
|||||||
'use server';
|
'use server';
|
||||||
import axios from "axios";
|
import { redirect } from 'next/navigation'
|
||||||
|
import { cookies } from 'next/headers'
|
||||||
|
|
||||||
const SIGNUP_URL = 'https://tachy.daoyoucloud.com/api/auth:signUp';
|
const SIGNUP_URL = 'https://tachy.daoyoucloud.com/api/auth:signUp';
|
||||||
// const SIGNUP_URL = 'http://127.0.0.1:13000/api/auth:signUp';
|
const SIGNIN_URL = 'https://tachy.daoyoucloud.com/api/auth:signIn';
|
||||||
|
const SIGNOUT_URL = 'https://tachy.daoyoucloud.com/api/auth:signOut'
|
||||||
|
|
||||||
|
|
||||||
export async function authenticate(_currentState: unknown, formData: FormData) {
|
export async function signout() {
|
||||||
return '';
|
const token = cookies().get('token');
|
||||||
|
const result = await fetch(SIGNOUT_URL, {
|
||||||
|
"headers": {
|
||||||
|
"authorization": "Bearer " + token?.value,
|
||||||
|
"cache-control": "no-cache",
|
||||||
|
"pragma": "no-cache",
|
||||||
|
"x-app": "danmu-sim",
|
||||||
|
"x-authenticator": "basic",
|
||||||
|
"x-locale": "zh-CN",
|
||||||
|
"x-timezone": "+08:00",
|
||||||
|
"x-with-acl-meta": "true",
|
||||||
|
},
|
||||||
|
"body": '',
|
||||||
|
"method": "POST"
|
||||||
|
});
|
||||||
|
cookies().delete('token');
|
||||||
|
redirect('/signin');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function signin(_currentState: unknown, formData: FormData) {
|
||||||
|
const result = await fetch(SIGNIN_URL, {
|
||||||
|
"headers": {
|
||||||
|
"cache-control": "no-cache",
|
||||||
|
"content-type": "application/json",
|
||||||
|
"pragma": "no-cache",
|
||||||
|
"x-app": "danmu-sim",
|
||||||
|
"x-authenticator": "basic",
|
||||||
|
"x-hostname": "tachy.daoyoucloud.com",
|
||||||
|
"x-locale": "zh-CN",
|
||||||
|
"x-timezone": "+08:00",
|
||||||
|
"x-with-acl-meta": "true",
|
||||||
|
},
|
||||||
|
"body": JSON.stringify(Object.fromEntries(formData)),
|
||||||
|
"method": "POST"
|
||||||
|
});
|
||||||
|
const res = await result.json();
|
||||||
|
if (res.errors) {
|
||||||
|
return res.errors[0].message;
|
||||||
|
}
|
||||||
|
cookies().set('token', res.data.token);
|
||||||
|
redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signup(_currentState: unknown, formData: FormData) {
|
export async function signup(_currentState: unknown, formData: FormData) {
|
||||||
|
3
app/music/page.tsx
Normal file
3
app/music/page.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default function Page() {
|
||||||
|
return <main>hello world</main>
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
import SignoutButton from "@/app/components/signout-button";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<main className="flex min-h-screen flex-col items-center justify-between p-24">
|
<main className="flex min-h-screen flex-col items-center justify-between p-24">
|
||||||
|
<SignoutButton />
|
||||||
|
<Link className="btn" href="/music">弹幕测试</Link>
|
||||||
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
|
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
|
||||||
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
|
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
|
||||||
Get started by editing
|
Get started by editing
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { authenticate } from '@/app/lib/actions'
|
import { signin } from '@/app/lib/actions'
|
||||||
import { useFormState, useFormStatus } from 'react-dom'
|
import { useFormState, useFormStatus } from 'react-dom'
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [errorMessage, dispatch] = useFormState(authenticate, undefined)
|
const [errorMessage, dispatch] = useFormState(signin, undefined)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form action={dispatch}>
|
<form action={dispatch}>
|
||||||
<input type="email" name="email" placeholder="Email" required />
|
<input name="account" placeholder="Account" required />
|
||||||
<input type="password" name="password" placeholder="Password" required />
|
<input type="password" name="password" placeholder="Password" required />
|
||||||
<div>{errorMessage && <p>{errorMessage}</p>}</div>
|
<div>{errorMessage && <p>{errorMessage}</p>}</div>
|
||||||
<LoginButton />
|
<LoginButton />
|
||||||
@ -19,7 +19,7 @@ export default function Page() {
|
|||||||
function LoginButton() {
|
function LoginButton() {
|
||||||
const { pending } = useFormStatus()
|
const { pending } = useFormStatus()
|
||||||
|
|
||||||
const handleClick = (event) => {
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
if (pending) {
|
if (pending) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
20
middleware.ts
Normal file
20
middleware.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import type { NextRequest } from 'next/server'
|
||||||
|
|
||||||
|
export function middleware(request: NextRequest) {
|
||||||
|
const currentUser = request.cookies.get('token')?.value
|
||||||
|
|
||||||
|
if (currentUser && !request.nextUrl.pathname.startsWith('/')) {
|
||||||
|
return Response.redirect(new URL('/', request.url))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentUser
|
||||||
|
&& !request.nextUrl.pathname.startsWith('/signin')
|
||||||
|
&& !request.nextUrl.pathname.startsWith('/signup')
|
||||||
|
) {
|
||||||
|
return Response.redirect(new URL('/signin', request.url))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user