refactor: convert all findMany to new structure
This commit is contained in:
parent
74714f8e74
commit
1e04c763f0
27 changed files with 304 additions and 269 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { hashPassword } from "better-auth/crypto";
|
||||
import { and, eq, ne } from "drizzle-orm";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "~/server/db/db";
|
||||
import { account, usersTable, member, organization } from "~/server/db/schema";
|
||||
import type { AuthMiddlewareContext } from "../auth";
|
||||
|
|
@ -14,7 +14,9 @@ export const convertLegacyUserOnFirstLogin = async (ctx: AuthMiddlewareContext)
|
|||
}
|
||||
|
||||
const legacyUser = await db.query.usersTable.findFirst({
|
||||
where: and(eq(usersTable.username, body.username.trim().toLowerCase()), ne(usersTable.passwordHash, "")),
|
||||
where: {
|
||||
AND: [{ username: body.username.trim().toLowerCase() }, { passwordHash: { NOT: "" } }],
|
||||
},
|
||||
});
|
||||
|
||||
if (legacyUser) {
|
||||
|
|
@ -26,7 +28,7 @@ export const convertLegacyUserOnFirstLogin = async (ctx: AuthMiddlewareContext)
|
|||
const accountId = crypto.randomUUID();
|
||||
|
||||
const oldMembership = await tx.query.member.findFirst({
|
||||
where: eq(member.userId, legacyUser.id),
|
||||
where: { userId: legacyUser.id },
|
||||
with: {
|
||||
organization: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { db } from "~/server/db/db";
|
||||
import type { AuthMiddlewareContext } from "../auth";
|
||||
import { logger } from "~/server/utils/logger";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { appMetadataTable } from "~/server/db/schema";
|
||||
import { ForbiddenError } from "http-errors-enhanced";
|
||||
import { REGISTRATION_ENABLED_KEY } from "~/client/lib/constants";
|
||||
|
||||
|
|
@ -15,7 +13,7 @@ export const ensureOnlyOneUser = async (ctx: AuthMiddlewareContext) => {
|
|||
}
|
||||
|
||||
const result = await db.query.appMetadataTable.findFirst({
|
||||
where: eq(appMetadataTable.key, REGISTRATION_ENABLED_KEY),
|
||||
where: { key: REGISTRATION_ENABLED_KEY },
|
||||
});
|
||||
|
||||
if (result?.value !== "true" && existingUser) {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ const createBetterAuth = (secret: string) => {
|
|||
create: {
|
||||
before: async (session) => {
|
||||
const orgMembership = await db.query.member.findFirst({
|
||||
where: eq(member.userId, session.userId),
|
||||
where: { userId: session.userId },
|
||||
});
|
||||
|
||||
if (!orgMembership) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const listOrganizations = () => {
|
|||
|
||||
const getUserCurrentOrganization = async (userId: string) => {
|
||||
const membership = await db.query.member.findFirst({
|
||||
where: eq(member.userId, userId),
|
||||
where: { userId },
|
||||
with: {
|
||||
organization: true,
|
||||
},
|
||||
|
|
@ -36,9 +36,7 @@ const assignUserToOrganization = async (userId: string, organizationId: string)
|
|||
throw new Error("Organization not found");
|
||||
}
|
||||
|
||||
const existingMembership = await db.query.member.findFirst({
|
||||
where: eq(member.userId, userId),
|
||||
});
|
||||
const existingMembership = await db.query.member.findFirst({ where: { userId } });
|
||||
|
||||
await db.transaction(async (tx) => {
|
||||
if (existingMembership) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Database } from "bun:sqlite";
|
||||
import { relations } from "./relations";
|
||||
import path from "node:path";
|
||||
import { drizzle } from "drizzle-orm/bun-sqlite";
|
||||
import { migrate } from "drizzle-orm/bun-sqlite/migrator";
|
||||
|
|
@ -13,7 +14,7 @@ import type * as schemaTypes from "./schema";
|
|||
* to isolate the db initialization code from the rest of the server code.
|
||||
*/
|
||||
let _sqlite: Database | undefined;
|
||||
let _db: ReturnType<typeof drizzle<typeof schemaTypes>> | undefined;
|
||||
let _db: ReturnType<typeof initDb> | undefined;
|
||||
let _schema: typeof schemaTypes | undefined;
|
||||
|
||||
/**
|
||||
|
|
@ -35,7 +36,7 @@ const initDb = () => {
|
|||
}
|
||||
|
||||
_sqlite = new Database(DATABASE_URL);
|
||||
return drizzle({ client: _sqlite, schema: _schema });
|
||||
return drizzle({ client: _sqlite, relations, schema: _schema });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -51,7 +52,7 @@ export const db = new Proxy(
|
|||
return Reflect.get(_db, prop, receiver);
|
||||
},
|
||||
},
|
||||
) as ReturnType<typeof drizzle<typeof schemaTypes>>;
|
||||
) as ReturnType<typeof initDb>;
|
||||
|
||||
export const runDbMigrations = () => {
|
||||
let migrationsFolder: string;
|
||||
|
|
|
|||
141
app/server/db/relations.ts
Normal file
141
app/server/db/relations.ts
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
import { defineRelations } from "drizzle-orm";
|
||||
import * as schema from "./schema";
|
||||
|
||||
export const relations = defineRelations(schema, (r) => ({
|
||||
repositoriesTable: {
|
||||
backupSchedulesTablesViaBackupScheduleMirrorsTable: r.many.backupSchedulesTable({
|
||||
from: r.repositoriesTable.id.through(r.backupScheduleMirrorsTable.repositoryId),
|
||||
to: r.backupSchedulesTable.id.through(r.backupScheduleMirrorsTable.scheduleId),
|
||||
alias: "repositoriesTable_id_backupSchedulesTable_id_via_backupScheduleMirrorsTable",
|
||||
}),
|
||||
backupSchedules: r.many.backupSchedulesTable({
|
||||
alias: "backupSchedulesTable_repositoryId_repositoriesTable_id",
|
||||
}),
|
||||
organization: r.one.organization({
|
||||
from: r.repositoriesTable.organizationId,
|
||||
to: r.organization.id,
|
||||
}),
|
||||
},
|
||||
backupScheduleMirrorsTable: {
|
||||
repository: r.one.repositoriesTable({
|
||||
from: r.backupScheduleMirrorsTable.repositoryId,
|
||||
to: r.repositoriesTable.id,
|
||||
optional: false,
|
||||
}),
|
||||
backupSchedule: r.one.backupSchedulesTable({
|
||||
from: r.backupScheduleMirrorsTable.scheduleId,
|
||||
to: r.backupSchedulesTable.id,
|
||||
optional: false,
|
||||
}),
|
||||
},
|
||||
backupSchedulesTable: {
|
||||
mirrors: r.many.repositoriesTable({
|
||||
alias: "repositoriesTable_id_backupSchedulesTable_id_via_backupScheduleMirrorsTable",
|
||||
}),
|
||||
notificationDestinationsTables: r.many.notificationDestinationsTable(),
|
||||
organization: r.one.organization({
|
||||
from: r.backupSchedulesTable.organizationId,
|
||||
to: r.organization.id,
|
||||
optional: false,
|
||||
}),
|
||||
repository: r.one.repositoriesTable({
|
||||
from: r.backupSchedulesTable.repositoryId,
|
||||
to: r.repositoriesTable.id,
|
||||
alias: "backupSchedulesTable_repositoryId_repositoriesTable_id",
|
||||
optional: false,
|
||||
}),
|
||||
volume: r.one.volumesTable({
|
||||
from: r.backupSchedulesTable.volumeId,
|
||||
to: r.volumesTable.id,
|
||||
optional: false,
|
||||
}),
|
||||
},
|
||||
notificationDestinationsTable: {
|
||||
backupSchedules: r.many.backupSchedulesTable({
|
||||
from: r.notificationDestinationsTable.id.through(r.backupScheduleNotificationsTable.destinationId),
|
||||
to: r.backupSchedulesTable.id.through(r.backupScheduleNotificationsTable.scheduleId),
|
||||
}),
|
||||
organization: r.one.organization({
|
||||
from: r.notificationDestinationsTable.organizationId,
|
||||
to: r.organization.id,
|
||||
}),
|
||||
},
|
||||
account: {
|
||||
user: r.one.usersTable({
|
||||
from: r.account.userId,
|
||||
to: r.usersTable.id,
|
||||
}),
|
||||
},
|
||||
usersTable: {
|
||||
accounts: r.many.account(),
|
||||
sessions: r.many.sessionsTable(),
|
||||
members: r.many.member(),
|
||||
twoFactors: r.many.twoFactor(),
|
||||
organizations: r.many.organization({
|
||||
from: r.usersTable.id.through(r.member.userId),
|
||||
to: r.organization.id.through(r.member.organizationId),
|
||||
alias: "usersTable_id_organization_id_via_member",
|
||||
}),
|
||||
},
|
||||
sessionsTable: {
|
||||
user: r.one.usersTable({
|
||||
from: r.sessionsTable.userId,
|
||||
to: r.usersTable.id,
|
||||
}),
|
||||
},
|
||||
twoFactor: {
|
||||
usersTable: r.one.usersTable({
|
||||
from: r.twoFactor.userId,
|
||||
to: r.usersTable.id,
|
||||
}),
|
||||
},
|
||||
organization: {
|
||||
users: r.many.usersTable({
|
||||
alias: "usersTable_id_organization_id_via_member",
|
||||
}),
|
||||
backupSchedules: r.many.backupSchedulesTable(),
|
||||
notificationDestinations: r.many.notificationDestinationsTable(),
|
||||
repositories: r.many.repositoriesTable(),
|
||||
volumes: r.many.volumesTable(),
|
||||
members: r.many.member(),
|
||||
invitations: r.many.invitation(),
|
||||
},
|
||||
volumesTable: {
|
||||
backupSchedules: r.many.backupSchedulesTable(),
|
||||
organization: r.one.organization({
|
||||
from: r.volumesTable.organizationId,
|
||||
to: r.organization.id,
|
||||
}),
|
||||
},
|
||||
member: {
|
||||
user: r.one.usersTable({
|
||||
from: r.member.userId,
|
||||
to: r.usersTable.id,
|
||||
optional: false,
|
||||
}),
|
||||
organization: r.one.organization({
|
||||
from: r.member.organizationId,
|
||||
to: r.organization.id,
|
||||
optional: false,
|
||||
}),
|
||||
},
|
||||
invitation: {
|
||||
organization: r.one.organization({
|
||||
from: r.invitation.organizationId,
|
||||
to: r.organization.id,
|
||||
optional: false,
|
||||
}),
|
||||
},
|
||||
backupScheduleNotificationsTable: {
|
||||
destination: r.one.notificationDestinationsTable({
|
||||
from: r.backupScheduleNotificationsTable.destinationId,
|
||||
to: r.notificationDestinationsTable.id,
|
||||
optional: false,
|
||||
}),
|
||||
backupSchedule: r.one.backupSchedulesTable({
|
||||
from: r.backupScheduleNotificationsTable.scheduleId,
|
||||
to: r.backupSchedulesTable.id,
|
||||
optional: false,
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { relations, sql } from "drizzle-orm";
|
||||
import { sql } from "drizzle-orm";
|
||||
import { index, int, integer, sqliteTable, text, real, primaryKey, unique, uniqueIndex } from "drizzle-orm/sqlite-core";
|
||||
import type {
|
||||
CompressionMode,
|
||||
|
|
@ -175,29 +175,33 @@ export const invitation = sqliteTable(
|
|||
/**
|
||||
* Volumes Table
|
||||
*/
|
||||
export const volumesTable = sqliteTable("volumes_table", {
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
shortId: text("short_id").notNull().unique(),
|
||||
name: text().notNull(),
|
||||
type: text().$type<BackendType>().notNull(),
|
||||
status: text().$type<BackendStatus>().notNull().default("unmounted"),
|
||||
lastError: text("last_error"),
|
||||
lastHealthCheck: integer("last_health_check", { mode: "number" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch() * 1000)`),
|
||||
createdAt: integer("created_at", { mode: "number" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch() * 1000)`),
|
||||
updatedAt: integer("updated_at", { mode: "number" })
|
||||
.notNull()
|
||||
.$onUpdate(() => Date.now())
|
||||
.default(sql`(unixepoch() * 1000)`),
|
||||
config: text("config", { mode: "json" }).$type<typeof volumeConfigSchema.inferOut>().notNull(),
|
||||
autoRemount: int("auto_remount", { mode: "boolean" }).notNull().default(true),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id, { onDelete: "cascade" }),
|
||||
}, (table) => [unique().on(table.name, table.organizationId)]);
|
||||
export const volumesTable = sqliteTable(
|
||||
"volumes_table",
|
||||
{
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
shortId: text("short_id").notNull().unique(),
|
||||
name: text().notNull(),
|
||||
type: text().$type<BackendType>().notNull(),
|
||||
status: text().$type<BackendStatus>().notNull().default("unmounted"),
|
||||
lastError: text("last_error"),
|
||||
lastHealthCheck: integer("last_health_check", { mode: "number" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch() * 1000)`),
|
||||
createdAt: integer("created_at", { mode: "number" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch() * 1000)`),
|
||||
updatedAt: integer("updated_at", { mode: "number" })
|
||||
.notNull()
|
||||
.$onUpdate(() => Date.now())
|
||||
.default(sql`(unixepoch() * 1000)`),
|
||||
config: text("config", { mode: "json" }).$type<typeof volumeConfigSchema.inferOut>().notNull(),
|
||||
autoRemount: int("auto_remount", { mode: "boolean" }).notNull().default(true),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id, { onDelete: "cascade" }),
|
||||
},
|
||||
(table) => [unique().on(table.name, table.organizationId)],
|
||||
);
|
||||
export type Volume = typeof volumesTable.$inferSelect;
|
||||
export type VolumeInsert = typeof volumesTable.$inferInsert;
|
||||
|
||||
|
|
@ -381,102 +385,3 @@ export const twoFactor = sqliteTable(
|
|||
},
|
||||
(table) => [index("twoFactor_secret_idx").on(table.secret), index("twoFactor_userId_idx").on(table.userId)],
|
||||
);
|
||||
|
||||
export const userRelations = relations(usersTable, ({ many }) => ({
|
||||
sessions: many(sessionsTable),
|
||||
accounts: many(account),
|
||||
members: many(member),
|
||||
invitations: many(invitation),
|
||||
twoFactors: many(twoFactor),
|
||||
}));
|
||||
|
||||
export const sessionRelations = relations(sessionsTable, ({ one }) => ({
|
||||
user: one(usersTable, {
|
||||
fields: [sessionsTable.userId],
|
||||
references: [usersTable.id],
|
||||
}),
|
||||
activeOrganization: one(organization, {
|
||||
fields: [sessionsTable.activeOrganizationId],
|
||||
references: [organization.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const accountRelations = relations(account, ({ one }) => ({
|
||||
user: one(usersTable, {
|
||||
fields: [account.userId],
|
||||
references: [usersTable.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const organizationRelations = relations(organization, ({ many }) => ({
|
||||
members: many(member),
|
||||
invitations: many(invitation),
|
||||
}));
|
||||
|
||||
export const memberRelations = relations(member, ({ one }) => ({
|
||||
organization: one(organization, {
|
||||
fields: [member.organizationId],
|
||||
references: [organization.id],
|
||||
}),
|
||||
usersTable: one(usersTable, {
|
||||
fields: [member.userId],
|
||||
references: [usersTable.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const invitationRelations = relations(invitation, ({ one }) => ({
|
||||
organization: one(organization, {
|
||||
fields: [invitation.organizationId],
|
||||
references: [organization.id],
|
||||
}),
|
||||
usersTable: one(usersTable, {
|
||||
fields: [invitation.inviterId],
|
||||
references: [usersTable.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const twoFactorRelations = relations(twoFactor, ({ one }) => ({
|
||||
usersTable: one(usersTable, {
|
||||
fields: [twoFactor.userId],
|
||||
references: [usersTable.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const backupScheduleMirrorRelations = relations(backupScheduleMirrorsTable, ({ one }) => ({
|
||||
schedule: one(backupSchedulesTable, {
|
||||
fields: [backupScheduleMirrorsTable.scheduleId],
|
||||
references: [backupSchedulesTable.id],
|
||||
}),
|
||||
repository: one(repositoriesTable, {
|
||||
fields: [backupScheduleMirrorsTable.repositoryId],
|
||||
references: [repositoriesTable.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const backupScheduleRelations = relations(backupSchedulesTable, ({ one, many }) => ({
|
||||
volume: one(volumesTable, {
|
||||
fields: [backupSchedulesTable.volumeId],
|
||||
references: [volumesTable.id],
|
||||
}),
|
||||
repository: one(repositoriesTable, {
|
||||
fields: [backupSchedulesTable.repositoryId],
|
||||
references: [repositoriesTable.id],
|
||||
}),
|
||||
notifications: many(backupScheduleNotificationsTable),
|
||||
mirrors: many(backupScheduleMirrorsTable),
|
||||
}));
|
||||
|
||||
export const notificationDestinationRelations = relations(notificationDestinationsTable, ({ many }) => ({
|
||||
schedules: many(backupScheduleNotificationsTable),
|
||||
}));
|
||||
|
||||
export const backupScheduleNotificationRelations = relations(backupScheduleNotificationsTable, ({ one }) => ({
|
||||
schedule: one(backupSchedulesTable, {
|
||||
fields: [backupScheduleNotificationsTable.scheduleId],
|
||||
references: [backupSchedulesTable.id],
|
||||
}),
|
||||
destination: one(notificationDestinationsTable, {
|
||||
fields: [backupScheduleNotificationsTable.destinationId],
|
||||
references: [notificationDestinationsTable.id],
|
||||
}),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ import { Job } from "../core/scheduler";
|
|||
import { volumeService } from "../modules/volumes/volume.service";
|
||||
import { logger } from "../utils/logger";
|
||||
import { db } from "../db/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { volumesTable } from "../db/schema";
|
||||
import { withContext } from "../core/request-context";
|
||||
|
||||
export class VolumeAutoRemountJob extends Job {
|
||||
|
|
@ -11,7 +9,7 @@ export class VolumeAutoRemountJob extends Job {
|
|||
logger.debug("Running auto-remount for all errored volumes...");
|
||||
|
||||
const volumes = await db.query.volumesTable.findMany({
|
||||
where: eq(volumesTable.status, "error"),
|
||||
where: { status: "error" },
|
||||
});
|
||||
|
||||
for (const volume of volumes) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ import { Job } from "../core/scheduler";
|
|||
import { volumeService } from "../modules/volumes/volume.service";
|
||||
import { logger } from "../utils/logger";
|
||||
import { db } from "../db/db";
|
||||
import { eq, or } from "drizzle-orm";
|
||||
import { volumesTable } from "../db/schema";
|
||||
import { withContext } from "../core/request-context";
|
||||
|
||||
export class VolumeHealthCheckJob extends Job {
|
||||
|
|
@ -11,7 +9,9 @@ export class VolumeHealthCheckJob extends Job {
|
|||
logger.debug("Running health check for all volumes...");
|
||||
|
||||
const volumes = await db.query.volumesTable.findMany({
|
||||
where: or(eq(volumesTable.status, "mounted"), eq(volumesTable.status, "error")),
|
||||
where: {
|
||||
OR: [{ status: "mounted" }, { status: "error" }],
|
||||
},
|
||||
});
|
||||
|
||||
for (const volume of volumes) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ import { Job } from "../core/scheduler";
|
|||
import { repositoriesService } from "../modules/repositories/repositories.service";
|
||||
import { logger } from "../utils/logger";
|
||||
import { db } from "../db/db";
|
||||
import { eq, or } from "drizzle-orm";
|
||||
import { repositoriesTable } from "../db/schema";
|
||||
import { withContext } from "../core/request-context";
|
||||
|
||||
export class RepositoryHealthCheckJob extends Job {
|
||||
|
|
@ -11,7 +9,7 @@ export class RepositoryHealthCheckJob extends Job {
|
|||
logger.debug("Running health check for all repositories...");
|
||||
|
||||
const repositories = await db.query.repositoriesTable.findMany({
|
||||
where: or(eq(repositoriesTable.status, "healthy"), eq(repositoriesTable.status, "error")),
|
||||
where: { OR: [{ status: "healthy" }, { status: "error" }] },
|
||||
});
|
||||
|
||||
for (const repository of repositories) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { createMiddleware } from "hono/factory";
|
||||
import { auth } from "~/lib/auth";
|
||||
import { db } from "~/server/db/db";
|
||||
import { member } from "~/server/db/schema";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { withContext } from "~/server/core/request-context";
|
||||
|
||||
declare module "hono" {
|
||||
|
|
@ -34,7 +32,9 @@ export const requireAuth = createMiddleware(async (c, next) => {
|
|||
}
|
||||
|
||||
const membership = await db.query.member.findFirst({
|
||||
where: and(eq(member.userId, user.id), eq(member.organizationId, activeOrganizationId)),
|
||||
where: {
|
||||
AND: [{ userId: user.id }, { organizationId: activeOrganizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!membership) {
|
||||
|
|
@ -58,7 +58,9 @@ export const requireOrgAdmin = createMiddleware(async (c, next) => {
|
|||
const organizationId = c.get("organizationId");
|
||||
|
||||
const membership = await db.query.member.findFirst({
|
||||
where: and(eq(member.userId, user.id), eq(member.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ userId: user.id }, { organizationId: organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!membership || (membership.role !== "owner" && membership.role !== "admin")) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ export class AuthService {
|
|||
*/
|
||||
async getUserDeletionImpact(userId: string): Promise<UserDeletionImpactDto> {
|
||||
const userMemberships = await db.query.member.findMany({
|
||||
where: and(eq(member.userId, userId), eq(member.role, "owner")),
|
||||
where: {
|
||||
AND: [{ userId: userId }, { role: "owner" }],
|
||||
},
|
||||
});
|
||||
|
||||
const impacts: UserDeletionImpactDto["organizations"] = [];
|
||||
|
|
@ -43,7 +45,7 @@ export class AuthService {
|
|||
|
||||
if (otherOwners[0].count === 0) {
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(organization.id, membership.organizationId),
|
||||
where: { id: membership.organizationId },
|
||||
});
|
||||
|
||||
if (org) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { verifyPassword } from "better-auth/crypto";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "~/server/db/db";
|
||||
import { account } from "~/server/db/schema";
|
||||
|
||||
type PasswordVerificationBody = {
|
||||
userId: string;
|
||||
|
|
@ -10,7 +8,7 @@ type PasswordVerificationBody = {
|
|||
|
||||
export const verifyUserPassword = async ({ password, userId }: PasswordVerificationBody) => {
|
||||
const userAccount = await db.query.account.findFirst({
|
||||
where: eq(account.userId, userId),
|
||||
where: { userId },
|
||||
});
|
||||
|
||||
if (!userAccount || !userAccount.password) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { and, asc, eq, isNull, ne, or } from "drizzle-orm";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import cron from "node-cron";
|
||||
import { CronExpressionParser } from "cron-parser";
|
||||
import { NotFoundError, BadRequestError, ConflictError } from "http-errors-enhanced";
|
||||
import { db } from "../../db/db";
|
||||
import { backupSchedulesTable, backupScheduleMirrorsTable, repositoriesTable, volumesTable } from "../../db/schema";
|
||||
import { backupSchedulesTable, backupScheduleMirrorsTable, repositoriesTable } from "../../db/schema";
|
||||
import { restic } from "../../utils/restic";
|
||||
import { logger } from "../../utils/logger";
|
||||
import { cache } from "../../utils/cache";
|
||||
|
|
@ -60,12 +60,9 @@ const processPattern = (pattern: string, volumePath: string) => {
|
|||
const listSchedules = async () => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedules = await db.query.backupSchedulesTable.findMany({
|
||||
where: eq(backupSchedulesTable.organizationId, organizationId),
|
||||
with: {
|
||||
volume: true,
|
||||
repository: true,
|
||||
},
|
||||
orderBy: [asc(backupSchedulesTable.sortOrder), asc(backupSchedulesTable.id)],
|
||||
where: { organizationId },
|
||||
with: { volume: true, repository: true },
|
||||
orderBy: { sortOrder: "asc", id: "asc" },
|
||||
});
|
||||
return schedules;
|
||||
};
|
||||
|
|
@ -73,11 +70,8 @@ const listSchedules = async () => {
|
|||
const getSchedule = async (scheduleId: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
with: {
|
||||
volume: true,
|
||||
repository: true,
|
||||
},
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
with: { volume: true, repository: true },
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -94,7 +88,9 @@ const createSchedule = async (data: CreateBackupScheduleBody) => {
|
|||
}
|
||||
|
||||
const existingName = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.name, data.name), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ name: data.name }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (existingName) {
|
||||
|
|
@ -102,7 +98,9 @@ const createSchedule = async (data: CreateBackupScheduleBody) => {
|
|||
}
|
||||
|
||||
const volume = await db.query.volumesTable.findFirst({
|
||||
where: and(eq(volumesTable.id, data.volumeId), eq(volumesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ id: data.volumeId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!volume) {
|
||||
|
|
@ -110,7 +108,9 @@ const createSchedule = async (data: CreateBackupScheduleBody) => {
|
|||
}
|
||||
|
||||
const repository = await db.query.repositoriesTable.findFirst({
|
||||
where: and(eq(repositoriesTable.id, data.repositoryId), eq(repositoriesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ id: data.repositoryId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!repository) {
|
||||
|
|
@ -148,7 +148,9 @@ const createSchedule = async (data: CreateBackupScheduleBody) => {
|
|||
const updateSchedule = async (scheduleId: number, data: UpdateBackupScheduleBody) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ id: scheduleId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -161,11 +163,9 @@ const updateSchedule = async (scheduleId: number, data: UpdateBackupScheduleBody
|
|||
|
||||
if (data.name) {
|
||||
const existingName = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(
|
||||
eq(backupSchedulesTable.name, data.name),
|
||||
ne(backupSchedulesTable.id, scheduleId),
|
||||
eq(backupSchedulesTable.organizationId, organizationId),
|
||||
),
|
||||
where: {
|
||||
AND: [{ name: data.name }, { NOT: { id: scheduleId } }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (existingName) {
|
||||
|
|
@ -174,7 +174,9 @@ const updateSchedule = async (scheduleId: number, data: UpdateBackupScheduleBody
|
|||
}
|
||||
|
||||
const repository = await db.query.repositoriesTable.findFirst({
|
||||
where: and(eq(repositoriesTable.id, data.repositoryId), eq(repositoriesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ id: data.repositoryId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!repository) {
|
||||
|
|
@ -200,7 +202,9 @@ const updateSchedule = async (scheduleId: number, data: UpdateBackupScheduleBody
|
|||
const deleteSchedule = async (scheduleId: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ id: scheduleId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -215,7 +219,7 @@ const deleteSchedule = async (scheduleId: number) => {
|
|||
const executeBackup = async (scheduleId: number, manual = false) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -233,7 +237,7 @@ const executeBackup = async (scheduleId: number, manual = false) => {
|
|||
}
|
||||
|
||||
const volume = await db.query.volumesTable.findFirst({
|
||||
where: and(eq(volumesTable.id, schedule.volumeId), eq(volumesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: schedule.volumeId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!volume) {
|
||||
|
|
@ -241,7 +245,7 @@ const executeBackup = async (scheduleId: number, manual = false) => {
|
|||
}
|
||||
|
||||
const repository = await db.query.repositoriesTable.findFirst({
|
||||
where: and(eq(repositoriesTable.id, schedule.repositoryId), eq(repositoriesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: schedule.repositoryId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!repository) {
|
||||
|
|
@ -436,11 +440,9 @@ const getSchedulesToExecute = async () => {
|
|||
const organizationId = getOrganizationId();
|
||||
const now = Date.now();
|
||||
const schedules = await db.query.backupSchedulesTable.findMany({
|
||||
where: and(
|
||||
eq(backupSchedulesTable.enabled, true),
|
||||
or(ne(backupSchedulesTable.lastBackupStatus, "in_progress"), isNull(backupSchedulesTable.lastBackupStatus)),
|
||||
eq(backupSchedulesTable.organizationId, organizationId),
|
||||
),
|
||||
where: {
|
||||
AND: [{ enabled: true }, { lastBackupStatus: { NOT: "in_progress" } }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
const schedulesToRun: number[] = [];
|
||||
|
|
@ -457,7 +459,7 @@ const getSchedulesToExecute = async () => {
|
|||
const getScheduleForVolume = async (volumeId: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.volumeId, volumeId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ volumeId }, { organizationId }] },
|
||||
with: { volume: true, repository: true },
|
||||
});
|
||||
|
||||
|
|
@ -467,7 +469,7 @@ const getScheduleForVolume = async (volumeId: number) => {
|
|||
const stopBackup = async (scheduleId: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -498,7 +500,9 @@ const stopBackup = async (scheduleId: number) => {
|
|||
const runForget = async (scheduleId: number, repositoryId?: string) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ id: scheduleId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -510,10 +514,9 @@ const runForget = async (scheduleId: number, repositoryId?: string) => {
|
|||
}
|
||||
|
||||
const repository = await db.query.repositoriesTable.findFirst({
|
||||
where: and(
|
||||
eq(repositoriesTable.id, repositoryId ?? schedule.repositoryId),
|
||||
eq(repositoriesTable.organizationId, organizationId),
|
||||
),
|
||||
where: {
|
||||
AND: [{ id: repositoryId ?? schedule.repositoryId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!repository) {
|
||||
|
|
@ -535,7 +538,9 @@ const runForget = async (scheduleId: number, repositoryId?: string) => {
|
|||
const getMirrors = async (scheduleId: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: {
|
||||
AND: [{ id: scheduleId }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -543,7 +548,9 @@ const getMirrors = async (scheduleId: number) => {
|
|||
}
|
||||
|
||||
const mirrors = await db.query.backupScheduleMirrorsTable.findMany({
|
||||
where: eq(backupScheduleMirrorsTable.scheduleId, scheduleId),
|
||||
where: {
|
||||
scheduleId,
|
||||
},
|
||||
with: { repository: true },
|
||||
});
|
||||
|
||||
|
|
@ -553,7 +560,7 @@ const getMirrors = async (scheduleId: number) => {
|
|||
const updateMirrors = async (scheduleId: number, data: UpdateScheduleMirrorsBody) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
with: { repository: true },
|
||||
});
|
||||
|
||||
|
|
@ -567,7 +574,7 @@ const updateMirrors = async (scheduleId: number, data: UpdateScheduleMirrorsBody
|
|||
}
|
||||
|
||||
const repo = await db.query.repositoriesTable.findFirst({
|
||||
where: and(eq(repositoriesTable.id, mirror.repositoryId), eq(repositoriesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: mirror.repositoryId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!repo) {
|
||||
|
|
@ -584,7 +591,7 @@ const updateMirrors = async (scheduleId: number, data: UpdateScheduleMirrorsBody
|
|||
}
|
||||
|
||||
const existingMirrors = await db.query.backupScheduleMirrorsTable.findMany({
|
||||
where: eq(backupScheduleMirrorsTable.scheduleId, scheduleId),
|
||||
where: { scheduleId },
|
||||
});
|
||||
|
||||
const existingMirrorsMap = new Map(
|
||||
|
|
@ -622,7 +629,7 @@ const copyToMirrors = async (
|
|||
) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -630,7 +637,7 @@ const copyToMirrors = async (
|
|||
}
|
||||
|
||||
const mirrors = await db.query.backupScheduleMirrorsTable.findMany({
|
||||
where: eq(backupScheduleMirrorsTable.scheduleId, scheduleId),
|
||||
where: { scheduleId },
|
||||
with: { repository: true },
|
||||
});
|
||||
|
||||
|
|
@ -712,7 +719,7 @@ const copyToMirrors = async (
|
|||
const getMirrorCompatibility = async (scheduleId: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
with: { repository: true },
|
||||
});
|
||||
|
||||
|
|
@ -720,9 +727,7 @@ const getMirrorCompatibility = async (scheduleId: number) => {
|
|||
throw new NotFoundError("Backup schedule not found");
|
||||
}
|
||||
|
||||
const allRepositories = await db.query.repositoriesTable.findMany({
|
||||
where: eq(repositoriesTable.organizationId, organizationId),
|
||||
});
|
||||
const allRepositories = await db.query.repositoriesTable.findMany({ where: { organizationId } });
|
||||
const repos = allRepositories.filter((repo) => repo.id !== schedule.repositoryId);
|
||||
|
||||
const compatibility = await Promise.all(
|
||||
|
|
@ -740,7 +745,7 @@ const reorderSchedules = async (scheduleIds: number[]) => {
|
|||
}
|
||||
|
||||
const existingSchedules = await db.query.backupSchedulesTable.findMany({
|
||||
where: eq(backupSchedulesTable.organizationId, organizationId),
|
||||
where: { organizationId },
|
||||
columns: { id: true },
|
||||
});
|
||||
const existingIds = new Set(existingSchedules.map((s) => s.id));
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { v00001 } from "./migrations/00001-retag-snapshots";
|
|||
import { v00002 } from "./migrations/00002-isolate-restic-passwords";
|
||||
import { v00003 } from "./migrations/00003-assign-organization";
|
||||
import { sql } from "drizzle-orm";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { appMetadataTable, usersTable } from "../../db/schema";
|
||||
import { db } from "../../db/db";
|
||||
|
||||
|
|
@ -26,9 +25,7 @@ const recordMigrationCheckpoint = async (version: string): Promise<void> => {
|
|||
|
||||
const hasMigrationCheckpoint = async (id: string): Promise<boolean> => {
|
||||
const key = `${MIGRATION_KEY_PREFIX}${id}`;
|
||||
const result = await db.query.appMetadataTable.findFirst({
|
||||
where: eq(appMetadataTable.key, key),
|
||||
});
|
||||
const result = await db.query.appMetadataTable.findFirst({ where: { key } });
|
||||
return result !== undefined;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../../../db/db";
|
||||
import { backupScheduleMirrorsTable, repositoriesTable, type Repository } from "../../../db/schema";
|
||||
import { backupScheduleMirrorsTable, type Repository } from "../../../db/schema";
|
||||
import { logger } from "../../../utils/logger";
|
||||
import { toMessage } from "~/server/utils/errors";
|
||||
import { exec } from "~/server/utils/spawn";
|
||||
|
|
@ -42,7 +42,7 @@ const execute = async () => {
|
|||
const newTag = schedule.shortId;
|
||||
|
||||
const repository = await db.query.repositoriesTable.findFirst({
|
||||
where: eq(repositoriesTable.id, schedule.repositoryId),
|
||||
where: { id: schedule.repositoryId },
|
||||
});
|
||||
|
||||
if (!repository) {
|
||||
|
|
@ -63,7 +63,7 @@ const execute = async () => {
|
|||
|
||||
for (const mirror of mirrors) {
|
||||
const mirrorRepo = await db.query.repositoriesTable.findFirst({
|
||||
where: eq(repositoriesTable.id, mirror.repositoryId),
|
||||
where: { id: mirror.repositoryId },
|
||||
});
|
||||
|
||||
if (!mirrorRepo) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../../../db/db";
|
||||
import { member, usersTable } from "../../../db/schema";
|
||||
import { member } from "../../../db/schema";
|
||||
import { logger } from "../../../utils/logger";
|
||||
import { toMessage } from "~/server/utils/errors";
|
||||
|
||||
|
|
@ -8,7 +7,9 @@ const execute = async () => {
|
|||
const errors: Array<{ name: string; error: string }> = [];
|
||||
|
||||
try {
|
||||
const allUsers = await db.query.usersTable.findMany({ where: eq(usersTable.role, "admin") });
|
||||
const allUsers = await db.query.usersTable.findMany({
|
||||
where: { role: "admin" },
|
||||
});
|
||||
const allOrganizations = await db.query.organization.findMany({});
|
||||
|
||||
if (allUsers.length === 0) {
|
||||
|
|
@ -35,7 +36,7 @@ const execute = async () => {
|
|||
const org = allOrganizations[0];
|
||||
|
||||
const existingMembers = await db.query.member.findMany({
|
||||
where: (memberTable, { eq }) => eq(memberTable.userId, user.id),
|
||||
where: { userId: user.id },
|
||||
});
|
||||
|
||||
if (existingMembers.length > 0) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { Scheduler } from "../../core/scheduler";
|
||||
import { eq, or } from "drizzle-orm";
|
||||
import { db } from "../../db/db";
|
||||
import { volumesTable } from "../../db/schema";
|
||||
import { logger } from "../../utils/logger";
|
||||
import { createVolumeBackend } from "../backends/backend";
|
||||
|
||||
|
|
@ -9,7 +7,7 @@ export const shutdown = async () => {
|
|||
await Scheduler.stop();
|
||||
|
||||
const volumes = await db.query.volumesTable.findMany({
|
||||
where: or(eq(volumesTable.status, "mounted")),
|
||||
where: { status: "mounted" },
|
||||
});
|
||||
|
||||
for (const volume of volumes) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Scheduler } from "../../core/scheduler";
|
||||
import { and, eq, or } from "drizzle-orm";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../../db/db";
|
||||
import { backupSchedulesTable, volumesTable } from "../../db/schema";
|
||||
import { backupSchedulesTable } from "../../db/schema";
|
||||
import { logger } from "../../utils/logger";
|
||||
import { volumeService } from "../volumes/volume.service";
|
||||
import { CleanupDanglingMountsJob } from "../../jobs/cleanup-dangling";
|
||||
|
|
@ -62,10 +62,14 @@ export const startup = async () => {
|
|||
await ensureLatestConfigurationSchema();
|
||||
|
||||
const volumes = await db.query.volumesTable.findMany({
|
||||
where: or(
|
||||
eq(volumesTable.status, "mounted"),
|
||||
and(eq(volumesTable.autoRemount, true), eq(volumesTable.status, "error")),
|
||||
),
|
||||
where: {
|
||||
OR: [
|
||||
{ status: "mounted" },
|
||||
{
|
||||
AND: [{ autoRemount: true }, { status: "error" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
for (const volume of volumes) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { eq, and, inArray } from "drizzle-orm";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { BadRequestError, ConflictError, InternalServerError, NotFoundError } from "http-errors-enhanced";
|
||||
import { db } from "../../db/db";
|
||||
import {
|
||||
notificationDestinationsTable,
|
||||
backupScheduleNotificationsTable,
|
||||
backupSchedulesTable,
|
||||
type NotificationDestination,
|
||||
} from "../../db/schema";
|
||||
import { cryptoUtils } from "../../utils/crypto";
|
||||
|
|
@ -19,8 +18,8 @@ import { getOrganizationId } from "~/server/core/request-context";
|
|||
const listDestinations = async () => {
|
||||
const organizationId = getOrganizationId();
|
||||
const destinations = await db.query.notificationDestinationsTable.findMany({
|
||||
where: eq(notificationDestinationsTable.organizationId, organizationId),
|
||||
orderBy: (destinations, { asc }) => [asc(destinations.name)],
|
||||
where: { organizationId },
|
||||
orderBy: { name: "asc" },
|
||||
});
|
||||
return destinations;
|
||||
};
|
||||
|
|
@ -28,10 +27,7 @@ const listDestinations = async () => {
|
|||
const getDestination = async (id: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const destination = await db.query.notificationDestinationsTable.findFirst({
|
||||
where: and(
|
||||
eq(notificationDestinationsTable.id, id),
|
||||
eq(notificationDestinationsTable.organizationId, organizationId),
|
||||
),
|
||||
where: { AND: [{ id }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!destination) {
|
||||
|
|
@ -256,7 +252,7 @@ const testDestination = async (id: number) => {
|
|||
const getScheduleNotifications = async (scheduleId: number) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -264,7 +260,7 @@ const getScheduleNotifications = async (scheduleId: number) => {
|
|||
}
|
||||
|
||||
const assignments = await db.query.backupScheduleNotificationsTable.findMany({
|
||||
where: eq(backupScheduleNotificationsTable.scheduleId, scheduleId),
|
||||
where: { scheduleId },
|
||||
with: {
|
||||
destination: true,
|
||||
},
|
||||
|
|
@ -285,7 +281,7 @@ const updateScheduleNotifications = async (
|
|||
) => {
|
||||
const organizationId = getOrganizationId();
|
||||
const schedule = await db.query.backupSchedulesTable.findFirst({
|
||||
where: and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId)),
|
||||
where: { AND: [{ id: scheduleId }, { organizationId }] },
|
||||
});
|
||||
|
||||
if (!schedule) {
|
||||
|
|
@ -295,10 +291,9 @@ const updateScheduleNotifications = async (
|
|||
const destinationIds = [...new Set(assignments.map((a) => a.destinationId))];
|
||||
if (destinationIds.length > 0) {
|
||||
const destinations = await db.query.notificationDestinationsTable.findMany({
|
||||
where: and(
|
||||
inArray(notificationDestinationsTable.id, destinationIds),
|
||||
eq(notificationDestinationsTable.organizationId, organizationId),
|
||||
),
|
||||
where: {
|
||||
AND: [{ id: { in: destinationIds } }, { organizationId }],
|
||||
},
|
||||
});
|
||||
|
||||
if (destinations.length !== destinationIds.length) {
|
||||
|
|
@ -338,7 +333,7 @@ const sendBackupNotification = async (
|
|||
const organizationId = getOrganizationId();
|
||||
|
||||
const assignments = await db.query.backupScheduleNotificationsTable.findMany({
|
||||
where: eq(backupScheduleNotificationsTable.scheduleId, scheduleId),
|
||||
where: { scheduleId },
|
||||
with: {
|
||||
destination: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import crypto from "node:crypto";
|
||||
import { and, eq, or } from "drizzle-orm";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { ConflictError, InternalServerError, NotFoundError } from "http-errors-enhanced";
|
||||
import { db } from "../../db/db";
|
||||
import { repositoriesTable } from "../../db/schema";
|
||||
|
|
@ -26,18 +26,15 @@ const runningDoctors = new Map<string, AbortController>();
|
|||
const findRepository = async (idOrShortId: string) => {
|
||||
const organizationId = getOrganizationId();
|
||||
return await db.query.repositoriesTable.findFirst({
|
||||
where: and(
|
||||
or(eq(repositoriesTable.id, idOrShortId), eq(repositoriesTable.shortId, idOrShortId)),
|
||||
eq(repositoriesTable.organizationId, organizationId),
|
||||
),
|
||||
where: {
|
||||
AND: [{ OR: [{ id: idOrShortId }, { shortId: idOrShortId }] }, { organizationId }],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const listRepositories = async () => {
|
||||
const organizationId = getOrganizationId();
|
||||
const repositories = await db.query.repositoriesTable.findMany({
|
||||
where: eq(repositoriesTable.organizationId, organizationId),
|
||||
});
|
||||
const repositories = await db.query.repositoriesTable.findMany({ where: { organizationId } });
|
||||
return repositories;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
import { systemService } from "./system.service";
|
||||
import { requireAuth, requireOrgAdmin } from "../auth/auth.middleware";
|
||||
import { db } from "../../db/db";
|
||||
import { organization, usersTable } from "../../db/schema";
|
||||
import { usersTable } from "../../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { verifyUserPassword } from "../auth/helpers";
|
||||
import { cryptoUtils } from "../../utils/crypto";
|
||||
|
|
@ -78,9 +78,7 @@ export const systemController = new Hono()
|
|||
}
|
||||
|
||||
try {
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(organization.id, organizationId),
|
||||
});
|
||||
const org = await db.query.organization.findFirst({ where: { id: organizationId } });
|
||||
|
||||
if (!org?.metadata?.resticPassword) {
|
||||
return c.json({ message: "Organization Restic password not found" }, 404);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { cache } from "../../utils/cache";
|
|||
import { logger } from "~/server/utils/logger";
|
||||
import { db } from "../../db/db";
|
||||
import { appMetadataTable } from "../../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { REGISTRATION_ENABLED_KEY } from "~/client/lib/constants";
|
||||
|
||||
const CACHE_TTL = 60 * 60;
|
||||
|
|
@ -91,7 +90,7 @@ const getUpdates = async (): Promise<UpdateInfoDto> => {
|
|||
|
||||
const isRegistrationEnabled = async () => {
|
||||
const result = await db.query.appMetadataTable.findFirst({
|
||||
where: eq(appMetadataTable.key, REGISTRATION_ENABLED_KEY),
|
||||
where: { key: REGISTRATION_ENABLED_KEY },
|
||||
});
|
||||
|
||||
return result?.value === "true";
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ async function encryptSensitiveFields(config: BackendConfig): Promise<BackendCon
|
|||
const listVolumes = async () => {
|
||||
const organizationId = getOrganizationId();
|
||||
const volumes = await db.query.volumesTable.findMany({
|
||||
where: eq(volumesTable.organizationId, organizationId),
|
||||
where: { organizationId: organizationId },
|
||||
});
|
||||
|
||||
return volumes;
|
||||
|
|
@ -56,10 +56,12 @@ const findVolume = async (idOrShortId: string | number) => {
|
|||
const organizationId = getOrganizationId();
|
||||
const isNumeric = typeof idOrShortId === "number" || /^\d+$/.test(String(idOrShortId));
|
||||
return await db.query.volumesTable.findFirst({
|
||||
where: and(
|
||||
isNumeric ? eq(volumesTable.id, Number(idOrShortId)) : eq(volumesTable.shortId, idOrShortId),
|
||||
eq(volumesTable.organizationId, organizationId),
|
||||
),
|
||||
where: {
|
||||
AND: [
|
||||
isNumeric ? { id: Number(idOrShortId) } : { shortId: String(idOrShortId) },
|
||||
{ organizationId: organizationId },
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import path from "node:path";
|
|||
import os from "node:os";
|
||||
import { throttle } from "es-toolkit";
|
||||
import { type } from "arktype";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { REPOSITORY_BASE, RESTIC_PASS_FILE, DEFAULT_EXCLUDES, RESTIC_CACHE_DIR } from "../core/constants";
|
||||
import { config as appConfig } from "../core/config";
|
||||
import { logger } from "./logger";
|
||||
|
|
@ -14,7 +13,6 @@ import { safeSpawn, exec } from "./spawn";
|
|||
import type { CompressionMode, RepositoryConfig, OverwriteMode, BandwidthLimit } from "~/schemas/restic";
|
||||
import { ResticError } from "./errors";
|
||||
import { db } from "../db/db";
|
||||
import { organization } from "../db/schema";
|
||||
|
||||
const backupOutputSchema = type({
|
||||
message_type: "'summary'",
|
||||
|
|
@ -110,9 +108,7 @@ export const buildEnv = async (config: RepositoryConfig, organizationId: string)
|
|||
await fs.writeFile(passwordFilePath, decryptedPassword, { mode: 0o600 });
|
||||
env.RESTIC_PASSWORD_FILE = passwordFilePath;
|
||||
} else {
|
||||
const org = await db.query.organization.findFirst({
|
||||
where: eq(organization.id, organizationId),
|
||||
});
|
||||
const org = await db.query.organization.findFirst({ where: { id: organizationId } });
|
||||
|
||||
if (!org) {
|
||||
throw new Error(`Organization ${organizationId} not found`);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export const createTestOrganization = async (overrides: Partial<typeof organizat
|
|||
};
|
||||
|
||||
const existing = await db.query.organization.findFirst({
|
||||
where: (o, { eq }) => eq(o.id, org.id ?? TEST_ORG_ID),
|
||||
where: { id: org.id },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import { createClient } from "@libsql/client";
|
|||
import { drizzle } from "drizzle-orm/libsql";
|
||||
import path from "node:path";
|
||||
import { DATABASE_URL } from "~/server/core/constants";
|
||||
import * as schema from "~/server/db/schema";
|
||||
import { relations } from "~/server/db/relations";
|
||||
|
||||
const sqlite = createClient({ url: `file:${path.join(process.cwd(), "playwright", DATABASE_URL)}` });
|
||||
|
||||
export const db = drizzle({ client: sqlite, schema: schema });
|
||||
export const db = drizzle({ client: sqlite, relations: relations });
|
||||
|
||||
export const resetDatabase = async () => {
|
||||
const cursor = await sqlite.execute("SELECT name FROM sqlite_master WHERE type='table'");
|
||||
|
|
|
|||
Loading…
Reference in a new issue