feat: add prisma
This commit is contained in:
parent
89c0874983
commit
6761bc5d08
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
||||
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.env
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
10
package.json
10
package.json
@ -5,13 +5,19 @@
|
||||
"scripts": {
|
||||
"dev": "nodemon src/server/main.ts -w src/server",
|
||||
"start": "NODE_ENV=production ts-node src/server/main.ts",
|
||||
"build": "vite build"
|
||||
"build": "vite build",
|
||||
"db:push": "prisma db push",
|
||||
"db:generate": "prisma generate",
|
||||
"db:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/charts": "^1.4.2",
|
||||
"@ant-design/icons": "^5.2.5",
|
||||
"@prisma/client": "^5.2.0",
|
||||
"antd": "^5.8.5",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"clsx": "^2.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"react": "^18.2.0",
|
||||
@ -23,6 +29,7 @@
|
||||
"vite-express": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bcryptjs": "^2.4.3",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/lodash-es": "^4.17.9",
|
||||
"@types/node": "^18.17.12",
|
||||
@ -32,6 +39,7 @@
|
||||
"autoprefixer": "^10.4.15",
|
||||
"nodemon": "^2.0.22",
|
||||
"postcss": "^8.4.29",
|
||||
"prisma": "^5.2.0",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"vite": "^4.4.9"
|
||||
}
|
||||
|
@ -7,12 +7,21 @@ dependencies:
|
||||
'@ant-design/icons':
|
||||
specifier: ^5.2.5
|
||||
version: 5.2.5(react-dom@18.2.0)(react@18.2.0)
|
||||
'@prisma/client':
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.0(prisma@5.2.0)
|
||||
antd:
|
||||
specifier: ^5.8.5
|
||||
version: 5.8.5(react-dom@18.2.0)(react@18.2.0)
|
||||
bcryptjs:
|
||||
specifier: ^2.4.3
|
||||
version: 2.4.3
|
||||
clsx:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
dotenv:
|
||||
specifier: ^16.3.1
|
||||
version: 16.3.1
|
||||
express:
|
||||
specifier: ^4.18.2
|
||||
version: 4.18.2
|
||||
@ -42,6 +51,9 @@ dependencies:
|
||||
version: 0.10.0
|
||||
|
||||
devDependencies:
|
||||
'@types/bcryptjs':
|
||||
specifier: ^2.4.3
|
||||
version: 2.4.3
|
||||
'@types/express':
|
||||
specifier: ^4.17.17
|
||||
version: 4.17.17
|
||||
@ -69,6 +81,9 @@ devDependencies:
|
||||
postcss:
|
||||
specifier: ^8.4.29
|
||||
version: 8.4.29
|
||||
prisma:
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.0
|
||||
tailwindcss:
|
||||
specifier: ^3.3.3
|
||||
version: 3.3.3(ts-node@10.9.1)
|
||||
@ -1519,6 +1534,28 @@ packages:
|
||||
fastq: 1.15.0
|
||||
dev: true
|
||||
|
||||
/@prisma/client@5.2.0(prisma@5.2.0):
|
||||
resolution: {integrity: sha512-AiTjJwR4J5Rh6Z/9ZKrBBLel3/5DzUNntMohOy7yObVnVoTNVFi2kvpLZlFuKO50d7yDspOtW6XBpiAd0BVXbQ==}
|
||||
engines: {node: '>=16.13'}
|
||||
requiresBuild: true
|
||||
peerDependencies:
|
||||
prisma: '*'
|
||||
peerDependenciesMeta:
|
||||
prisma:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@prisma/engines-version': 5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f
|
||||
prisma: 5.2.0
|
||||
dev: false
|
||||
|
||||
/@prisma/engines-version@5.2.0-25.2804dc98259d2ea960602aca6b8e7fdc03c1758f:
|
||||
resolution: {integrity: sha512-jsnKT5JIDIE01lAeCj2ghY9IwxkedhKNvxQeoyLs6dr4ZXynetD0vTy7u6wMJt8vVPv8I5DPy/I4CFaoXAgbtg==}
|
||||
dev: false
|
||||
|
||||
/@prisma/engines@5.2.0:
|
||||
resolution: {integrity: sha512-dT7FOLUCdZmq+AunLqB1Iz+ZH/IIS1Fz2THmKZQ6aFONrQD/BQ5ecJ7g2wGS2OgyUFf4OaLam6/bxmgdOBDqig==}
|
||||
requiresBuild: true
|
||||
|
||||
/@probe.gl/env@3.6.0:
|
||||
resolution: {integrity: sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==}
|
||||
dependencies:
|
||||
@ -1710,6 +1747,10 @@ packages:
|
||||
resolution: {integrity: sha512-q/qvE40hkg9gcfFBR5JwlWepK+eh2RB93dwUEHtNID+nx+UPsBBK2ilzYtP8QOutw89eR2F0PQ0RfypFSSdz2w==}
|
||||
dev: false
|
||||
|
||||
/@types/bcryptjs@2.4.3:
|
||||
resolution: {integrity: sha512-XTnH9E/rp51aKGsiMtQCHV/owDLW2E9QAxI7ItpWWm6Gi6XO1e4o3VuEYDma0lbitj1vNOBj05Qk8l2BYoiN4A==}
|
||||
dev: true
|
||||
|
||||
/@types/body-parser@1.19.2:
|
||||
resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
|
||||
dependencies:
|
||||
@ -2077,6 +2118,10 @@ packages:
|
||||
/balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
/bcryptjs@2.4.3:
|
||||
resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==}
|
||||
dev: false
|
||||
|
||||
/binary-extensions@2.2.0:
|
||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2536,6 +2581,11 @@ packages:
|
||||
resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==}
|
||||
dev: false
|
||||
|
||||
/dotenv@16.3.1:
|
||||
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/dotignore@0.1.2:
|
||||
resolution: {integrity: sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==}
|
||||
hasBin: true
|
||||
@ -3774,6 +3824,14 @@ packages:
|
||||
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==}
|
||||
dev: false
|
||||
|
||||
/prisma@5.2.0:
|
||||
resolution: {integrity: sha512-FfFlpjVCkZwrqxDnP4smlNYSH1so+CbfjgdpioFzGGqlQAEm6VHAYSzV7jJgC3ebtY9dNOhDMS2+4/1DDSM7bQ==}
|
||||
engines: {node: '>=16.13'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@prisma/engines': 5.2.0
|
||||
|
||||
/probe.gl@3.6.0:
|
||||
resolution: {integrity: sha512-19JydJWI7+DtR4feV+pu4Mn1I5TAc0xojuxVgZdXIyfmTLfUaFnk4OloWK1bKbPtkgGKLr2lnbnCXmpZEcEp9g==}
|
||||
dependencies:
|
||||
|
142
prisma/schema.prisma
Normal file
142
prisma/schema.prisma
Normal file
@ -0,0 +1,142 @@
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @unique @db.Uuid @default(uuid())
|
||||
username String @unique @db.VarChar(255)
|
||||
password String @db.VarChar(60)
|
||||
role String @db.VarChar(50)
|
||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||
updatedAt DateTime? @updatedAt @db.Timestamptz(6)
|
||||
deletedAt DateTime? @db.Timestamptz(6)
|
||||
|
||||
website Website[]
|
||||
}
|
||||
|
||||
model Website {
|
||||
id String @id @unique @db.Uuid @default(uuid())
|
||||
name String @db.VarChar(100)
|
||||
domain String? @db.VarChar(500)
|
||||
shareId String? @unique @db.VarChar(50)
|
||||
resetAt DateTime? @db.Timestamptz(6)
|
||||
userId String? @db.Uuid
|
||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||
updatedAt DateTime? @updatedAt @db.Timestamptz(6)
|
||||
deletedAt DateTime? @db.Timestamptz(6)
|
||||
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
eventData EventData[]
|
||||
sessionData SessionData[]
|
||||
|
||||
@@index([userId])
|
||||
@@index([createdAt])
|
||||
@@index([shareId])
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @unique @db.Uuid
|
||||
websiteId String @db.Uuid
|
||||
hostname String? @db.VarChar(100)
|
||||
browser String? @db.VarChar(20)
|
||||
os String? @db.VarChar(20)
|
||||
device String? @db.VarChar(20)
|
||||
screen String? @db.VarChar(11)
|
||||
language String? @db.VarChar(35)
|
||||
country String? @db.Char(2)
|
||||
subdivision1 String? @db.VarChar(20)
|
||||
subdivision2 String? @db.VarChar(50)
|
||||
city String? @db.VarChar(50)
|
||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||
|
||||
websiteEvent WebsiteEvent[]
|
||||
sessionData SessionData[]
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([websiteId])
|
||||
@@index([websiteId, createdAt])
|
||||
@@index([websiteId, createdAt, hostname])
|
||||
@@index([websiteId, createdAt, browser])
|
||||
@@index([websiteId, createdAt, os])
|
||||
@@index([websiteId, createdAt, device])
|
||||
@@index([websiteId, createdAt, screen])
|
||||
@@index([websiteId, createdAt, language])
|
||||
@@index([websiteId, createdAt, country])
|
||||
@@index([websiteId, createdAt, subdivision1])
|
||||
@@index([websiteId, createdAt, city])
|
||||
}
|
||||
|
||||
model WebsiteEvent {
|
||||
id String @id() @db.Uuid
|
||||
websiteId String @db.Uuid
|
||||
sessionId String @db.Uuid
|
||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||
urlPath String @db.VarChar(500)
|
||||
urlQuery String? @db.VarChar(500)
|
||||
referrerPath String? @db.VarChar(500)
|
||||
referrerQuery String? @db.VarChar(500)
|
||||
referrerDomain String? @db.VarChar(500)
|
||||
pageTitle String? @db.VarChar(500)
|
||||
eventType Int @default(1) @db.Integer
|
||||
eventName String? @db.VarChar(50)
|
||||
|
||||
eventData EventData[]
|
||||
session Session @relation(fields: [sessionId], references: [id])
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([sessionId])
|
||||
@@index([websiteId])
|
||||
@@index([websiteId, createdAt])
|
||||
@@index([websiteId, createdAt, urlPath])
|
||||
@@index([websiteId, createdAt, urlQuery])
|
||||
@@index([websiteId, createdAt, referrerDomain])
|
||||
@@index([websiteId, createdAt, pageTitle])
|
||||
@@index([websiteId, createdAt, eventName])
|
||||
@@index([websiteId, sessionId, createdAt])
|
||||
}
|
||||
|
||||
model EventData {
|
||||
id String @id() @db.Uuid
|
||||
websiteId String @db.Uuid
|
||||
websiteEventId String @db.Uuid
|
||||
eventKey String @db.VarChar(500)
|
||||
stringValue String? @db.VarChar(500)
|
||||
numberValue Decimal? @db.Decimal(19, 4)
|
||||
dateValue DateTime? @db.Timestamptz(6)
|
||||
dataType Int @db.Integer
|
||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||
|
||||
website Website @relation(fields: [websiteId], references: [id])
|
||||
websiteEvent WebsiteEvent @relation(fields: [websiteEventId], references: [id])
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([websiteId])
|
||||
@@index([websiteEventId])
|
||||
@@index([websiteId, createdAt])
|
||||
@@index([websiteId, createdAt, eventKey])
|
||||
}
|
||||
|
||||
model SessionData {
|
||||
id String @id() @db.Uuid
|
||||
websiteId String @db.Uuid
|
||||
sessionId String @db.Uuid
|
||||
sessionKey String @db.VarChar(500)
|
||||
stringValue String? @db.VarChar(500)
|
||||
numberValue Decimal? @db.Decimal(19, 4)
|
||||
dateValue DateTime? @db.Timestamptz(6)
|
||||
dataType Int @db.Integer
|
||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||
deletedAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||
|
||||
website Website @relation(fields: [websiteId], references: [id])
|
||||
session Session @relation(fields: [sessionId], references: [id])
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([websiteId])
|
||||
@@index([sessionId])
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import 'dotenv/config';
|
||||
import express from 'express';
|
||||
import ViteExpress from 'vite-express';
|
||||
|
||||
|
3
src/server/model/_client.ts
Normal file
3
src/server/model/_client.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
export const prisma = new PrismaClient();
|
46
src/server/model/user.ts
Normal file
46
src/server/model/user.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { prisma } from './_client';
|
||||
import bcryptjs from 'bcryptjs';
|
||||
|
||||
async function hashPassword(password: string) {
|
||||
return await bcryptjs.hash(password, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create User
|
||||
*/
|
||||
export async function createAdminUser(username: string, password: string) {
|
||||
const count = await prisma.user.count();
|
||||
|
||||
if (count > 0) {
|
||||
throw new Error('Create Admin User Just Only allow in non people exist');
|
||||
}
|
||||
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
password: await hashPassword(password),
|
||||
role: 'admin',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function createUser(username: string, password: string) {
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
password: await hashPassword(password),
|
||||
role: 'normal',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function authUser(username: string, password: string) {
|
||||
const user = await prisma.user.findFirstOrThrow({
|
||||
where: {
|
||||
username,
|
||||
password: await hashPassword(password),
|
||||
},
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
Loading…
Reference in New Issue
Block a user