1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/web/src/hooks/UseOrganizationActions.ts
Harish Govindarajulu a7d01d052d fix(ui): Add "Requires fresh login" checks for superuser operations (PROJQUAY-9658) (#4451)
* fix(ui): show password verification for take ownership (PROJQUAY-9658)

Co-authored-by: Claude <noreply@anthropic.com>

* fix(ui): add fresh login verification to superuser operations (PROJQUAY-9658)

  Implemented password verification modal for sensitive superuser operations
  that require fresh login. Added fresh login handling to:
  - Delete organization
  - Rename organization
  - Delete user
  - Create user
  - Change user password
  - Change user email

  Also fixed UseCreateUser hook to pass error object instead of string
  to enable fresh login detection.

  🤖 Generated with [Claude Code](https://claude.com/claude-code)

  Co-Authored-By: Claude <noreply@anthropic.com>

* fix(ui): implement global fresh login with request queuing (PROJQUAY-9658)

Replaced component-level fresh login handling with centralized axios
interceptor approach. All failed requests due to fresh login requirement
are now queued and automatically retried after password verification.

- Add axios interceptor to catch 401 fresh_login_required globally
- Implement request queuing mechanism for pending operations
- Add global FreshLoginModal at app root level
- Remove component-level useFreshLogin hook from all modals
- Close operation modals immediately after submit (request queued if needed)
- Add fresh login support for quota management operations

* Add Cypress tests for fresh login flow (6 tests)

* Address code rabbit reviews

* fix(ui): handle fresh login password verification errors

- Display error toast when wrong password entered in verification modal
- Add centralized fresh login error filtering utility
- Add Cypress tests for wrong password and retry scenarios

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-18 05:23:35 +05:30

107 lines
3.0 KiB
TypeScript

import {useMutation, useQueryClient} from '@tanstack/react-query';
import {useNavigate} from 'react-router-dom';
import {
deleteOrg,
renameOrganization,
takeOwnership,
} from 'src/resources/OrganizationResource';
export function useRenameOrganization({onSuccess, onError}) {
const queryClient = useQueryClient();
const renameOrganizationMutator = useMutation(
async ({orgName, newName}: {orgName: string; newName: string}) => {
return await renameOrganization(orgName, newName);
},
{
onSuccess: (data, variables) => {
// Invalidate the main organizations list queries
queryClient.invalidateQueries([
'organization',
'superuser',
'organizations',
]);
queryClient.invalidateQueries(['organization', 'superuser', 'users']);
queryClient.invalidateQueries(['user']);
onSuccess(variables.orgName, variables.newName);
},
onError: (err) => {
onError(err);
},
},
);
return {
renameOrganization: async (orgName: string, newName: string) =>
renameOrganizationMutator.mutate({orgName, newName}),
isLoading: renameOrganizationMutator.isLoading,
};
}
export function useDeleteSingleOrganization({onSuccess, onError}) {
const queryClient = useQueryClient();
const deleteOrganizationMutator = useMutation(
async (orgName: string) => {
return await deleteOrg(orgName, true); // true for superuser
},
{
onSuccess: () => {
// Invalidate the main organizations list queries
queryClient.invalidateQueries([
'organization',
'superuser',
'organizations',
]);
queryClient.invalidateQueries(['organization', 'superuser', 'users']);
queryClient.invalidateQueries(['user']);
onSuccess();
},
onError: (err) => {
onError(err);
},
},
);
return {
deleteOrganization: async (orgName: string) =>
deleteOrganizationMutator.mutate(orgName),
isLoading: deleteOrganizationMutator.isLoading,
};
}
export function useTakeOwnership({onSuccess, onError}) {
const queryClient = useQueryClient();
const navigate = useNavigate();
const takeOwnershipMutator = useMutation(
async (namespace: string) => {
return await takeOwnership(namespace);
},
{
onSuccess: (data, namespace) => {
// Invalidate the main organizations list queries
queryClient.invalidateQueries([
'organization',
'superuser',
'organizations',
]);
queryClient.invalidateQueries(['organization', 'superuser', 'users']);
queryClient.invalidateQueries(['user']);
// Navigate to the organization page
navigate(`/organization/${namespace}`);
onSuccess();
},
onError: (err) => {
onError(err);
},
},
);
return {
takeOwnership: async (namespace: string) =>
takeOwnershipMutator.mutate(namespace),
isLoading: takeOwnershipMutator.isLoading,
};
}