feat: Prisma schema (7 models) + NestJS bootstrap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
88dbb99f9d
commit
5a6c376821
115
backend/prisma/schema.prisma
Normal file
115
backend/prisma/schema.prisma
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
model User {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
email String @unique
|
||||||
|
passwordHash String @map("password_hash")
|
||||||
|
displayName String? @map("display_name")
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
@@map("users")
|
||||||
|
}
|
||||||
|
|
||||||
|
model HostGroup {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
name String
|
||||||
|
parentId Int? @map("parent_id")
|
||||||
|
sortOrder Int @default(0) @map("sort_order")
|
||||||
|
parent HostGroup? @relation("GroupTree", fields: [parentId], references: [id], onDelete: SetNull)
|
||||||
|
children HostGroup[] @relation("GroupTree")
|
||||||
|
hosts Host[]
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
@@map("host_groups")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Host {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
name String
|
||||||
|
hostname String
|
||||||
|
port Int @default(22)
|
||||||
|
protocol Protocol @default(ssh)
|
||||||
|
groupId Int? @map("group_id")
|
||||||
|
credentialId Int? @map("credential_id")
|
||||||
|
tags String[] @default([])
|
||||||
|
notes String?
|
||||||
|
color String? @db.VarChar(7)
|
||||||
|
sortOrder Int @default(0) @map("sort_order")
|
||||||
|
hostFingerprint String? @map("host_fingerprint")
|
||||||
|
lastConnectedAt DateTime? @map("last_connected_at")
|
||||||
|
group HostGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
|
||||||
|
credential Credential? @relation(fields: [credentialId], references: [id], onDelete: SetNull)
|
||||||
|
connectionLogs ConnectionLog[]
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
@@map("hosts")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Credential {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
name String
|
||||||
|
username String?
|
||||||
|
domain String?
|
||||||
|
type CredentialType
|
||||||
|
encryptedValue String? @map("encrypted_value")
|
||||||
|
sshKeyId Int? @map("ssh_key_id")
|
||||||
|
sshKey SshKey? @relation(fields: [sshKeyId], references: [id], onDelete: SetNull)
|
||||||
|
hosts Host[]
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
@@map("credentials")
|
||||||
|
}
|
||||||
|
|
||||||
|
model SshKey {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
name String
|
||||||
|
keyType String @map("key_type") @db.VarChar(20)
|
||||||
|
fingerprint String?
|
||||||
|
publicKey String? @map("public_key")
|
||||||
|
encryptedPrivateKey String @map("encrypted_private_key")
|
||||||
|
passphraseEncrypted String? @map("passphrase_encrypted")
|
||||||
|
credentials Credential[]
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
@@map("ssh_keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
model ConnectionLog {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
hostId Int @map("host_id")
|
||||||
|
protocol Protocol
|
||||||
|
connectedAt DateTime @default(now()) @map("connected_at")
|
||||||
|
disconnectedAt DateTime? @map("disconnected_at")
|
||||||
|
host Host @relation(fields: [hostId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@map("connection_logs")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Setting {
|
||||||
|
key String @id
|
||||||
|
value String
|
||||||
|
|
||||||
|
@@map("settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Protocol {
|
||||||
|
ssh
|
||||||
|
rdp
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CredentialType {
|
||||||
|
password
|
||||||
|
ssh_key
|
||||||
|
}
|
||||||
23
backend/src/app.module.ts
Normal file
23
backend/src/app.module.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { PrismaModule } from './prisma/prisma.module';
|
||||||
|
import { AuthModule } from './auth/auth.module';
|
||||||
|
import { VaultModule } from './vault/vault.module';
|
||||||
|
import { ConnectionsModule } from './connections/connections.module';
|
||||||
|
import { SettingsModule } from './settings/settings.module';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
PrismaModule,
|
||||||
|
AuthModule,
|
||||||
|
VaultModule,
|
||||||
|
ConnectionsModule,
|
||||||
|
SettingsModule,
|
||||||
|
ServeStaticModule.forRoot({
|
||||||
|
rootPath: join(__dirname, '..', 'public'),
|
||||||
|
exclude: ['/api/(.*)'],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class AppModule {}
|
||||||
18
backend/src/main.ts
Normal file
18
backend/src/main.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
import { ValidationPipe } from '@nestjs/common';
|
||||||
|
import { WsAdapter } from '@nestjs/platform-ws';
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
async function bootstrap() {
|
||||||
|
const app = await NestFactory.create(AppModule);
|
||||||
|
app.setGlobalPrefix('api');
|
||||||
|
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
|
||||||
|
app.useWebSocketAdapter(new WsAdapter(app));
|
||||||
|
app.enableCors({
|
||||||
|
origin: process.env.NODE_ENV === 'production' ? false : 'http://localhost:3001',
|
||||||
|
credentials: true,
|
||||||
|
});
|
||||||
|
await app.listen(3000);
|
||||||
|
console.log('Wraith backend running on port 3000');
|
||||||
|
}
|
||||||
|
bootstrap();
|
||||||
9
backend/src/prisma/prisma.module.ts
Normal file
9
backend/src/prisma/prisma.module.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
import { PrismaService } from './prisma.service';
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@Module({
|
||||||
|
providers: [PrismaService],
|
||||||
|
exports: [PrismaService],
|
||||||
|
})
|
||||||
|
export class PrismaModule {}
|
||||||
13
backend/src/prisma/prisma.service.ts
Normal file
13
backend/src/prisma/prisma.service.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
|
||||||
|
async onModuleInit() {
|
||||||
|
await this.$connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
async onModuleDestroy() {
|
||||||
|
await this.$disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user