From 84c663985a3c48e87c4d8dc1f0e604a411136d42 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sun, 3 Sep 2023 03:49:20 +0800 Subject: [PATCH] feat: add workspace --- README.md | 7 ++++++ prisma/schema.prisma | 53 ++++++++++++++++++++++++++++----------- src/server/model/user.ts | 47 ++++++++++++++++++++++++++++++++-- src/server/utils/const.ts | 9 +++++++ vite.config.ts | 4 +-- 5 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 src/server/utils/const.ts diff --git a/README.md b/README.md index 5afa51d..794edb2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # tianji Tianji must not be leaked + + +## Open Source + +`Tianji` is open source with `Apache 2.0` license. + +And its inspired by `umami` license which under `MIT` and `uptime-kuma` which under `MIT` license too diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8d8f27f..e84284a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -4,11 +4,11 @@ datasource db { } generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" } model User { - id String @id @unique @db.Uuid @default(uuid()) + id String @id @unique @default(uuid()) @db.Uuid username String @unique @db.VarChar(255) password String @db.VarChar(60) role String @db.VarChar(50) @@ -16,25 +16,50 @@ model User { updatedAt DateTime? @updatedAt @db.Timestamptz(6) deletedAt DateTime? @db.Timestamptz(6) + workspaces WorkspacesOnUsers[] +} + +model Workspace { + id String @id @unique @default(uuid()) @db.Uuid + name String @db.VarChar(100) + createdAt DateTime? @default(now()) @db.Timestamptz(6) + updatedAt DateTime? @updatedAt @db.Timestamptz(6) + + users WorkspacesOnUsers[] 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) +model WorkspacesOnUsers { + userId String @db.Uuid + workspaceId String @db.Uuid + role String @db.VarChar(100) + createdAt DateTime? @default(now()) @db.Timestamptz(6) + updatedAt DateTime? @updatedAt @db.Timestamptz(6) + + user User @relation(fields: [userId], references: [id]) + workspace Workspace @relation(fields: [workspaceId], references: [id]) + + @@id([userId, workspaceId]) + @@index([userId]) + @@index([workspaceId]) +} + +model Website { + id String @id @unique @default(uuid()) @db.Uuid + name String @db.VarChar(100) + domain String? @db.VarChar(500) + shareId String? @unique @db.VarChar(50) + resetAt DateTime? @db.Timestamptz(6) + workspace Workspace @relation(fields: [workspaceId], references: [id]) + workspaceId 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([workspaceId]) @@index([createdAt]) @@index([shareId]) } diff --git a/src/server/model/user.ts b/src/server/model/user.ts index 3927b65..d245f6f 100644 --- a/src/server/model/user.ts +++ b/src/server/model/user.ts @@ -1,5 +1,6 @@ import { prisma } from './_client'; import bcryptjs from 'bcryptjs'; +import { ROLES } from '../utils/const'; async function hashPassword(password: string) { return await bcryptjs.hash(password, 10); @@ -19,17 +20,51 @@ export async function createAdminUser(username: string, password: string) { data: { username, password: await hashPassword(password), - role: 'admin', + role: ROLES.admin, + workspaces: { + create: [ + { + role: ROLES.owner, + workspace: { + create: { + name: username, + }, + }, + }, + ], + }, }, }); } export async function createUser(username: string, password: string) { + const existCount = await prisma.user.count({ + where: { + username, + }, + }); + + if (existCount > 0) { + throw new Error('User already exists'); + } + await prisma.user.create({ data: { username, password: await hashPassword(password), - role: 'normal', + role: ROLES.user, + workspaces: { + create: [ + { + role: ROLES.owner, + workspace: { + create: { + name: username, + }, + }, + }, + ], + }, }, }); } @@ -40,6 +75,14 @@ export async function authUser(username: string, password: string) { username, password: await hashPassword(password), }, + select: { + id: true, + username: true, + role: true, + createdAt: true, + updatedAt: true, + deletedAt: true, + }, }); return user; diff --git a/src/server/utils/const.ts b/src/server/utils/const.ts new file mode 100644 index 0000000..4be83c2 --- /dev/null +++ b/src/server/utils/const.ts @@ -0,0 +1,9 @@ +export const ROLES = { + // System Role + admin: 'admin', + user: 'user', + + // Workspace Role + owner: 'owner', + readOnly: 'readOnly', +} as const; diff --git a/vite.config.ts b/vite.config.ts index 9cc50ea..627a319 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,5 +1,5 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig({