mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
feat: Working version with google drive storage.
This commit is contained in:
@@ -1,16 +1,12 @@
|
||||
import {NextResponse} from "next/server";
|
||||
import {Body} from "./route";
|
||||
import {isUuidv4} from "@/utils/verify-uuid";
|
||||
import {getFileUrlPresignedLocal, getFileUrlPreSignedS3Action} from "@/features/upload/private/upload.action";
|
||||
import {Agent} from "@/db/schema/08_agent";
|
||||
import {Database} from "@/db/schema/07_database";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {db as dbClient} from "@/db";
|
||||
import {and, eq, inArray} from "drizzle-orm";
|
||||
import {dbmsEnumSchema, EDbmsSchema} from "@/db/schema/types";
|
||||
import {ServerActionResult} from "@/types/action-type";
|
||||
import {SafeActionResult} from "next-safe-action";
|
||||
import {ZodString} from "zod";
|
||||
import {withUpdatedAt} from "@/db/utils";
|
||||
import type {StorageInput} from "@/features/storages/types";
|
||||
import {dispatchStorage} from "@/features/storages/dispatch";
|
||||
@@ -83,10 +79,6 @@ export async function handleDatabases(body: Body, agent: Agent, lastContact: Dat
|
||||
.returning();
|
||||
|
||||
|
||||
// const backup = await dbClient.query.backup.findFirst({
|
||||
// where: and(eq(drizzleDb.schemas.backup.databaseId, databaseUpdated.id), eq(drizzleDb.schemas.backup.status, "waiting"))
|
||||
// })
|
||||
|
||||
const activeBackup = await dbClient.query.backup.findFirst({
|
||||
where: and(
|
||||
eq(drizzleDb.schemas.backup.databaseId, databaseUpdated.id),
|
||||
@@ -116,25 +108,6 @@ export async function handleDatabases(body: Body, agent: Agent, lastContact: Dat
|
||||
restoreAction = true
|
||||
|
||||
|
||||
// const backupToRestore = await dbClient.query.backup.findFirst({
|
||||
// where: eq(drizzleDb.schemas.backup.id, restoration.backupId),
|
||||
// with: {
|
||||
// database: {
|
||||
// with: {
|
||||
// project: true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
// const [settings] = await dbClient.select().from(drizzleDb.schemas.setting).where(eq(drizzleDb.schemas.setting.name, "system")).limit(1);
|
||||
// if (!settings) {
|
||||
// return NextResponse.json(
|
||||
// {error: "Unable to find settings"},
|
||||
// {status: 500}
|
||||
// );
|
||||
// }
|
||||
|
||||
if (!restoration.backupStorage || restoration.backupStorage.status != "success" || !restoration.backupStorage.path) {
|
||||
restoreAction = false
|
||||
continue;
|
||||
@@ -147,6 +120,10 @@ export async function handleDatabases(body: Body, agent: Agent, lastContact: Dat
|
||||
path: restoration.backupStorage.path,
|
||||
signedUrl: true,
|
||||
},
|
||||
metadata: {
|
||||
storageId: restoration.backupStorage.storageChannelId,
|
||||
fileKind: "backups"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import {NextResponse} from "next/server";
|
||||
import path from "path";
|
||||
import {db} from "@/db";
|
||||
import {eq} from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
import type {StorageInput} from "@/features/storages/types";
|
||||
import {dispatchStorage} from "@/features/storages/dispatch";
|
||||
import {Readable} from "node:stream";
|
||||
@@ -15,17 +12,10 @@ export async function GET(
|
||||
const token = searchParams.get('token');
|
||||
const expires = searchParams.get('expires');
|
||||
const pathFromUrl = searchParams.get('path');
|
||||
const storageId = searchParams.get('storageId');
|
||||
|
||||
if (!pathFromUrl) {
|
||||
return NextResponse.json({error: "Missing file path in search params"}, {status: 404})
|
||||
}
|
||||
|
||||
const localStorageChannel = await db.query.storageChannel.findFirst({
|
||||
where: eq(drizzleDb.schemas.storageChannel.provider, "local"),
|
||||
})
|
||||
|
||||
if (!localStorageChannel) {
|
||||
return NextResponse.json({error: "No local storage channel found"})
|
||||
if (!pathFromUrl || !storageId) {
|
||||
return NextResponse.json({error: "Missing search params"}, {status: 404})
|
||||
}
|
||||
|
||||
const input: StorageInput = {
|
||||
@@ -34,14 +24,18 @@ export async function GET(
|
||||
path: pathFromUrl,
|
||||
signedUrl: true,
|
||||
},
|
||||
metadata: {
|
||||
storageId: storageId,
|
||||
fileKind: "backups",
|
||||
}
|
||||
};
|
||||
|
||||
console.debug(input);
|
||||
|
||||
const result = await dispatchStorage(input, undefined, localStorageChannel.id);
|
||||
const result = await dispatchStorage(input, undefined, storageId);
|
||||
|
||||
if (!result.success) {
|
||||
return NextResponse.json({error: "Enable to get file from local storage channel, an error occurred !"})
|
||||
return NextResponse.json({error: "Enable to get file from privided storage channel, an error occurred !"})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import {NextResponse} from "next/server";
|
||||
import {auth} from "@/lib/auth/auth";
|
||||
import {headers} from "next/headers";
|
||||
import {checkFileExistsInBucket, getObjectFromClient} from "@/utils/s3-file-management";
|
||||
import {env} from "@/env.mjs";
|
||||
import * as stream from "node:stream";
|
||||
import path from "path";
|
||||
import {db} from "@/db";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {eq} from "drizzle-orm";
|
||||
@@ -16,28 +12,34 @@ export async function GET(
|
||||
req: Request,
|
||||
{params}: { params: Promise<{ fileName: string }> }
|
||||
) {
|
||||
|
||||
|
||||
const {searchParams} = new URL(req.url);
|
||||
const fileName = (await params).fileName;
|
||||
|
||||
const storageId = searchParams.get('storageId');
|
||||
|
||||
if (!fileName) return NextResponse.json({error: "Missing file parameter"}, {status: 400});
|
||||
|
||||
const session = await auth.api.getSession({headers: await headers()});
|
||||
if (!session) return NextResponse.json({error: "Unauthorized"}, {status: 403});
|
||||
|
||||
const settings = await db.query.setting.findFirst({
|
||||
where: eq(drizzleDb.schemas.setting.name, "system"),
|
||||
with: {
|
||||
storageChannel: true
|
||||
}
|
||||
});
|
||||
|
||||
if (!settings || !settings.storageChannel) {
|
||||
return NextResponse.json({error: "Unable to get settings or no default storage channel"});
|
||||
if (!storageId) {
|
||||
return NextResponse.json({error: "Missing storageId in search params"}, {status: 404})
|
||||
}
|
||||
|
||||
|
||||
|
||||
// const settings = await db.query.setting.findFirst({
|
||||
// where: eq(drizzleDb.schemas.setting.name, "system"),
|
||||
// with: {
|
||||
// storageChannel: true
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// if (!settings || !settings.storageChannel) {
|
||||
// return NextResponse.json({error: "Unable to get settings or no default storage channel"});
|
||||
// }
|
||||
|
||||
|
||||
const ext = fileName.split(".").pop()?.toLowerCase();
|
||||
const contentType =
|
||||
ext === "png"
|
||||
@@ -58,10 +60,14 @@ export async function GET(
|
||||
action: "get",
|
||||
data: {
|
||||
path: path,
|
||||
},
|
||||
metadata: {
|
||||
storageId: storageId,
|
||||
fileKind: "images"
|
||||
}
|
||||
}
|
||||
|
||||
const result = await dispatchStorage(input, undefined, settings.storageChannel.id);
|
||||
const result = await dispatchStorage(input, undefined, storageId);
|
||||
|
||||
if (!result.file || !Buffer.isBuffer(result.file)) {
|
||||
console.error(`An error occurred while getting file :`, result);
|
||||
@@ -1,31 +1,23 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { google } from "googleapis";
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const code = url.searchParams.get("code");
|
||||
const clientId = url.searchParams.get("clientId");
|
||||
const clientSecret = url.searchParams.get("clientSecret");
|
||||
const redirectUri = url.searchParams.get("redirectUri");
|
||||
const url = new URL(request.url);
|
||||
const code = url.searchParams.get("code");
|
||||
|
||||
if (!code || !clientId || !clientSecret || !redirectUri) {
|
||||
return NextResponse.json({ error: "Missing parameters" }, { status: 400 });
|
||||
const success = Boolean(code);
|
||||
|
||||
return new Response(
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>${success ? "Success" : "Failed"}</h1>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
{
|
||||
status: success ? 200 : 400,
|
||||
headers: {
|
||||
"Content-Type": "text/html; charset=utf-8",
|
||||
},
|
||||
}
|
||||
|
||||
try {
|
||||
const oauth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);
|
||||
const { tokens } = await oauth2Client.getToken(code);
|
||||
|
||||
// Save tokens.refresh_token securely in your DB here
|
||||
|
||||
return NextResponse.json(tokens);
|
||||
} catch (err: any) {
|
||||
console.error("Error exchanging code:", err);
|
||||
return NextResponse.json({ error: "Failed to exchange code" }, { status: 500 });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in GET handler:", error);
|
||||
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user