Admin panel init (#8742)
WIP Related issues - #7090 #8547 Master issue - #4499 --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@ -0,0 +1,91 @@
|
||||
import { UserLookup } from '@/settings/admin-panel/types/UserLookup';
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
import {
|
||||
useUpdateWorkspaceFeatureFlagMutation,
|
||||
useUserLookupAdminPanelMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const useFeatureFlagsManagement = () => {
|
||||
const [userLookupResult, setUserLookupResult] = useState<UserLookup | null>(
|
||||
null,
|
||||
);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const [userLookup] = useUserLookupAdminPanelMutation({
|
||||
onCompleted: (data) => {
|
||||
setIsLoading(false);
|
||||
if (isDefined(data?.userLookupAdminPanel)) {
|
||||
setUserLookupResult(data.userLookupAdminPanel);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
setIsLoading(false);
|
||||
setError(error.message);
|
||||
},
|
||||
});
|
||||
|
||||
const [updateFeatureFlag] = useUpdateWorkspaceFeatureFlagMutation();
|
||||
|
||||
const handleUserLookup = async (userIdentifier: string) => {
|
||||
setError(null);
|
||||
setIsLoading(true);
|
||||
setUserLookupResult(null);
|
||||
|
||||
const response = await userLookup({
|
||||
variables: { userIdentifier },
|
||||
});
|
||||
|
||||
return response.data?.userLookupAdminPanel;
|
||||
};
|
||||
|
||||
const handleFeatureFlagUpdate = async (
|
||||
workspaceId: string,
|
||||
featureFlag: string,
|
||||
value: boolean,
|
||||
) => {
|
||||
setError(null);
|
||||
const previousState = userLookupResult;
|
||||
|
||||
if (isDefined(userLookupResult)) {
|
||||
setUserLookupResult({
|
||||
...userLookupResult,
|
||||
workspaces: userLookupResult.workspaces.map((workspace) =>
|
||||
workspace.id === workspaceId
|
||||
? {
|
||||
...workspace,
|
||||
featureFlags: workspace.featureFlags.map((flag) =>
|
||||
flag.key === featureFlag ? { ...flag, value } : flag,
|
||||
),
|
||||
}
|
||||
: workspace,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
const response = await updateFeatureFlag({
|
||||
variables: {
|
||||
workspaceId,
|
||||
featureFlag,
|
||||
value,
|
||||
},
|
||||
onError: (error) => {
|
||||
if (isDefined(previousState)) {
|
||||
setUserLookupResult(previousState);
|
||||
}
|
||||
setError(error.message);
|
||||
},
|
||||
});
|
||||
|
||||
return !!response.data;
|
||||
};
|
||||
|
||||
return {
|
||||
userLookupResult,
|
||||
handleUserLookup,
|
||||
handleFeatureFlagUpdate,
|
||||
isLoading,
|
||||
error,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,60 @@
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { tokenPairState } from '@/auth/states/tokenPairState';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
import { useImpersonateMutation } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { sleep } from '~/utils/sleep';
|
||||
|
||||
export const useImpersonate = () => {
|
||||
const { clearSession } = useAuth();
|
||||
const [currentUser, setCurrentUser] = useRecoilState(currentUserState);
|
||||
const setTokenPair = useSetRecoilState(tokenPairState);
|
||||
const [impersonate] = useImpersonateMutation();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const handleImpersonate = async (userId: string) => {
|
||||
if (!userId.trim()) {
|
||||
setError('Please enter a user ID');
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const impersonateResult = await impersonate({
|
||||
variables: { userId },
|
||||
});
|
||||
|
||||
if (isDefined(impersonateResult.errors)) {
|
||||
throw impersonateResult.errors;
|
||||
}
|
||||
|
||||
if (!impersonateResult.data?.impersonate) {
|
||||
throw new Error('No impersonate result');
|
||||
}
|
||||
|
||||
const { user, tokens } = impersonateResult.data.impersonate;
|
||||
await clearSession();
|
||||
setCurrentUser(user);
|
||||
setTokenPair(tokens);
|
||||
await sleep(0); // This hacky workaround is necessary to ensure the tokens stored in the cookie are updated correctly.
|
||||
window.location.href = AppPath.Index;
|
||||
} catch (error) {
|
||||
setError('Failed to impersonate user. Please try again.');
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
handleImpersonate,
|
||||
isLoading,
|
||||
error,
|
||||
canImpersonate: currentUser?.canImpersonate,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user