mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
feat: adding storage system ping method in order to test.
This commit is contained in:
@@ -3,7 +3,7 @@ import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/
|
|||||||
import {Metadata} from "next";
|
import {Metadata} from "next";
|
||||||
import {ChannelsSection} from "@/components/wrappers/dashboard/admin/channels/channels-section";
|
import {ChannelsSection} from "@/components/wrappers/dashboard/admin/channels/channels-section";
|
||||||
import {db} from "@/db";
|
import {db} from "@/db";
|
||||||
import {desc, eq, isNotNull, isNull, not} from "drizzle-orm";
|
import {desc, eq, isNull} from "drizzle-orm";
|
||||||
import * as drizzleDb from "@/db";
|
import * as drizzleDb from "@/db";
|
||||||
import {StorageChannelWith} from "@/db/schema/12_storage-channel";
|
import {StorageChannelWith} from "@/db/schema/12_storage-channel";
|
||||||
import {ChannelAddEditModal} from "@/components/wrappers/dashboard/admin/channels/channel/channel-add-edit-modal";
|
import {ChannelAddEditModal} from "@/components/wrappers/dashboard/admin/channels/channel/channel-add-edit-modal";
|
||||||
|
|||||||
+14
-3
@@ -10,6 +10,8 @@ import {useIsMobile} from "@/hooks/use-mobile";
|
|||||||
import {cn} from "@/lib/utils";
|
import {cn} from "@/lib/utils";
|
||||||
import {StorageChannel} from "@/db/schema/12_storage-channel";
|
import {StorageChannel} from "@/db/schema/12_storage-channel";
|
||||||
import {ChannelKind, getChannelTextBasedOnKind} from "@/components/wrappers/dashboard/admin/channels/helpers/common";
|
import {ChannelKind, getChannelTextBasedOnKind} from "@/components/wrappers/dashboard/admin/channels/helpers/common";
|
||||||
|
import type {StorageInput} from "@/features/storages/types";
|
||||||
|
import {dispatchStorage} from "@/features/storages/dispatch";
|
||||||
|
|
||||||
type NotifierTestChannelButtonProps = {
|
type NotifierTestChannelButtonProps = {
|
||||||
channel: NotificationChannel | StorageChannel;
|
channel: NotificationChannel | StorageChannel;
|
||||||
@@ -19,7 +21,6 @@ type NotifierTestChannelButtonProps = {
|
|||||||
|
|
||||||
export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestChannelButtonProps) => {
|
export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestChannelButtonProps) => {
|
||||||
const channelText = getChannelTextBasedOnKind(kind)
|
const channelText = getChannelTextBasedOnKind(kind)
|
||||||
|
|
||||||
const isMobile = useIsMobile()
|
const isMobile = useIsMobile()
|
||||||
const mutation = useMutation({
|
const mutation = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
@@ -34,7 +35,18 @@ export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestC
|
|||||||
if (result.success) {
|
if (result.success) {
|
||||||
toast.success(result.message);
|
toast.success(result.message);
|
||||||
} else {
|
} else {
|
||||||
toast.error("An error occurred while testing the notification channel");
|
toast.error("An error occurred while testing the notification channel, check your configuration");
|
||||||
|
}
|
||||||
|
} else if (kind === "storage") {
|
||||||
|
const input: StorageInput = {
|
||||||
|
action: "ping",
|
||||||
|
};
|
||||||
|
const result = await dispatchStorage(input, undefined, channel.id);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
toast.success("Successfully connected to storage channel");
|
||||||
|
} else {
|
||||||
|
toast.error("An error occurred while testing the storage channel, check your configuration");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toast.error("Not yet supported");
|
toast.error("Not yet supported");
|
||||||
@@ -43,7 +55,6 @@ export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestC
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import type {
|
|||||||
StorageResult,
|
StorageResult,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
import {uploadLocal, getLocal, deleteLocal} from './local';
|
import {uploadLocal, getLocal, deleteLocal, pingLocal} from './local';
|
||||||
import {deleteS3, getS3, uploadS3} from "@/features/storages/providers/s3";
|
import {deleteS3, getS3, pingS3, uploadS3} from "@/features/storages/providers/s3";
|
||||||
|
|
||||||
type ProviderHandler = {
|
type ProviderHandler = {
|
||||||
upload: (config: any, input: StorageInput & { action: 'upload' }) => Promise<StorageResult>;
|
upload: (config: any, input: StorageInput & { action: 'upload' }) => Promise<StorageResult>;
|
||||||
get: (config: any, input: StorageInput & { action: 'get' }) => Promise<StorageResult>;
|
get: (config: any, input: StorageInput & { action: 'get' }) => Promise<StorageResult>;
|
||||||
delete: (config: any, input: StorageInput & { action: 'delete' }) => Promise<StorageResult>;
|
delete: (config: any, input: StorageInput & { action: 'delete' }) => Promise<StorageResult>;
|
||||||
|
ping: (config: any, input: { action: 'ping' }) => Promise<StorageResult>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlers: Record<StorageProviderKind, ProviderHandler> = {
|
const handlers: Record<StorageProviderKind, ProviderHandler> = {
|
||||||
@@ -18,11 +19,13 @@ const handlers: Record<StorageProviderKind, ProviderHandler> = {
|
|||||||
upload: uploadLocal,
|
upload: uploadLocal,
|
||||||
get: getLocal,
|
get: getLocal,
|
||||||
delete: deleteLocal,
|
delete: deleteLocal,
|
||||||
|
ping: pingLocal,
|
||||||
},
|
},
|
||||||
s3: {
|
s3: {
|
||||||
upload: uploadS3,
|
upload: uploadS3,
|
||||||
get: getS3,
|
get: getS3,
|
||||||
delete: deleteS3,
|
delete: deleteS3,
|
||||||
|
ping: pingS3,
|
||||||
},
|
},
|
||||||
// gcs: null as any,
|
// gcs: null as any,
|
||||||
// azure: null as any,
|
// azure: null as any,
|
||||||
|
|||||||
@@ -76,3 +76,21 @@ export async function deleteLocal(
|
|||||||
provider: 'local',
|
provider: 'local',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function pingLocal(
|
||||||
|
config: { baseDir?: string }
|
||||||
|
): Promise<StorageResult> {
|
||||||
|
|
||||||
|
const base = config.baseDir || BASE_DIR;
|
||||||
|
const fullPath = path.join(process.cwd(), base, "ping.txt");
|
||||||
|
|
||||||
|
await fs.promises.writeFile(fullPath, "ping");
|
||||||
|
await fs.promises.readFile(fullPath);
|
||||||
|
await fs.promises.unlink(fullPath);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
provider: 'local',
|
||||||
|
response: "Local storage OK"
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -90,3 +90,31 @@ export async function deleteS3(config: S3Config, input: { data: StorageDeleteInp
|
|||||||
return {success: false, provider: "s3", error: err.message};
|
return {success: false, provider: "s3", error: err.message};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function pingS3(config: S3Config): Promise<StorageResult> {
|
||||||
|
try {
|
||||||
|
const client = await getS3Client(config);
|
||||||
|
const exists = await client.bucketExists(config.bucketName);
|
||||||
|
if (!exists) return {
|
||||||
|
success: false,
|
||||||
|
provider: "s3",
|
||||||
|
response: "Bucket does not exist"
|
||||||
|
};
|
||||||
|
const key = `${BASE_DIR}ping.txt`;
|
||||||
|
await client.putObject(config.bucketName, key, Buffer.from("ping"));
|
||||||
|
await client.getObject(config.bucketName, key);
|
||||||
|
await client.removeObject(config.bucketName, key);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
provider: "s3",
|
||||||
|
response: "S3 storage OK"
|
||||||
|
};
|
||||||
|
} catch (err: any) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
provider: "s3",
|
||||||
|
response: err.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ export interface StorageDeleteInput {
|
|||||||
export type StorageInput =
|
export type StorageInput =
|
||||||
| { action: 'upload'; data: StorageUploadInput }
|
| { action: 'upload'; data: StorageUploadInput }
|
||||||
| { action: 'get'; data: StorageGetInput }
|
| { action: 'get'; data: StorageGetInput }
|
||||||
| { action: 'delete'; data: StorageDeleteInput };
|
| { action: 'delete'; data: StorageDeleteInput }
|
||||||
|
| { action: 'ping'; };
|
||||||
|
|
||||||
export interface StorageResult {
|
export interface StorageResult {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user