mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-27 17:56:25 +02:00
refactor: complete RBAC migration cleanup - remove unused hooks and fix type imports
This commit is contained in:
parent
1c00e6f12e
commit
9c378550ba
3 changed files with 14 additions and 193 deletions
|
|
@ -49,12 +49,11 @@ import { toast } from "sonner";
|
|||
import { updateMemberMutationAtom, deleteMemberMutationAtom } from "@/atoms/members/members-mutation.atoms";
|
||||
import { myAccessAtom } from "@/atoms/members/members-query.atoms";
|
||||
import { createInviteMutationAtom, deleteInviteMutationAtom } from '@/atoms/invites/invites-mutation.atoms';
|
||||
import type { CreateInviteRequest, DeleteInviteRequest } from '@/contracts/types/invites.types';
|
||||
import type { UpdateMembershipRequest, DeleteMembershipRequest, Membership } from "@/contracts/types/members.types";
|
||||
import type { DeleteInviteRequest } from '@/contracts/types/invites.types';
|
||||
import type { UpdateMembershipRequest, DeleteMembershipRequest} from "@/contracts/types/members.types";
|
||||
import { permissionsAtom } from "@/atoms/permissions/permissions-query.atoms";
|
||||
import { membersAtom } from "@/atoms/members/members-query.atoms";
|
||||
import { invitesApiService } from '@/lib/apis/invites-api.service';
|
||||
import type { Invite } from '@/contracts/types/invites.types';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
|
|
@ -117,9 +116,10 @@ import type {
|
|||
UpdateRoleRequest,
|
||||
} from "@/contracts/types/roles.types";
|
||||
import {
|
||||
type InviteCreate,
|
||||
type Member,
|
||||
} from "@/hooks/use-rbac";
|
||||
type Invite,
|
||||
type CreateInviteRequest,
|
||||
} from "@/contracts/types/invites.types";
|
||||
import type { Membership } from "@/contracts/types/members.types";
|
||||
import { rolesApiService } from "@/lib/apis/roles-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
|
@ -165,8 +165,7 @@ export default function TeamManagementPage() {
|
|||
[access]
|
||||
);
|
||||
|
||||
const { data: membersData = [], isLoading: membersLoading, refetch: fetchMembers } = useAtomValue(membersAtom);
|
||||
const members = membersData as Member[];
|
||||
const { data: members = [], isLoading: membersLoading, refetch: fetchMembers } = useAtomValue(membersAtom);
|
||||
|
||||
const { mutateAsync: createRole } = useAtomValue(createRoleMutationAtom);
|
||||
const { mutateAsync: updateRole } = useAtomValue(updateRoleMutationAtom);
|
||||
|
|
@ -190,7 +189,7 @@ export default function TeamManagementPage() {
|
|||
);
|
||||
|
||||
const handleCreateInvite = useCallback(
|
||||
async (inviteData: InviteCreate) => {
|
||||
async (inviteData: CreateInviteRequest['data']) => {
|
||||
const request: CreateInviteRequest = {
|
||||
search_space_id: searchSpaceId,
|
||||
data: inviteData,
|
||||
|
|
@ -236,7 +235,7 @@ export default function TeamManagementPage() {
|
|||
);
|
||||
|
||||
const handleUpdateMember = useCallback(
|
||||
async (membershipId: number, roleId: number | null): Promise<Member> => {
|
||||
async (membershipId: number, roleId: number | null): Promise<Membership> => {
|
||||
const request: UpdateMembershipRequest = {
|
||||
search_space_id: searchSpaceId,
|
||||
membership_id: membershipId,
|
||||
|
|
@ -244,7 +243,7 @@ export default function TeamManagementPage() {
|
|||
role_id: roleId,
|
||||
},
|
||||
};
|
||||
return await updateMember(request) as Member;
|
||||
return await updateMember(request) as Membership;
|
||||
},
|
||||
[updateMember, searchSpaceId]
|
||||
);
|
||||
|
|
@ -511,10 +510,10 @@ function MembersTab({
|
|||
canManageRoles,
|
||||
canRemove,
|
||||
}: {
|
||||
members: Member[];
|
||||
members: Membership[];
|
||||
roles: Role[];
|
||||
loading: boolean;
|
||||
onUpdateRole: (membershipId: number, roleId: number | null) => Promise<Member>;
|
||||
onUpdateRole: (membershipId: number, roleId: number | null) => Promise<Membership>;
|
||||
onRemoveMember: (membershipId: number) => Promise<boolean>;
|
||||
canManageRoles: boolean;
|
||||
canRemove: boolean;
|
||||
|
|
@ -1078,7 +1077,7 @@ function CreateInviteDialog({
|
|||
searchSpaceId,
|
||||
}: {
|
||||
roles: Role[];
|
||||
onCreateInvite: (data: InviteCreate) => Promise<Invite>;
|
||||
onCreateInvite: (data: CreateInviteRequest['data']) => Promise<Invite>;
|
||||
searchSpaceId: number;
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
|
@ -1093,7 +1092,7 @@ function CreateInviteDialog({
|
|||
const handleCreate = async () => {
|
||||
setCreating(true);
|
||||
try {
|
||||
const data: InviteCreate = {};
|
||||
const data: CreateInviteRequest['data'] = {};
|
||||
if (name) data.name = name;
|
||||
if (roleId && roleId !== "default") data.role_id = Number(roleId);
|
||||
if (maxUses) data.max_uses = Number(maxUses);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
export * from "./use-debounced-value";
|
||||
export * from "./use-logs";
|
||||
export * from "./use-rbac";
|
||||
export * from "./use-search-source-connectors";
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue