feat: adding storage system ping method in order to test.

This commit is contained in:
charlesgauthereau
2026-01-17 22:41:39 +01:00
parent 5b980fb382
commit bce1c5d9b8
6 changed files with 68 additions and 7 deletions
@@ -3,7 +3,7 @@ import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/
import {Metadata} from "next";
import {ChannelsSection} from "@/components/wrappers/dashboard/admin/channels/channels-section";
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 {StorageChannelWith} from "@/db/schema/12_storage-channel";
import {ChannelAddEditModal} from "@/components/wrappers/dashboard/admin/channels/channel/channel-add-edit-modal";
@@ -10,6 +10,8 @@ import {useIsMobile} from "@/hooks/use-mobile";
import {cn} from "@/lib/utils";
import {StorageChannel} from "@/db/schema/12_storage-channel";
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 = {
channel: NotificationChannel | StorageChannel;
@@ -19,7 +21,6 @@ type NotifierTestChannelButtonProps = {
export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestChannelButtonProps) => {
const channelText = getChannelTextBasedOnKind(kind)
const isMobile = useIsMobile()
const mutation = useMutation({
mutationFn: async () => {
@@ -34,7 +35,18 @@ export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestC
if (result.success) {
toast.success(result.message);
} 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 {
toast.error("Not yet supported");
@@ -43,7 +55,6 @@ export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestC
},
});
return (
<Button
type="button"
+5 -2
View File
@@ -4,13 +4,14 @@ import type {
StorageResult,
} from '../types';
import {uploadLocal, getLocal, deleteLocal} from './local';
import {deleteS3, getS3, uploadS3} from "@/features/storages/providers/s3";
import {uploadLocal, getLocal, deleteLocal, pingLocal} from './local';
import {deleteS3, getS3, pingS3, uploadS3} from "@/features/storages/providers/s3";
type ProviderHandler = {
upload: (config: any, input: StorageInput & { action: 'upload' }) => Promise<StorageResult>;
get: (config: any, input: StorageInput & { action: 'get' }) => Promise<StorageResult>;
delete: (config: any, input: StorageInput & { action: 'delete' }) => Promise<StorageResult>;
ping: (config: any, input: { action: 'ping' }) => Promise<StorageResult>;
};
const handlers: Record<StorageProviderKind, ProviderHandler> = {
@@ -18,11 +19,13 @@ const handlers: Record<StorageProviderKind, ProviderHandler> = {
upload: uploadLocal,
get: getLocal,
delete: deleteLocal,
ping: pingLocal,
},
s3: {
upload: uploadS3,
get: getS3,
delete: deleteS3,
ping: pingS3,
},
// gcs: null as any,
// azure: null as any,
+18
View File
@@ -76,3 +76,21 @@ export async function deleteLocal(
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"
};
}
+28
View File
@@ -90,3 +90,31 @@ export async function deleteS3(config: S3Config, input: { data: StorageDeleteInp
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
};
}
}
+2 -1
View File
@@ -27,7 +27,8 @@ export interface StorageDeleteInput {
export type StorageInput =
| { action: 'upload'; data: StorageUploadInput }
| { action: 'get'; data: StorageGetInput }
| { action: 'delete'; data: StorageDeleteInput };
| { action: 'delete'; data: StorageDeleteInput }
| { action: 'ping'; };
export interface StorageResult {
success: boolean;