pankod/refine

View on GitHub
packages/core/src/hooks/auditLog/useLog/index.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { useContext } from "react";

import { getXRay } from "@refinedev/devtools-internal";
import {
  UseMutationOptions,
  UseMutationResult,
  useMutation,
  useQueryClient,
} from "@tanstack/react-query";

import { AuditLogContext } from "@contexts/auditLog";
import { ResourceContext } from "@contexts/resource";
import { hasPermission, pickNotDeprecated } from "@definitions/helpers";
import { useActiveAuthProvider } from "@definitions/helpers";
import { pickResource } from "@definitions/helpers/pick-resource";
import { useGetIdentity } from "@hooks/auth";
import { useKeys } from "@hooks/useKeys";

import { LogParams } from "../../../contexts/auditLog/types";
import { BaseKey } from "../../../contexts/data/types";

type LogRenameData =
  | {
      resource?: string;
    }
  | undefined;

export type UseLogReturnType<TLogData, TLogRenameData> = {
  log: UseMutationResult<TLogData, Error, LogParams>;
  rename: UseMutationResult<
    TLogRenameData,
    Error,
    {
      id: BaseKey;
      name: string;
    }
  >;
};

export type UseLogMutationProps<
  TLogData,
  TLogRenameData extends LogRenameData = LogRenameData,
> = {
  logMutationOptions?: Omit<
    UseMutationOptions<TLogData, Error, LogParams, unknown>,
    "mutationFn"
  >;
  renameMutationOptions?: Omit<
    UseMutationOptions<
      TLogRenameData,
      Error,
      { id: BaseKey; name: string },
      unknown
    >,
    "mutationFn" | "onSuccess"
  >;
};

/**
 * useLog is used to `create` a new and `rename` the existing audit log.
 * @see {@link https://refine.dev/docs/api-reference/core/hooks/audit-log/useLog} for more details.
 */

export const useLog = <
  TLogData,
  TLogRenameData extends LogRenameData = LogRenameData,
>({
  logMutationOptions,
  renameMutationOptions,
}: UseLogMutationProps<TLogData, TLogRenameData> = {}): UseLogReturnType<
  TLogData,
  TLogRenameData
> => {
  const queryClient = useQueryClient();
  const auditLogContext = useContext(AuditLogContext);
  const { keys, preferLegacyKeys } = useKeys();

  const authProvider = useActiveAuthProvider();

  const { resources } = useContext(ResourceContext);
  const {
    data: identityData,
    refetch,
    isLoading,
  } = useGetIdentity({
    v3LegacyAuthProviderCompatible: Boolean(authProvider?.isLegacy),
    queryOptions: {
      enabled: !!auditLogContext?.create,
    },
  });

  const log = useMutation<TLogData, Error, LogParams, unknown>(
    async (params) => {
      const resource = pickResource(params.resource, resources);
      const logPermissions = pickNotDeprecated(
        resource?.meta?.audit,
        resource?.options?.audit,
        resource?.options?.auditLog?.permissions,
      );

      if (logPermissions) {
        if (!hasPermission(logPermissions, params.action)) {
          return;
        }
      }

      let authorData;
      if (isLoading && !!auditLogContext?.create) {
        authorData = await refetch();
      }

      return await auditLogContext.create?.({
        ...params,
        author: identityData ?? authorData?.data,
      });
    },
    {
      mutationKey: keys().audit().action("log").get(),
      ...logMutationOptions,
      meta: {
        ...logMutationOptions?.meta,
        ...getXRay("useLog", preferLegacyKeys),
      },
    },
  );

  const rename = useMutation<
    TLogRenameData,
    Error,
    { id: BaseKey; name: string },
    unknown
  >(
    async (params) => {
      return await auditLogContext.update?.(params);
    },
    {
      onSuccess: (data) => {
        if (data?.resource) {
          queryClient.invalidateQueries(
            keys()
              .audit()
              .resource(data?.resource ?? "")
              .action("list")
              .get(preferLegacyKeys),
          );
        }
      },
      mutationKey: keys().audit().action("rename").get(),
      ...renameMutationOptions,
      meta: {
        ...renameMutationOptions?.meta,
        ...getXRay("useLog", preferLegacyKeys),
      },
    },
  );

  return { log, rename };
};