v0.1.16: Security overhaul and systematic deployment preparation
Breaking changes for clean alpha releases: - JWT authentication with user-provided secrets (no more development defaults) - Registration token system for secure agent enrollment - Rate limiting with user-adjustable settings - Enhanced agent configuration with proxy support - Interactive server setup wizard (--setup flag) - Heartbeat architecture separation for better UX - Package status synchronization fixes - Accurate timestamp tracking for RMM features Setup process for new installations: 1. docker-compose up -d postgres 2. ./redflag-server --setup 3. ./redflag-server --migrate 4. ./redflag-server 5. Generate tokens via admin UI 6. Deploy agents with registration tokens
This commit is contained in:
103
aggregator-web/src/hooks/useRegistrationTokens.ts
Normal file
103
aggregator-web/src/hooks/useRegistrationTokens.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { adminApi } from '@/lib/api';
|
||||
import {
|
||||
RegistrationToken,
|
||||
CreateRegistrationTokenRequest,
|
||||
RegistrationTokenStats
|
||||
} from '@/types';
|
||||
|
||||
// Query keys
|
||||
export const registrationTokenKeys = {
|
||||
all: ['registration-tokens'] as const,
|
||||
lists: () => [...registrationTokenKeys.all, 'list'] as const,
|
||||
list: (params: any) => [...registrationTokenKeys.lists(), params] as const,
|
||||
details: () => [...registrationTokenKeys.all, 'detail'] as const,
|
||||
detail: (id: string) => [...registrationTokenKeys.details(), id] as const,
|
||||
stats: () => [...registrationTokenKeys.all, 'stats'] as const,
|
||||
};
|
||||
|
||||
// Hooks
|
||||
export const useRegistrationTokens = (params?: {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
is_active?: boolean;
|
||||
label?: string;
|
||||
}) => {
|
||||
return useQuery({
|
||||
queryKey: registrationTokenKeys.list(params),
|
||||
queryFn: () => adminApi.tokens.getTokens(params),
|
||||
staleTime: 1000 * 60, // 1 minute
|
||||
});
|
||||
};
|
||||
|
||||
export const useRegistrationToken = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: registrationTokenKeys.detail(id),
|
||||
queryFn: () => adminApi.tokens.getToken(id),
|
||||
enabled: !!id,
|
||||
staleTime: 1000 * 60, // 1 minute
|
||||
});
|
||||
};
|
||||
|
||||
export const useRegistrationTokenStats = () => {
|
||||
return useQuery({
|
||||
queryKey: registrationTokenKeys.stats(),
|
||||
queryFn: () => adminApi.tokens.getStats(),
|
||||
staleTime: 1000 * 60, // 1 minute
|
||||
refetchInterval: 1000 * 60 * 5, // Refresh every 5 minutes
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreateRegistrationToken = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (data: CreateRegistrationTokenRequest) =>
|
||||
adminApi.tokens.createToken(data),
|
||||
onSuccess: (newToken) => {
|
||||
toast.success(`Registration token "${newToken.label}" created successfully`);
|
||||
queryClient.invalidateQueries({ queryKey: registrationTokenKeys.lists() });
|
||||
queryClient.invalidateQueries({ queryKey: registrationTokenKeys.stats() });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
console.error('Failed to create registration token:', error);
|
||||
toast.error(error.response?.data?.message || 'Failed to create registration token');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useRevokeRegistrationToken = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => adminApi.tokens.revokeToken(id),
|
||||
onSuccess: (_, tokenId) => {
|
||||
toast.success('Registration token revoked successfully');
|
||||
queryClient.invalidateQueries({ queryKey: registrationTokenKeys.lists() });
|
||||
queryClient.invalidateQueries({ queryKey: registrationTokenKeys.detail(tokenId) });
|
||||
queryClient.invalidateQueries({ queryKey: registrationTokenKeys.stats() });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
console.error('Failed to revoke registration token:', error);
|
||||
toast.error(error.response?.data?.message || 'Failed to revoke registration token');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useCleanupRegistrationTokens = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: () => adminApi.tokens.cleanup(),
|
||||
onSuccess: (result) => {
|
||||
toast.success(`Cleaned up ${result.cleaned} expired tokens`);
|
||||
queryClient.invalidateQueries({ queryKey: registrationTokenKeys.lists() });
|
||||
queryClient.invalidateQueries({ queryKey: registrationTokenKeys.stats() });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
console.error('Failed to cleanup registration tokens:', error);
|
||||
toast.error(error.response?.data?.message || 'Failed to cleanup registration tokens');
|
||||
},
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user