feat(/api/user): Compete login-code and auth-middleware
This commit is contained in:
parent
1abe25849b
commit
ba813ffcc8
@ -24,11 +24,12 @@
|
||||
<el-menu-item index="/area/jx2/game">游戏服务器</el-menu-item>
|
||||
</el-sub-menu> -->
|
||||
</el-sub-menu>
|
||||
<el-menu-item index="/forum" disabled>论坛</el-menu-item>
|
||||
<el-menu-item index="/host" disabled>托管</el-menu-item>
|
||||
<el-menu-item index="forum" disabled>论坛</el-menu-item>
|
||||
<el-menu-item index="host" disabled>托管</el-menu-item>
|
||||
<div class="flex-grow" />
|
||||
<el-menu-item index="/login">登录</el-menu-item>
|
||||
<el-menu-item index="register">注册</el-menu-item>
|
||||
<el-menu-item v-if="auth" index="/user/login">登录</el-menu-item>
|
||||
<el-menu-item v-if="auth" index="/user/register">注册</el-menu-item>
|
||||
<el-menu-item v-if="!auth" @click="logoutNow">注销</el-menu-item>
|
||||
</el-menu>
|
||||
</client-only>
|
||||
</template>
|
||||
@ -36,9 +37,13 @@
|
||||
<script lang="ts" setup>
|
||||
const activeIndex = ref("1");
|
||||
const handleSelect = (key: string, keyPath: string[]) => {
|
||||
console.log(key, keyPath);
|
||||
navigateTo(key);
|
||||
};
|
||||
const auth = ref(useCookie("auth").value == undefined);
|
||||
function logoutNow() {
|
||||
logout();
|
||||
auth.value = true;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.flex-grow {
|
||||
|
14
composables/logout.ts
Normal file
14
composables/logout.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// 它将作为 useFoo() 可用(文件名的驼峰形式,不包括扩展名)
|
||||
|
||||
export default function () {
|
||||
const auth = useCookie("auth");
|
||||
$fetch("/api/user/logout", {
|
||||
method: "POST",
|
||||
body: {
|
||||
auth: auth.value,
|
||||
},
|
||||
});
|
||||
auth.value = undefined;
|
||||
navigateTo("/");
|
||||
return 1;
|
||||
}
|
0
middleware/admin.ts
Normal file
0
middleware/admin.ts
Normal file
27
middleware/auth.ts
Normal file
27
middleware/auth.ts
Normal file
@ -0,0 +1,27 @@
|
||||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
const auth = useCookie("auth");
|
||||
if (auth.value === undefined) {
|
||||
ElMessage("未登录或cookie未开启");
|
||||
return navigateTo("/user/login", { replace: true });
|
||||
} else {
|
||||
const { data: result } = await useFetch("/api/user/auth", {
|
||||
method: "post",
|
||||
body: {
|
||||
auth: auth.value,
|
||||
},
|
||||
});
|
||||
if (!result.value?.login && to.path !== "/user/test") {
|
||||
if (result.value?.code == 0) {
|
||||
ElMessage("未登录");
|
||||
} else if (result.value?.code == 2) {
|
||||
ElMessage("登录超时,请重新登录");
|
||||
auth.value = undefined;
|
||||
} else {
|
||||
ElMessage(result.value?.code);
|
||||
}
|
||||
return navigateTo("/user/login");
|
||||
} else {
|
||||
console.log(auth.value);
|
||||
}
|
||||
}
|
||||
});
|
7
middleware/unauth.ts
Normal file
7
middleware/unauth.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
const auth = useCookie("auth");
|
||||
if (auth.value === undefined) {
|
||||
} else {
|
||||
return navigateTo("/");
|
||||
}
|
||||
});
|
23
pages/admin/loginlogs/index.vue
Normal file
23
pages/admin/loginlogs/index.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<Head>
|
||||
<Title>登录日志</Title>
|
||||
<Meta name="description" />
|
||||
</Head>
|
||||
<client-only>
|
||||
<el-table
|
||||
:default-sort="{ prop: 'id', order: 'descending' }"
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="id" label="id" width="50" />
|
||||
<el-table-column prop="username" label="用户" width="180" />
|
||||
<el-table-column prop="date" label="登录时间" width="180" />
|
||||
<el-table-column prop="ip" label="登录ip" width="180" />
|
||||
</el-table>
|
||||
</client-only>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { LoginLog } from "~/types/Log";
|
||||
const data: LoginLog[] = await $fetch("/api/admin/loginlogs");
|
||||
const tableData = ref(data);
|
||||
</script>
|
@ -17,42 +17,6 @@
|
||||
view="tabs"
|
||||
style="padding: 30px"
|
||||
>
|
||||
<StaticElement
|
||||
tag="h4"
|
||||
align="center"
|
||||
content="个人信息"
|
||||
name="static"
|
||||
/>
|
||||
<TextElement
|
||||
name="username"
|
||||
label="昵称"
|
||||
placeholder="昵称"
|
||||
:columns="{ container: 4, label: 3, wrapper: 12 }"
|
||||
rules="required|min:3"
|
||||
/>
|
||||
<PhoneElement
|
||||
name="phone"
|
||||
allow-incomplete
|
||||
unmask
|
||||
default="+86"
|
||||
:include="['cn']"
|
||||
label="手机号"
|
||||
placeholder="+86"
|
||||
:columns="{ container: 12, label: 1, wrapper: 4 }"
|
||||
rules="required"
|
||||
/>
|
||||
<TextElement
|
||||
name="code"
|
||||
label="验证码"
|
||||
placeholder="xxxxxx"
|
||||
:columns="{ container: 4, label: 4, wrapper: 12 }"
|
||||
rules="required"
|
||||
/>
|
||||
<ButtonElement
|
||||
name="button"
|
||||
:columns="{ container: 8, label: 3, wrapper: 12 }"
|
||||
button-label="发送验证码"
|
||||
/>
|
||||
<StaticElement
|
||||
tag="h4"
|
||||
align="center"
|
||||
@ -119,5 +83,8 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import PhoneElemen from "@vueform/vueform";
|
||||
definePageMeta({
|
||||
middleware: ["auth"],
|
||||
});
|
||||
const form = ref();
|
||||
</script>
|
||||
|
@ -4,6 +4,7 @@
|
||||
<Title>FreePotato Server</Title>
|
||||
<Meta name="description" content="免费服务器~" />
|
||||
</Head>
|
||||
|
||||
<ElRow :gutter="10" align="middle" style="height: 900px">
|
||||
<ElCol :span="24"><IndexNewsCarouel /></ElCol>
|
||||
<ElCol :span="24"><IndexNewsStatus /></ElCol>
|
||||
|
@ -1,63 +0,0 @@
|
||||
<template>
|
||||
<!--登录界面-->
|
||||
<Head>
|
||||
<Title>登录界面</Title>
|
||||
<Meta name="description" />
|
||||
</Head>
|
||||
<div
|
||||
style="width: 25%; margin: auto"
|
||||
:style="{
|
||||
boxShadow: `var(--el-box-shadow-light)`,
|
||||
}"
|
||||
>
|
||||
<ClientOnly>
|
||||
<Vueform
|
||||
endpoint="/api/test"
|
||||
method="POST"
|
||||
view="tabs"
|
||||
style="padding: 30px"
|
||||
>
|
||||
<StaticElement tag="h4" align="center" content="登录" name="static" />
|
||||
<PhoneElement
|
||||
input-type="number"
|
||||
name="phone"
|
||||
allow-incomplete
|
||||
unmask
|
||||
default="+86"
|
||||
:include="['cn']"
|
||||
label="手机号"
|
||||
placeholder="+86"
|
||||
:columns="{ container: 12, label: 3, wrapper: 10 }"
|
||||
rules="required|min:14|max:14"
|
||||
/>
|
||||
<TextElement
|
||||
input-type="password"
|
||||
name="password"
|
||||
label="密码"
|
||||
rules="required|min:8|max:16|confirmed"
|
||||
:columns="{ container: 12, label: 3, wrapper: 10 }"
|
||||
/>
|
||||
<CheckboxElement
|
||||
name="policy"
|
||||
label="用户协议"
|
||||
rules="required"
|
||||
message="您必须同意用户政策才能继续"
|
||||
>
|
||||
已阅读并同意<ElLink href="/" target="_blank">《用户协议》</ElLink>
|
||||
</CheckboxElement>
|
||||
<CheckboxElement name="news"> 希望获取最新资讯 </CheckboxElement>
|
||||
<ButtonElement
|
||||
name="submit"
|
||||
button-label="登录"
|
||||
align="center"
|
||||
size="lg"
|
||||
submits
|
||||
/>
|
||||
</Vueform>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import PhoneElemen from "@vueform/vueform";
|
||||
const form = ref();
|
||||
</script>
|
@ -4,3 +4,8 @@
|
||||
<Meta name="description" />
|
||||
</Head>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ["auth"],
|
||||
});
|
||||
</script>
|
||||
|
111
pages/user/login/index.vue
Normal file
111
pages/user/login/index.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--登录界面-->
|
||||
<Head>
|
||||
<Title>登录界面</Title>
|
||||
<Meta name="description" />
|
||||
</Head>
|
||||
<div
|
||||
class="formbox"
|
||||
:style="{
|
||||
boxShadow: `var(--el-box-shadow-light)`,
|
||||
}"
|
||||
>
|
||||
<ClientOnly>
|
||||
<Vueform
|
||||
endpoint="/api/user/login"
|
||||
method="POST"
|
||||
view="tabs"
|
||||
style="padding: 30px"
|
||||
@success="PostSuccess"
|
||||
>
|
||||
<StaticElement tag="h4" align="center" content="登录" name="static" />
|
||||
<TextElement
|
||||
ref="phone$"
|
||||
name="phone"
|
||||
allow-incomplete
|
||||
label="手机号"
|
||||
placeholder="+86"
|
||||
:columns="{ container: 12, label: 3, wrapper: 10 }"
|
||||
rules="required|min:11|max:11"
|
||||
/>
|
||||
<TextElement
|
||||
input-type="password"
|
||||
name="password"
|
||||
allow-incomplete
|
||||
label="密码"
|
||||
rules="required|min:8|max:16"
|
||||
:columns="{ container: 12, label: 3, wrapper: 10 }"
|
||||
/>
|
||||
<HiddenElement :default="ip" name="client_ip" />
|
||||
<CheckboxElement
|
||||
name="policy"
|
||||
label="用户协议"
|
||||
rules="required"
|
||||
message="您必须同意用户政策才能继续"
|
||||
>
|
||||
已阅读并同意<ElLink href="/" target="_blank">《用户协议》</ElLink>
|
||||
</CheckboxElement>
|
||||
<ButtonElement
|
||||
name="submit"
|
||||
button-label="登录"
|
||||
align="center"
|
||||
size="lg"
|
||||
submits
|
||||
/>
|
||||
</Vueform>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import PhoneElemen from "@vueform/vueform";
|
||||
definePageMeta({
|
||||
middleware: ["unauth"],
|
||||
});
|
||||
const form = ref();
|
||||
const data: { query: string } = await $fetch("http://ip-api.com/json");
|
||||
const ip = data.query;
|
||||
function PostSuccess(response: {
|
||||
data: {
|
||||
code: number;
|
||||
msg: string;
|
||||
token: string;
|
||||
};
|
||||
}) {
|
||||
if (response.data.code == 1) {
|
||||
ElMessage({ message: response.data.msg, type: "success" });
|
||||
const auth = useCookie("auth", { maxAge: 60 * 30 });
|
||||
auth.value = response.data.token;
|
||||
location.reload();
|
||||
navigateTo("/", { replace: true });
|
||||
} else if (response.data.code == -1) {
|
||||
ElMessage({ message: response.data.msg, type: "warning" });
|
||||
navigateTo("/user/register");
|
||||
} else {
|
||||
ElMessage({ message: response.data.msg, type: "warning" });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.formbox {
|
||||
width: 25%;
|
||||
margin: auto;
|
||||
}
|
||||
@media screen and (min-width: 901px) and (max-width: 1200px) {
|
||||
.formbox {
|
||||
width: 50%;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 601px) and (max-width: 900px) {
|
||||
.formbox {
|
||||
width: 75%;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
.formbox {
|
||||
width: 88%;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
9
pages/user/logout.ts
Normal file
9
pages/user/logout.ts
Normal file
@ -0,0 +1,9 @@
|
||||
const auth = useCookie("auth");
|
||||
$fetch("/api/user/logout", {
|
||||
method: "POST",
|
||||
body: {
|
||||
auth: auth.value,
|
||||
},
|
||||
});
|
||||
auth.value = undefined;
|
||||
navigateTo("/");
|
@ -17,6 +17,7 @@
|
||||
view="tabs"
|
||||
:model-value="form"
|
||||
@update:model-value="form = $event"
|
||||
@success="RegSuccess"
|
||||
validate-on="change"
|
||||
style="padding: 5%"
|
||||
>
|
||||
@ -31,18 +32,14 @@
|
||||
rules="required|min:3|max:64"
|
||||
@input="Check()"
|
||||
/>
|
||||
<PhoneElement
|
||||
<TextElement
|
||||
ref="phone$"
|
||||
input-type="number"
|
||||
name="phone"
|
||||
allow-incomplete
|
||||
unmask
|
||||
default="+86"
|
||||
:include="['cn']"
|
||||
label="手机号"
|
||||
placeholder="+86"
|
||||
:columns="{ container: 12, label: 3, wrapper: 10 }"
|
||||
rules="required|min:14|max:14"
|
||||
rules="required|min:11|max:11"
|
||||
@input="Check()"
|
||||
:disabled="phoneChecked"
|
||||
/>
|
||||
@ -95,7 +92,6 @@
|
||||
>
|
||||
已阅读并同意<ElLink href="/" target="_blank">《用户协议》</ElLink>
|
||||
</CheckboxElement>
|
||||
<CheckboxElement name="news"> 希望获取最新资讯 </CheckboxElement>
|
||||
<ButtonElement
|
||||
:disabled="canSubmit"
|
||||
name="submit"
|
||||
@ -134,30 +130,33 @@ function sliderHandleError() {
|
||||
function Check() {
|
||||
const query = {
|
||||
username: form.value.username,
|
||||
phone: form.value.phone.replace("+86", ""),
|
||||
phone: form.value.phone || "",
|
||||
};
|
||||
if (!/^(?!1(4|7)\d{9})1[3-9]\d{9}$/.test(query.phone)) {
|
||||
phone$.value.messageBag.clear("errors");
|
||||
phone$.value.messageBag.append("手机号格式错误" + query.phone);
|
||||
if (!/^(?!1(4|7)\d{9})1[3-9]\d{9}$/.test(query.phone) && query.phone != "") {
|
||||
username$.value.messageBag.clear("errors");
|
||||
username$.value.messageBag.append("手机号格式错误" + query.phone);
|
||||
canSubmit.value = true;
|
||||
return;
|
||||
} else {
|
||||
phone$.value.messageBag = [];
|
||||
username$.value.messageBag.clear("errors");
|
||||
}
|
||||
$fetch("/api/test/reg", {
|
||||
$fetch("/api/reg", {
|
||||
method: "POST",
|
||||
body: query,
|
||||
}).then((res) => {
|
||||
if (!res.phone) {
|
||||
phone$.value.messageBag.append("手机号已经注册");
|
||||
username$.value.messageBag.append("手机号已经注册");
|
||||
canSubmit.value = true;
|
||||
return 0;
|
||||
} else {
|
||||
username$.value.messageBag.clear("errors");
|
||||
canSubmit.value = false;
|
||||
}
|
||||
if (!res.username) {
|
||||
username$.value.messageBag.append("昵称已存在");
|
||||
canSubmit.value = true;
|
||||
} else {
|
||||
username$.value.messageBag.clear("errors");
|
||||
canSubmit.value = false;
|
||||
}
|
||||
});
|
||||
@ -170,10 +169,10 @@ function Send() {
|
||||
Check();
|
||||
|
||||
if (!canSubmit.value) {
|
||||
$fetch("/api/test/sms", {
|
||||
$fetch("/api/reg/sms", {
|
||||
method: "POST",
|
||||
body: {
|
||||
phone: form.value.phone.replace("+86", ""),
|
||||
phone: form.value.phone,
|
||||
},
|
||||
}).then((res) => {
|
||||
switch (res.code) {
|
||||
@ -199,7 +198,7 @@ function Send() {
|
||||
}
|
||||
function CheckCode() {
|
||||
if (!code$.value.invalid) {
|
||||
$fetch("/api/test/code", {
|
||||
$fetch("/api/reg/code", {
|
||||
method: "POST",
|
||||
body: {
|
||||
phone: form.value.phone.replace("+86", ""),
|
||||
@ -217,7 +216,7 @@ function CheckCode() {
|
||||
ElMessage({ message: res.msg, type: "success" });
|
||||
codeBtnRef.value.disabled = true;
|
||||
codeBtnRef.value.text = "已验证";
|
||||
phoneChecked.value = ture;
|
||||
phoneChecked.value = true;
|
||||
break;
|
||||
case 2:
|
||||
ElMessage({ message: res.msg, type: "warning" });
|
||||
@ -231,6 +230,14 @@ function CheckCode() {
|
||||
});
|
||||
}
|
||||
}
|
||||
function RegSuccess(response: { data: { code: number; msg: string } }, form$) {
|
||||
if (response.data.code == 1) {
|
||||
ElMessage({ message: response.data.msg, type: "success" });
|
||||
navigateTo("/user/login");
|
||||
} else {
|
||||
ElMessage({ message: response.data.msg, type: "warning" });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.formbox {
|
@ -3,6 +3,7 @@
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
binaryTargets = ["native", "debian-openssl-3.0.x"]
|
||||
}
|
||||
|
||||
datasource db {
|
||||
@ -44,9 +45,9 @@ model Register {
|
||||
}
|
||||
model Loginlogs {
|
||||
id Int @id @default(autoincrement())
|
||||
phone String
|
||||
time DateTime
|
||||
outtime DateTime
|
||||
ip String
|
||||
loiner User @relation(fields: [userid], references: [id])
|
||||
loginer User @relation(fields: [userid], references: [id])
|
||||
userid Int
|
||||
token String @unique
|
||||
}
|
38
server/api/admin/loginlogs.ts
Normal file
38
server/api/admin/loginlogs.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import type { LoginLog } from "~/types/Log";
|
||||
const db = new PrismaClient();
|
||||
type log = { loginer: { username: string | null } } & {
|
||||
id: number;
|
||||
outtime: Date;
|
||||
ip: string;
|
||||
userid: number;
|
||||
token: string;
|
||||
};
|
||||
function formatLogs(raw: log[]): LoginLog[] {
|
||||
var logs: LoginLog[] = [];
|
||||
raw.forEach((element: log) => {
|
||||
logs.push({
|
||||
id: element.id,
|
||||
username: element.loginer.username || "none",
|
||||
date: new Date(element.outtime.getTime() - 1800000).toLocaleTimeString(),
|
||||
ip: element.ip,
|
||||
});
|
||||
});
|
||||
return logs;
|
||||
}
|
||||
export default defineEventHandler(async (event) => {
|
||||
const loginlogs = await db.loginlogs.findMany({
|
||||
orderBy: {
|
||||
outtime: "desc", // 'asc' 表示升序,'desc' 表示降序
|
||||
},
|
||||
include: {
|
||||
loginer: {
|
||||
select: {
|
||||
username: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await db.$disconnect();
|
||||
return formatLogs(loginlogs);
|
||||
});
|
@ -14,6 +14,7 @@ export default defineEventHandler(async (event) => {
|
||||
code: "",
|
||||
deadline: new Date(),
|
||||
};
|
||||
await db.$disconnect();
|
||||
const deadlineDate = new Date(register.deadline);
|
||||
const now = new Date();
|
||||
if (now > deadlineDate) {
|
@ -2,7 +2,7 @@ import { PrismaClient } from "@prisma/client";
|
||||
const db = new PrismaClient();
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
return {
|
||||
const res = {
|
||||
username:
|
||||
(await db.user.findFirst({
|
||||
where: {
|
||||
@ -16,4 +16,6 @@ export default defineEventHandler(async (event) => {
|
||||
},
|
||||
})) == null,
|
||||
};
|
||||
await db.$disconnect();
|
||||
return res;
|
||||
});
|
@ -83,11 +83,14 @@ export default defineEventHandler(async (event) => {
|
||||
const deadlineDate = new Date(register.deadline);
|
||||
const now = new Date();
|
||||
if (now <= deadlineDate) {
|
||||
await db.$disconnect();
|
||||
return { code: 2, msg: "三分钟内请勿重发送" };
|
||||
} else {
|
||||
await db.$disconnect();
|
||||
return send(body.phone);
|
||||
}
|
||||
} else {
|
||||
await db.$disconnect();
|
||||
return send(body.phone);
|
||||
}
|
||||
});
|
@ -2,37 +2,6 @@ import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const db = new PrismaClient();
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
console.info(body);
|
||||
let isSend =
|
||||
(await db.register.findFirst({
|
||||
where: {
|
||||
phone: body.phone,
|
||||
},
|
||||
})) != null;
|
||||
if (isSend) {
|
||||
const register = (await db.register.findFirst({
|
||||
where: {
|
||||
phone: body.phone,
|
||||
},
|
||||
orderBy: {
|
||||
deadline: "desc", // 'asc' 表示升序,'desc' 表示降序
|
||||
},
|
||||
})) || {
|
||||
deadline: new Date(),
|
||||
};
|
||||
const deadlineDate = new Date(register.deadline);
|
||||
const now = new Date();
|
||||
if (now <= deadlineDate) {
|
||||
return { code: 2, msg: "三分钟内请勿重发送" };
|
||||
} else {
|
||||
return {
|
||||
code: -1,
|
||||
msg:
|
||||
"发送成功" + now + "<=" + deadlineDate + ":" + (now <= deadlineDate),
|
||||
};
|
||||
}
|
||||
}
|
||||
return isSend;
|
||||
export default defineEventHandler((event) => {
|
||||
return event;
|
||||
});
|
||||
|
35
server/api/user/auth.ts
Normal file
35
server/api/user/auth.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const db = new PrismaClient();
|
||||
|
||||
async function auth(auth: string) {
|
||||
const res = await db.loginlogs.findFirst({
|
||||
where: { token: auth.toString() },
|
||||
});
|
||||
//return JSON.stringify((await res).values)
|
||||
if (res == null) {
|
||||
return {
|
||||
login: false,
|
||||
code: 0, //未登录
|
||||
};
|
||||
} else {
|
||||
const deadlineDate = new Date(res.outtime);
|
||||
const now = new Date();
|
||||
if (now < deadlineDate) {
|
||||
return {
|
||||
login: true,
|
||||
code: 1, //登录状态正常
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
login: false,
|
||||
code: 2, //登录超时
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
return auth(body.auth);
|
||||
});
|
@ -2,22 +2,20 @@ import { PrismaClient } from "@prisma/client";
|
||||
const db = new PrismaClient();
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
const register = (await db.register.findFirst({
|
||||
const register = await db.register.findFirst({
|
||||
where: {
|
||||
phone: body.phone,
|
||||
},
|
||||
orderBy: {
|
||||
deadline: "desc", // 'asc' 表示升序,'desc' 表示降序
|
||||
},
|
||||
})) || {
|
||||
code: "",
|
||||
deadline: new Date(),
|
||||
};
|
||||
});
|
||||
if (register != null) {
|
||||
const deadlineDate = new Date(register.deadline.getTime() + 7 * 60 * 1000);
|
||||
const now = new Date();
|
||||
if (now <= deadlineDate) {
|
||||
if (register.code != body.code) {
|
||||
return { code: 0, msg: "验证码错误请重新发送" };
|
||||
return { code: 0, msg: "验证码错误请重新发送" + register };
|
||||
} else {
|
||||
await db.user.create({
|
||||
data: {
|
||||
@ -29,9 +27,18 @@ export default defineEventHandler(async (event) => {
|
||||
.digest("hex"),
|
||||
},
|
||||
});
|
||||
await db.$disconnect();
|
||||
return { code: 1, msg: "注册成功" };
|
||||
}
|
||||
} else {
|
||||
await db.$disconnect();
|
||||
return {
|
||||
code: -1,
|
||||
msg: "验证码超时",
|
||||
};
|
||||
}
|
||||
} else {
|
||||
await db.$disconnect();
|
||||
return {
|
||||
code: -1,
|
||||
msg: "验证码超时",
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
const db = new PrismaClient();
|
||||
function generateDeadline() {
|
||||
const now = new Date(); // 获取当前时间
|
||||
const threeMinutesLater = new Date(now.getTime() + 30 * 60 * 1000); // 加上30分钟
|
||||
return threeMinutesLater.toISOString(); // 转换为ISO格式字符串
|
||||
}
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
const loginer = await db.user.findFirst({
|
||||
@ -17,9 +22,26 @@ export default defineEventHandler(async (event) => {
|
||||
.update(body.password)
|
||||
.digest("hex")
|
||||
) {
|
||||
return { code: 1, msg: "登录成功" };
|
||||
const token = (await import("crypto"))
|
||||
.createHash("md5")
|
||||
.update(body.password + new Date().toISOString())
|
||||
.digest("hex");
|
||||
await db.loginlogs.create({
|
||||
data: {
|
||||
userid: loginer.id,
|
||||
outtime: generateDeadline(),
|
||||
token: token,
|
||||
ip: body.client_ip,
|
||||
},
|
||||
});
|
||||
await db.$disconnect();
|
||||
return { code: 1, msg: "登录成功", token: token };
|
||||
} else {
|
||||
return { code: 0, msg: "用户名、手机号或密码错误" };
|
||||
await db.$disconnect();
|
||||
return {
|
||||
code: 0,
|
||||
msg: "用户名、手机号或密码错误" /* + JSON.stringify(body) */,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
15
server/api/user/logout.ts
Normal file
15
server/api/user/logout.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
const db = new PrismaClient();
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
await db.loginlogs.update({
|
||||
where: {
|
||||
token: body.auth,
|
||||
},
|
||||
data: {
|
||||
outtime: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
await db.$disconnect();
|
||||
return 1;
|
||||
});
|
6
types/Log/LoginLog.ts
Normal file
6
types/Log/LoginLog.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type LoginLog = {
|
||||
id: number;
|
||||
username: string;
|
||||
date: string;
|
||||
ip: string;
|
||||
};
|
1
types/Log/index.d.ts
vendored
Normal file
1
types/Log/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export { LoginLog } from "./LoginLog.ts";
|
Loading…
Reference in New Issue
Block a user