Feat: User Model + Login

用户数据表,前端可登录可获取用户信息
This commit is contained in:
奇趣保罗 2022-05-22 12:36:15 +08:00
parent b03c9339bd
commit 04eb8628d4
13 changed files with 283 additions and 46 deletions

View File

@ -0,0 +1,11 @@
-- CreateTable
CREATE TABLE `User` (
`id` VARCHAR(191) NOT NULL,
`name` VARCHAR(191) NOT NULL,
`email` VARCHAR(191) NOT NULL,
`password` VARCHAR(191) NOT NULL,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

View File

@ -0,0 +1,12 @@
/*
Warnings:
- A unique constraint covering the columns `[name]` on the table `User` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[email]` on the table `User` will be added. If there are existing duplicate values, this will fail.
*/
-- CreateIndex
CREATE UNIQUE INDEX `User_name_key` ON `User`(`name`);
-- CreateIndex
CREATE UNIQUE INDEX `User_email_key` ON `User`(`email`);

View File

@ -1,14 +0,0 @@
import { createContext } from "react";
import { IGlobalData } from "@/types/GlobalData";
import { initalState, IAction } from "@/hooks/useGlobalData";
const GlobalContext = createContext<{ globalData: IGlobalData, setGlobalData: React.Dispatch<IAction> }>({
globalData: initalState,
setGlobalData() {}
});
GlobalContext.displayName = "GlobalContext";
export default GlobalContext;

View File

@ -1,6 +1,6 @@
// React
import React, { useState } from "react";
import useGlobalContext from "@/hooks/useGlobalContext";
import { useGlobalContext } from "@/hooks/useGlobal";
// UI
@ -47,7 +47,7 @@ function Aside() {
<Link to="/acgm"></Link>
<Link to="/bili"></Link>
<Link to="/bing"></Link>
{profile.name && <Link to="/admin"></Link>}
{profile.id && <Link to="/admin"></Link>}
</nav>
</nav>
</nav>

View File

@ -1,18 +1,31 @@
import { useReducer } from "react";
import { createContext, useReducer, useContext } from "react";
import { IGlobalData } from "@/types/GlobalData";
export const initalState: IGlobalData = {
profile: {
name: "加载中",
avatar: ""
}
};
export type IAction =
| { type: "all", value: IGlobalData }
| { type: "profile", value: Partial<IGlobalData["profile"]> }
export const initalState: IGlobalData = {
profile: {
name: "",
avatar: ""
}
};
//
// Context
//
export const GlobalContext = createContext<{ globalData: IGlobalData, setGlobalData: React.Dispatch<IAction> }>({
globalData: initalState,
setGlobalData() {}
});
GlobalContext.displayName = "GlobalContext";
//
// Reducer
//
function reducer(state: IGlobalData, action: IAction): IGlobalData {
if (!action) return state;
@ -35,10 +48,16 @@ function reducer(state: IGlobalData, action: IAction): IGlobalData {
return state;
}
function useGlobalData(): [IGlobalData, React.Dispatch<IAction>]{
let [state, dispatch] = useReducer(reducer, initalState);
return [state, dispatch];
//
// Reducer Hooks
//
export function useGlobalData() {
return useReducer(reducer, initalState);
}
export default useGlobalData;
//
// Context Hooks
//
export function useGlobalContext() {
return useContext(GlobalContext);
}

View File

@ -1,9 +0,0 @@
import { useContext } from "react";
import GlobalContext from "@/components/GlobalContext";
function useGlobalContext() {
return useContext(GlobalContext);
}
export default useGlobalContext;

View File

@ -1,8 +1,10 @@
import React, { lazy } from "react";
import ReactDOM from "react-dom";
import useGlobalData from "@/hooks/useGlobalData";
import GlobalContext from "@/components/GlobalContext";
import { useGlobalData, GlobalContext } from "@/hooks/useGlobal";
import { useRequest } from "ahooks";
import getUserInfo from "./server/api/auth/userinfo";
import "./kico.css";
import "./index.css";
@ -33,6 +35,17 @@ const admin = lazy(() => import("./pages/admin"));
function App() {
let [globalData, setGlobalData] = useGlobalData();
const getUserInfoRequest = useRequest(getUserInfo, {
onSuccess: (res) => {
if (res.code === 0){
setGlobalData({ type: "profile", value: { name: "未登录" } });
}
else if (res.data) {
setGlobalData({ type: "profile", value: res.data });
}
}
});
return (
<GlobalContext.Provider value={{ globalData, setGlobalData }}>
<Router>

View File

@ -3,7 +3,7 @@ import React from "react";
import { useNavigate } from "react-router-dom";
import { useRequest } from "ahooks";
import useStat from "@/hooks/useStat";
import useGlobalContext from "@/hooks/useGlobalContext";
import { useGlobalContext } from "@/hooks/useGlobal";
// UI

View File

@ -10,8 +10,6 @@ export default Api(
const jwt = await useInject(JwtService);
const token = await jwt.sign({ name: "Paul" });
const user = await prisma.user.findFirst({
where: {
name: ctx.query.username,
@ -26,6 +24,11 @@ export default Api(
}
}
const token = await jwt.sign({
id: user.id,
name: user.name
});
// Token
ctx.cookies.set("paul-token", token, {
maxAge: 60 * 60 * 24 * 2 * 100,
@ -43,7 +46,8 @@ export default Api(
msg: "Success",
data: {
profile: {
name: "Paul",
id: user.id,
name: user.name,
avatar: "https://sdn.geekzu.org/avatar/d22eb460ecab37fcd7205e6a3c55c228?s=200&r=X&d=",
},
token

View File

@ -0,0 +1,51 @@
import { Api, Get, Query, useContext, useInject } from "@midwayjs/hooks";
import { JwtService } from "@midwayjs/jwt";
import { prisma } from "../../utils/prisma";
export default Api(
Get(),
Query<{ username: string, password: string }>(),
async () => {
const ctx = useContext();
const jwt = await useInject(JwtService);
const token = ctx.cookies.get("paul-token");
if (!token) {
return {
code: 0,
msg: "Not Login"
}
}
const jwtContent = jwt.decode(token) as Record<string, any>;
if (!jwtContent.id) {
return {
code: 0,
msg: "Invalid Token"
}
}
const user = await prisma.user.findUnique({
where: {
id: jwtContent.id
}
});
if (!user) {
return {
code: 0,
msg: "Not Login"
}
}
return {
code: 1,
msg: "Success",
data: {
...user,
avatar: "https://sdn.geekzu.org/avatar/d22eb460ecab37fcd7205e6a3c55c228?s=200&r=X&d="
}
}
}
);

View File

@ -11,7 +11,7 @@ export class JwtStrategy extends PassportStrategy(
@Config("jwt")
jwtConfig: any;
async validate(payload) {
async validate(payload: any) {
console.log("payload", payload);
return payload;

View File

@ -1,5 +1,6 @@
export interface IGlobalData {
profile: {
id?: string
name: string
avatar: string
}

153
yarn.lock
View File

@ -487,6 +487,13 @@
tslib "^2.3.0"
upath "^2.0.1"
"@midwayjs/jwt@^3.3.5":
version "3.3.5"
resolved "https://registry.yarnpkg.com/@midwayjs/jwt/-/jwt-3.3.5.tgz#8d28df741c5b955b3317bf6eaea4b99c640b3e3e"
integrity sha512-LuhZaul/Spdn+ifkBY7FJAJvOatOeVWn+CQTcdjwwvIX4NQSkc3DXE1URYFfxesJEU8Z0eajG+FM4SoEuPhpyg==
dependencies:
jsonwebtoken "^8.5.1"
"@midwayjs/koa@^3.3.0":
version "3.3.0"
resolved "https://registry.yarnpkg.com/@midwayjs/koa/-/koa-3.3.0.tgz#4dbef1fa45f210a9156505d4bfcb6f6d7230791d"
@ -528,6 +535,11 @@
source-map-support "^0.5.16"
typescript "~4.2.4"
"@midwayjs/passport@^3.3.5":
version "3.3.5"
resolved "https://registry.yarnpkg.com/@midwayjs/passport/-/passport-3.3.5.tgz#f777d27f36ca10f128712beb7655e546226be86e"
integrity sha512-tA/jeMGA8+971tawqgt8aIPpeb/v4htgM4x4qkkxwjqcGn9I4vpO0aP3495RK6DAFDhkKcY9Yv/aFFwodEfmQQ==
"@midwayjs/redis@^3.3.2":
version "3.3.2"
resolved "https://registry.yarnpkg.com/@midwayjs/redis/-/redis-3.3.2.tgz#ab8c42f9548d27fad17a8b39326259e04122b753"
@ -843,6 +855,13 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/jsonwebtoken@*":
version "8.5.8"
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz#01b39711eb844777b7af1d1f2b4cf22fda1c0c44"
integrity sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A==
dependencies:
"@types/node" "*"
"@types/keygrip@*":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
@ -896,6 +915,30 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da"
integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==
"@types/passport-jwt@^3.0.6":
version "3.0.6"
resolved "https://registry.yarnpkg.com/@types/passport-jwt/-/passport-jwt-3.0.6.tgz#41cc8b5803d5f5f06eb33e19c453b42716def4f1"
integrity sha512-cmAAMIRTaEwpqxlrZyiEY9kdibk94gP5KTF8AT1Ra4rWNZYHNMreqhKUEeC5WJtuN5SJZjPQmV+XO2P5PlnvNQ==
dependencies:
"@types/express" "*"
"@types/jsonwebtoken" "*"
"@types/passport-strategy" "*"
"@types/passport-strategy@*":
version "0.2.35"
resolved "https://registry.yarnpkg.com/@types/passport-strategy/-/passport-strategy-0.2.35.tgz#e52f5212279ea73f02d9b06af67efe9cefce2d0c"
integrity sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==
dependencies:
"@types/express" "*"
"@types/passport" "*"
"@types/passport@*":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.7.tgz#85892f14932168158c86aecafd06b12f5439467a"
integrity sha512-JtswU8N3kxBYgo+n9of7C97YQBT+AYPP2aBfNGTzABqPAZnK/WOAaKfh3XesUYMZRrXFuoPc2Hv0/G/nQFveHw==
dependencies:
"@types/express" "*"
"@types/prismjs@^1.26.0":
version "1.26.0"
resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.0.tgz#a1c3809b0ad61c62cac6d4e0c56d610c910b7654"
@ -1139,6 +1182,11 @@ browserslist@^4.17.5:
node-releases "^2.0.2"
picocolors "^1.0.0"
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
@ -1473,6 +1521,13 @@ dotenv@^16.0.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411"
integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==
ecdsa-sig-formatter@1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
dependencies:
safe-buffer "^5.0.1"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@ -2079,6 +2134,39 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"
jsonwebtoken@^8.2.0, jsonwebtoken@^8.5.1:
version "8.5.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
dependencies:
jws "^3.2.2"
lodash.includes "^4.3.0"
lodash.isboolean "^3.0.3"
lodash.isinteger "^4.0.4"
lodash.isnumber "^3.0.3"
lodash.isplainobject "^4.0.6"
lodash.isstring "^4.0.1"
lodash.once "^4.0.0"
ms "^2.1.1"
semver "^5.6.0"
jwa@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
dependencies:
buffer-equal-constant-time "1.0.1"
ecdsa-sig-formatter "1.0.11"
safe-buffer "^5.0.1"
jws@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
dependencies:
jwa "^1.4.1"
safe-buffer "^5.0.1"
keygrip@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226"
@ -2169,11 +2257,46 @@ lodash.defaults@^4.2.0:
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
lodash.includes@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
lodash.isarguments@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
lodash.isboolean@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
lodash.isinteger@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
lodash.isnumber@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
lodash.isstring@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
lodash.once@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
@ -2377,6 +2500,27 @@ parseurl@^1.3.2:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
passport-jwt@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/passport-jwt/-/passport-jwt-4.0.0.tgz#7f0be7ba942e28b9f5d22c2ebbb8ce96ef7cf065"
integrity sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==
dependencies:
jsonwebtoken "^8.2.0"
passport-strategy "^1.0.0"
passport-strategy@1.x.x, passport-strategy@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=
passport@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/passport/-/passport-0.5.2.tgz#0cb38dd8a71552c8390dfa6a9a6f7f3909954bcf"
integrity sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==
dependencies:
passport-strategy "1.x.x"
pause "0.0.1"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
@ -2402,6 +2546,11 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
pause@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
@ -2595,7 +2744,7 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
safe-buffer@5.2.1, safe-buffer@~5.2.0:
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@ -2633,7 +2782,7 @@ screenfull@^5.0.0:
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba"
integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==
semver@^5.4.1:
semver@^5.4.1, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==