mirror of
https://github.com/LukeHagar/dokploy.git
synced 2025-12-06 04:19:37 +00:00
refactor: add fields
This commit is contained in:
1
apps/dokploy/drizzle/0069_known_aqueduct.sql
Normal file
1
apps/dokploy/drizzle/0069_known_aqueduct.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "user_temp" ADD COLUMN "created_at" timestamp DEFAULT now();
|
||||||
1
apps/dokploy/drizzle/0070_overrated_the_stranger.sql
Normal file
1
apps/dokploy/drizzle/0070_overrated_the_stranger.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "user_temp" ALTER COLUMN "token" SET DEFAULT '';
|
||||||
5285
apps/dokploy/drizzle/meta/0069_snapshot.json
Normal file
5285
apps/dokploy/drizzle/meta/0069_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
5286
apps/dokploy/drizzle/meta/0070_snapshot.json
Normal file
5286
apps/dokploy/drizzle/meta/0070_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -484,6 +484,20 @@
|
|||||||
"when": 1739428942964,
|
"when": 1739428942964,
|
||||||
"tag": "0068_sour_professor_monster",
|
"tag": "0068_sour_professor_monster",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 69,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1739432476590,
|
||||||
|
"tag": "0069_known_aqueduct",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 70,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1739432513877,
|
||||||
|
"tag": "0070_overrated_the_stranger",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,8 @@
|
|||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@oslojs/encoding":"1.1.0",
|
||||||
|
"@oslojs/crypto":"1.0.1",
|
||||||
"drizzle-dbml-generator":"0.10.0",
|
"drizzle-dbml-generator":"0.10.0",
|
||||||
"better-auth":"1.1.16",
|
"better-auth":"1.1.16",
|
||||||
"rotating-file-stream": "3.2.3",
|
"rotating-file-stream": "3.2.3",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export const lucia = new Lucia(adapter, {
|
|||||||
secure: false,
|
secure: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
sessionExpiresIn: new TimeSpan(1, "d"),
|
sessionExpiresIn: new TimeSpan(1, "d"),
|
||||||
getUserAttributes: (attributes) => {
|
getUserAttributes: (attributes) => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -73,14 +73,15 @@ export const users_temp = pgTable("user_temp", {
|
|||||||
.primaryKey()
|
.primaryKey()
|
||||||
.$defaultFn(() => nanoid()),
|
.$defaultFn(() => nanoid()),
|
||||||
name: text("name").notNull().default(""),
|
name: text("name").notNull().default(""),
|
||||||
token: text("token").notNull(),
|
token: text("token").notNull().default(""),
|
||||||
isRegistered: boolean("isRegistered").notNull().default(false),
|
isRegistered: boolean("isRegistered").notNull().default(false),
|
||||||
expirationDate: text("expirationDate")
|
expirationDate: text("expirationDate")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
createdAt: text("createdAt")
|
createdAt2: text("createdAt")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
|
createdAt: timestamp("created_at").defaultNow(),
|
||||||
canCreateProjects: boolean("canCreateProjects").notNull().default(false),
|
canCreateProjects: boolean("canCreateProjects").notNull().default(false),
|
||||||
canAccessToSSHKeys: boolean("canAccessToSSHKeys").notNull().default(false),
|
canAccessToSSHKeys: boolean("canAccessToSSHKeys").notNull().default(false),
|
||||||
canCreateServices: boolean("canCreateServices").notNull().default(false),
|
canCreateServices: boolean("canCreateServices").notNull().default(false),
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import { admin, createAuthMiddleware, organization } from "better-auth/plugins";
|
|||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "../db";
|
import { db } from "../db";
|
||||||
import * as schema from "../db/schema";
|
import * as schema from "../db/schema";
|
||||||
|
import { Scrypt } from "lucia";
|
||||||
|
const scrypt = new Scrypt();
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
database: drizzleAdapter(db, {
|
database: drizzleAdapter(db, {
|
||||||
provider: "pg",
|
provider: "pg",
|
||||||
@@ -12,6 +15,10 @@ export const auth = betterAuth({
|
|||||||
}),
|
}),
|
||||||
emailAndPassword: {
|
emailAndPassword: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
password: {
|
||||||
|
hash: scrypt.hash,
|
||||||
|
verify: scrypt.verify,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
after: createAuthMiddleware(async (ctx) => {
|
after: createAuthMiddleware(async (ctx) => {
|
||||||
|
|||||||
94
packages/server/src/lib/crypto.ts
Normal file
94
packages/server/src/lib/crypto.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// import {
|
||||||
|
// decodeHex,
|
||||||
|
// encodeBase32LowerCaseNoPadding,
|
||||||
|
// encodeHexLowerCase,
|
||||||
|
// } from "@oslojs/encoding";
|
||||||
|
// import { generateRandomString } from "@oslojs/crypto/random";
|
||||||
|
// import { constantTimeEqual } from "@oslojs/crypto/subtle";
|
||||||
|
// import { scrypt } from "./scrypt/index";
|
||||||
|
|
||||||
|
// import type { RandomReader } from "@oslojs/crypto/random";
|
||||||
|
|
||||||
|
// async function generateScryptKey(
|
||||||
|
// data: string,
|
||||||
|
// salt: string,
|
||||||
|
// blockSize = 16,
|
||||||
|
// ): Promise<Uint8Array> {
|
||||||
|
// const encodedData = new TextEncoder().encode(data);
|
||||||
|
// const encodedSalt = new TextEncoder().encode(salt);
|
||||||
|
// const keyUint8Array = await scrypt(encodedData, encodedSalt, {
|
||||||
|
// N: 16384,
|
||||||
|
// r: blockSize,
|
||||||
|
// p: 1,
|
||||||
|
// dkLen: 64,
|
||||||
|
// });
|
||||||
|
// return new Uint8Array(keyUint8Array);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const random: RandomReader = {
|
||||||
|
// read(bytes: Uint8Array): void {
|
||||||
|
// crypto.getRandomValues(bytes);
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export function generateId(length: number): string {
|
||||||
|
// const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
// return generateRandomString(random, alphabet, length);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export function generateIdFromEntropySize(size: number): string {
|
||||||
|
// const buffer = crypto.getRandomValues(new Uint8Array(size));
|
||||||
|
// return encodeBase32LowerCaseNoPadding(buffer);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export class Scrypt implements PasswordHashingAlgorithm {
|
||||||
|
// async hash(password: string): Promise<string> {
|
||||||
|
// const salt = encodeHexLowerCase(crypto.getRandomValues(new Uint8Array(16)));
|
||||||
|
// const key = await generateScryptKey(password.normalize("NFKC"), salt);
|
||||||
|
// return `${salt}:${encodeHexLowerCase(key)}`;
|
||||||
|
// }
|
||||||
|
// async verify(hash: string, password: string): Promise<boolean> {
|
||||||
|
// const parts = hash.split(":");
|
||||||
|
// if (parts.length !== 2) return false;
|
||||||
|
|
||||||
|
// const [salt, key] = parts;
|
||||||
|
// const targetKey = await generateScryptKey(password.normalize("NFKC"), salt);
|
||||||
|
// return constantTimeEqual(targetKey, decodeHex(key));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export class LegacyScrypt implements PasswordHashingAlgorithm {
|
||||||
|
// async hash(password: string): Promise<string> {
|
||||||
|
// const salt = encodeHexLowerCase(crypto.getRandomValues(new Uint8Array(16)));
|
||||||
|
// const key = await generateScryptKey(password.normalize("NFKC"), salt);
|
||||||
|
// return `s2:${salt}:${encodeHexLowerCase(key)}`;
|
||||||
|
// }
|
||||||
|
// async verify(hash: string, password: string): Promise<boolean> {
|
||||||
|
// const parts = hash.split(":");
|
||||||
|
// if (parts.length === 2) {
|
||||||
|
// const [salt, key] = parts;
|
||||||
|
// const targetKey = await generateScryptKey(
|
||||||
|
// password.normalize("NFKC"),
|
||||||
|
// salt,
|
||||||
|
// 8,
|
||||||
|
// );
|
||||||
|
// const result = constantTimeEqual(targetKey, decodeHex(key));
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
// if (parts.length !== 3) return false;
|
||||||
|
// const [version, salt, key] = parts;
|
||||||
|
// if (version === "s2") {
|
||||||
|
// const targetKey = await generateScryptKey(
|
||||||
|
// password.normalize("NFKC"),
|
||||||
|
// salt,
|
||||||
|
// );
|
||||||
|
// return constantTimeEqual(targetKey, decodeHex(key));
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export interface PasswordHashingAlgorithm {
|
||||||
|
// hash(password: string): Promise<string>;
|
||||||
|
// verify(hash: string, password: string): Promise<boolean>;
|
||||||
|
// }
|
||||||
1
packages/server/src/lib/scrypt/index.ts
Normal file
1
packages/server/src/lib/scrypt/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
//
|
||||||
31
pnpm-lock.yaml
generated
31
pnpm-lock.yaml
generated
@@ -558,6 +558,12 @@ importers:
|
|||||||
'@octokit/auth-app':
|
'@octokit/auth-app':
|
||||||
specifier: ^6.0.4
|
specifier: ^6.0.4
|
||||||
version: 6.1.1
|
version: 6.1.1
|
||||||
|
'@oslojs/crypto':
|
||||||
|
specifier: 1.0.1
|
||||||
|
version: 1.0.1
|
||||||
|
'@oslojs/encoding':
|
||||||
|
specifier: 1.1.0
|
||||||
|
version: 1.1.0
|
||||||
'@react-email/components':
|
'@react-email/components':
|
||||||
specifier: ^0.0.21
|
specifier: ^0.0.21
|
||||||
version: 0.0.21(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
version: 0.0.21(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
@@ -2164,6 +2170,18 @@ packages:
|
|||||||
'@one-ini/wasm@0.1.1':
|
'@one-ini/wasm@0.1.1':
|
||||||
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
||||||
|
|
||||||
|
'@oslojs/asn1@1.0.0':
|
||||||
|
resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==}
|
||||||
|
|
||||||
|
'@oslojs/binary@1.0.0':
|
||||||
|
resolution: {integrity: sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==}
|
||||||
|
|
||||||
|
'@oslojs/crypto@1.0.1':
|
||||||
|
resolution: {integrity: sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==}
|
||||||
|
|
||||||
|
'@oslojs/encoding@1.1.0':
|
||||||
|
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
|
||||||
|
|
||||||
'@peculiar/asn1-android@2.3.15':
|
'@peculiar/asn1-android@2.3.15':
|
||||||
resolution: {integrity: sha512-8U2TIj59cRlSXTX2d0mzUKP7whfWGFMzTeC3qPgAbccXFrPNZLaDhpNEdG5U2QZ/tBv/IHlCJ8s+KYXpJeop6w==}
|
resolution: {integrity: sha512-8U2TIj59cRlSXTX2d0mzUKP7whfWGFMzTeC3qPgAbccXFrPNZLaDhpNEdG5U2QZ/tBv/IHlCJ8s+KYXpJeop6w==}
|
||||||
|
|
||||||
@@ -8507,6 +8525,19 @@ snapshots:
|
|||||||
|
|
||||||
'@one-ini/wasm@0.1.1': {}
|
'@one-ini/wasm@0.1.1': {}
|
||||||
|
|
||||||
|
'@oslojs/asn1@1.0.0':
|
||||||
|
dependencies:
|
||||||
|
'@oslojs/binary': 1.0.0
|
||||||
|
|
||||||
|
'@oslojs/binary@1.0.0': {}
|
||||||
|
|
||||||
|
'@oslojs/crypto@1.0.1':
|
||||||
|
dependencies:
|
||||||
|
'@oslojs/asn1': 1.0.0
|
||||||
|
'@oslojs/binary': 1.0.0
|
||||||
|
|
||||||
|
'@oslojs/encoding@1.1.0': {}
|
||||||
|
|
||||||
'@peculiar/asn1-android@2.3.15':
|
'@peculiar/asn1-android@2.3.15':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@peculiar/asn1-schema': 2.3.15
|
'@peculiar/asn1-schema': 2.3.15
|
||||||
|
|||||||
Reference in New Issue
Block a user