Files
sarlink-portal/queries/devices.ts

147 lines
4.1 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { getServerSession } from "next-auth";
import { authOptions } from "@/app/auth";
import type { AddDeviceFormState, initialState } from "@/components/user/add-device-dialog";
import type { ApiError, ApiResponse, Device } from "@/lib/backend-types";
import { checkSession } from "@/utils/session";
import { handleApiResponse } from "@/utils/tryCatch";
type GetDevicesProps = {
name?: string;
offset?: number;
limit?: number;
page?: number;
sortBy?: string;
status?: string;
[key: string]: string | number | undefined; // Allow additional properties for flexibility
};
export async function getDevices(params: GetDevicesProps, allDevices = false) {
const session = await checkSession();
// Build query string from all defined params
const query = Object.entries(params)
.filter(([_, value]) => value !== undefined && value !== "")
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join("&");
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/devices/?${query}&all_devices=${allDevices}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
},
);
return handleApiResponse<ApiResponse<Device>>(response, "getDevices");
}
export async function getDevice({ deviceId }: { deviceId: string }) {
const session = await checkSession();
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/devices/${deviceId}/`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
},
);
return handleApiResponse<Device>(response, "getDevice");
}
export async function addDeviceAction(
prevState: AddDeviceFormState,
formData: FormData
): Promise<AddDeviceFormState> {
const name = formData.get("name") as string;
const mac_address = formData.get("mac_address") as string;
const errors: typeof initialState.fieldErrors = {};
if (!name || name.length < 2) {
errors.name = ["Device name is required and must be at least 2 characters."];
}
if (!mac_address || !/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(mac_address)) {
errors.mac_address = ["Invalid MAC address format."];
}
if (Object.keys(errors).length > 0) {
return {
message: "Validation failed.",
fieldErrors: errors,
payload: formData,
};
}
try {
const session = await getServerSession(authOptions);
if (!session?.apiToken) {
return { message: "Authentication required.", fieldErrors: {}, payload: formData };
}
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/devices/`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session.apiToken}`,
},
body: JSON.stringify({
name: name,
mac: mac_address,
registered: true,
}),
},
);
await handleApiResponse<Device>(response, "addDeviceAction");
revalidatePath("/devices");
return { message: "Device successfully added!", fieldErrors: {}, payload: formData };
} catch (error: unknown) {
console.error("Server Action Error:", error);
return { message: (error as ApiError).message || "An unexpected error occurred.", fieldErrors: {}, payload: formData };
}
}
export async function blockDevice({
deviceId,
reason_for_blocking,
blocked_by,
}: {
deviceId: string;
reason_for_blocking: string;
blocked_by: "ADMIN" | "PARENT";
}) {
console.log("Blocking device:", deviceId, reason_for_blocking, blocked_by);
const session = await getServerSession(authOptions);
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/devices/${deviceId}/block/`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
body: JSON.stringify({
blocked: true,
reason_for_blocking: session?.user?.is_superuser
? reason_for_blocking
: "Blocked by parent",
blocked_by: session?.user?.is_superuser ? "ADMIN" : "PARENT",
}),
},
);
return handleApiResponse<Device>(response, "blockDevice");
}