refactor: complete RBAC migration cleanup - remove unused hooks and fix type imports

This commit is contained in:
CREDO23 2025-12-18 07:49:39 +00:00
parent 1c00e6f12e
commit 9c378550ba
3 changed files with 14 additions and 193 deletions

View file

@ -49,12 +49,11 @@ import { toast } from "sonner";
import { updateMemberMutationAtom, deleteMemberMutationAtom } from "@/atoms/members/members-mutation.atoms"; import { updateMemberMutationAtom, deleteMemberMutationAtom } from "@/atoms/members/members-mutation.atoms";
import { myAccessAtom } from "@/atoms/members/members-query.atoms"; import { myAccessAtom } from "@/atoms/members/members-query.atoms";
import { createInviteMutationAtom, deleteInviteMutationAtom } from '@/atoms/invites/invites-mutation.atoms'; import { createInviteMutationAtom, deleteInviteMutationAtom } from '@/atoms/invites/invites-mutation.atoms';
import type { CreateInviteRequest, DeleteInviteRequest } from '@/contracts/types/invites.types'; import type { DeleteInviteRequest } from '@/contracts/types/invites.types';
import type { UpdateMembershipRequest, DeleteMembershipRequest, Membership } from "@/contracts/types/members.types"; import type { UpdateMembershipRequest, DeleteMembershipRequest} from "@/contracts/types/members.types";
import { permissionsAtom } from "@/atoms/permissions/permissions-query.atoms"; import { permissionsAtom } from "@/atoms/permissions/permissions-query.atoms";
import { membersAtom } from "@/atoms/members/members-query.atoms"; import { membersAtom } from "@/atoms/members/members-query.atoms";
import { invitesApiService } from '@/lib/apis/invites-api.service'; import { invitesApiService } from '@/lib/apis/invites-api.service';
import type { Invite } from '@/contracts/types/invites.types';
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@ -117,9 +116,10 @@ import type {
UpdateRoleRequest, UpdateRoleRequest,
} from "@/contracts/types/roles.types"; } from "@/contracts/types/roles.types";
import { import {
type InviteCreate, type Invite,
type Member, type CreateInviteRequest,
} from "@/hooks/use-rbac"; } from "@/contracts/types/invites.types";
import type { Membership } from "@/contracts/types/members.types";
import { rolesApiService } from "@/lib/apis/roles-api.service"; import { rolesApiService } from "@/lib/apis/roles-api.service";
import { cacheKeys } from "@/lib/query-client/cache-keys"; import { cacheKeys } from "@/lib/query-client/cache-keys";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@ -165,8 +165,7 @@ export default function TeamManagementPage() {
[access] [access]
); );
const { data: membersData = [], isLoading: membersLoading, refetch: fetchMembers } = useAtomValue(membersAtom); const { data: members = [], isLoading: membersLoading, refetch: fetchMembers } = useAtomValue(membersAtom);
const members = membersData as Member[];
const { mutateAsync: createRole } = useAtomValue(createRoleMutationAtom); const { mutateAsync: createRole } = useAtomValue(createRoleMutationAtom);
const { mutateAsync: updateRole } = useAtomValue(updateRoleMutationAtom); const { mutateAsync: updateRole } = useAtomValue(updateRoleMutationAtom);
@ -190,7 +189,7 @@ export default function TeamManagementPage() {
); );
const handleCreateInvite = useCallback( const handleCreateInvite = useCallback(
async (inviteData: InviteCreate) => { async (inviteData: CreateInviteRequest['data']) => {
const request: CreateInviteRequest = { const request: CreateInviteRequest = {
search_space_id: searchSpaceId, search_space_id: searchSpaceId,
data: inviteData, data: inviteData,
@ -236,7 +235,7 @@ export default function TeamManagementPage() {
); );
const handleUpdateMember = useCallback( const handleUpdateMember = useCallback(
async (membershipId: number, roleId: number | null): Promise<Member> => { async (membershipId: number, roleId: number | null): Promise<Membership> => {
const request: UpdateMembershipRequest = { const request: UpdateMembershipRequest = {
search_space_id: searchSpaceId, search_space_id: searchSpaceId,
membership_id: membershipId, membership_id: membershipId,
@ -244,7 +243,7 @@ export default function TeamManagementPage() {
role_id: roleId, role_id: roleId,
}, },
}; };
return await updateMember(request) as Member; return await updateMember(request) as Membership;
}, },
[updateMember, searchSpaceId] [updateMember, searchSpaceId]
); );
@ -511,10 +510,10 @@ function MembersTab({
canManageRoles, canManageRoles,
canRemove, canRemove,
}: { }: {
members: Member[]; members: Membership[];
roles: Role[]; roles: Role[];
loading: boolean; loading: boolean;
onUpdateRole: (membershipId: number, roleId: number | null) => Promise<Member>; onUpdateRole: (membershipId: number, roleId: number | null) => Promise<Membership>;
onRemoveMember: (membershipId: number) => Promise<boolean>; onRemoveMember: (membershipId: number) => Promise<boolean>;
canManageRoles: boolean; canManageRoles: boolean;
canRemove: boolean; canRemove: boolean;
@ -1078,7 +1077,7 @@ function CreateInviteDialog({
searchSpaceId, searchSpaceId,
}: { }: {
roles: Role[]; roles: Role[];
onCreateInvite: (data: InviteCreate) => Promise<Invite>; onCreateInvite: (data: CreateInviteRequest['data']) => Promise<Invite>;
searchSpaceId: number; searchSpaceId: number;
}) { }) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@ -1093,7 +1092,7 @@ function CreateInviteDialog({
const handleCreate = async () => { const handleCreate = async () => {
setCreating(true); setCreating(true);
try { try {
const data: InviteCreate = {}; const data: CreateInviteRequest['data'] = {};
if (name) data.name = name; if (name) data.name = name;
if (roleId && roleId !== "default") data.role_id = Number(roleId); if (roleId && roleId !== "default") data.role_id = Number(roleId);
if (maxUses) data.max_uses = Number(maxUses); if (maxUses) data.max_uses = Number(maxUses);

View file

@ -1,4 +1,3 @@
export * from "./use-debounced-value"; export * from "./use-debounced-value";
export * from "./use-logs"; export * from "./use-logs";
export * from "./use-rbac";
export * from "./use-search-source-connectors"; export * from "./use-search-source-connectors";

View file

@ -1,177 +0,0 @@
"use client";
import { useCallback, useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import { authenticatedFetch, getBearerToken, handleUnauthorized } from "@/lib/auth-utils";
// ============ Types ============
export interface Role {
id: number;
name: string;
description: string | null;
permissions: string[];
is_default: boolean;
is_system_role: boolean;
search_space_id: number;
created_at: string;
}
export interface Member {
id: number;
user_id: string;
search_space_id: number;
role_id: number | null;
is_owner: boolean;
joined_at: string;
created_at: string;
role: Role | null;
user_email: string | null;
}
export interface Invite {
id: number;
invite_code: string;
search_space_id: number;
role_id: number | null;
created_by_id: string | null;
expires_at: string | null;
max_uses: number | null;
uses_count: number;
is_active: boolean;
name: string | null;
created_at: string;
role: Role | null;
}
export interface InviteCreate {
name?: string;
role_id?: number;
expires_at?: string;
max_uses?: number;
}
export interface InviteUpdate {
name?: string;
role_id?: number;
expires_at?: string;
max_uses?: number;
is_active?: boolean;
}
export interface RoleCreate {
name: string;
description?: string;
permissions: string[];
is_default?: boolean;
}
export interface RoleUpdate {
name?: string;
description?: string;
permissions?: string[];
is_default?: boolean;
}
export interface PermissionInfo {
value: string;
name: string;
category: string;
}
export interface UserAccess {
search_space_id: number;
search_space_name: string;
is_owner: boolean;
role_name: string | null;
permissions: string[];
}
export interface InviteInfo {
search_space_name: string;
role_name: string | null;
is_valid: boolean;
message: string | null;
}
// ============ Members Hook ============
export function useInviteInfo(inviteCode: string | null) {
const [inviteInfo, setInviteInfo] = useState<InviteInfo | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchInviteInfo = useCallback(async () => {
if (!inviteCode) {
setLoading(false);
return;
}
try {
setLoading(true);
const response = await fetch(
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/invites/${inviteCode}/info`,
{
method: "GET",
}
);
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.detail || "Failed to fetch invite info");
}
const data = await response.json();
setInviteInfo(data);
setError(null);
return data;
} catch (err: any) {
setError(err.message || "Failed to fetch invite info");
console.error("Error fetching invite info:", err);
} finally {
setLoading(false);
}
}, [inviteCode]);
useEffect(() => {
fetchInviteInfo();
}, [fetchInviteInfo]);
const acceptInvite = useCallback(async () => {
if (!inviteCode) {
toast.error("No invite code provided");
return null;
}
try {
const response = await authenticatedFetch(
`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/invites/accept`,
{
headers: { "Content-Type": "application/json" },
method: "POST",
body: JSON.stringify({ invite_code: inviteCode }),
}
);
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.detail || "Failed to accept invite");
}
const data = await response.json();
toast.success(data.message || "Successfully joined the search space");
return data;
} catch (err: any) {
toast.error(err.message || "Failed to accept invite");
throw err;
}
}, [inviteCode]);
return {
inviteInfo,
loading,
error,
fetchInviteInfo,
acceptInvite,
};
}