web2-client/src/shared/services/admin/index.ts

1157 lines
28 KiB
TypeScript

import axios, { AxiosError } from 'axios';
import {
useMutation,
useQuery,
UseMutationOptions,
UseQueryOptions,
} from 'react-query';
import { request } from "~/shared/libs";
import { clearAdminAuth, persistAdminAuth } from "~/shared/libs/admin-auth";
export type AdminServiceState = {
name: string;
status?: string;
last_reported_seconds: number | null;
};
export type AdminOverviewResponse = {
project: {
host: string | null;
name: string;
privacy: string;
};
codebase: {
branch: string | null;
commit: string | null;
};
node: {
id: string;
service_wallet: string;
ton_master: string;
};
runtime: {
python: string;
implementation: string;
platform: string;
utc_now: string;
};
ipfs: Record<string, unknown> & {
identity?: Record<string, unknown> | { error: string };
bitswap?: Record<string, unknown> | { error: string };
repo?: Record<string, unknown> | { error: string };
};
content: {
encrypted_total: number;
upload_sessions_total: number;
derivatives_ready: number;
};
ton: {
host: string | null;
api_key_configured: boolean;
testnet: boolean;
};
services: AdminServiceState[];
};
export type AdminStorageResponse = {
directories: Array<{
label: string;
path: string;
exists: boolean;
file_count: number;
size_bytes: number;
}>;
disk: null | {
path: string;
total_bytes: number;
used_bytes: number;
free_bytes: number;
percent_used: number | null;
};
derivatives: {
ready: number;
processing: number;
pending: number;
failed: number;
total_bytes: number;
};
};
export type AdminUploadsContentDerivative = {
kind: string;
status: string;
size_bytes: number | null;
error: string | null;
created_at: string | null;
updated_at: string | null;
attempts: number;
download_url: string | null;
};
export type AdminUploadsContentUploadHistoryItem = {
state: string;
at: string | null;
error: string | null;
filename: string | null;
};
export type AdminUploadsContentIpfs = {
pin_state: string | null;
pin_error: string | null;
bytes_total: number | null;
bytes_fetched: number | null;
pinned_at: string | null;
updated_at: string | null;
} | null;
export type AdminUploadsContentStored = {
stored_id: number | null;
type: string | null;
owner_address: string | null;
user_id: number | null;
status: string | null;
content_url: string | null;
download_url: string | null;
created: string | null;
updated: string | null;
user?: {
id: number;
telegram_id: number;
username: string | null;
first_name: string | null;
last_name: string | null;
};
} | null;
export type AdminUploadsContentLinks = {
web_view: string | null;
start_app: string | null;
api_view: string | null;
download_primary: string | null;
download_derivatives: Array<{
kind: string;
url: string;
size_bytes: number | null;
}>;
};
export type AdminUploadsContentFlags = {
issues: boolean;
processing: boolean;
ready: boolean;
unindexed: boolean;
};
export type AdminContentDistributionNode = {
node_id: number | null;
is_local: boolean;
host: string | null;
public_host: string | null;
version: string | null;
role: string | null;
last_seen: string | null;
content: {
encrypted_cid: string | null;
content_type: string | null;
size_bytes: number | null;
preview_enabled: boolean | null;
updated_at: string | null;
metadata_cid?: string | null;
issuer_node_id?: string | null;
};
links: {
web_view: string | null;
api_view: string | null;
gateway_view: string | null;
};
};
export type AdminContentDistribution = {
local_present: boolean;
nodes: AdminContentDistributionNode[];
};
export type AdminUploadsContentStatus = {
upload_state: string | null;
conversion_state: string | null;
ipfs_state: string | null;
onchain: {
indexed: boolean;
onchain_index: number | null;
item_address: string | null;
license_count?: number;
} | null;
};
export type AdminUploadsContent = {
encrypted_cid: string;
metadata_cid: string | null;
content_hash: string | null;
title: string;
description: string | null;
content_type: string;
size: {
encrypted: number | null;
plain: number | null;
};
created_at: string | null;
updated_at: string | null;
status: AdminUploadsContentStatus;
upload_history: AdminUploadsContentUploadHistoryItem[];
derivative_summary: Record<string, number>;
derivatives: AdminUploadsContentDerivative[];
ipfs: AdminUploadsContentIpfs;
stored: AdminUploadsContentStored;
links: AdminUploadsContentLinks;
distribution: AdminContentDistribution;
flags?: AdminUploadsContentFlags;
};
export type AdminUploadsResponse = {
total: number;
states: Record<string, number>;
recent: Array<{
id: string;
filename: string | null;
size_bytes: number | null;
state: string;
encrypted_cid: string | null;
error: string | null;
updated_at: string;
created_at: string;
}>;
contents: AdminUploadsContent[];
matching_total?: number;
filter?: string[];
search?: string | null;
limit?: number;
scan?: number;
scanned?: number;
category_totals?: Record<string, number>;
};
export type AdminUploadsQueryParams = {
filter?: string | string[];
search?: string;
limit?: number;
scan?: number;
};
type AdminUploadsQueryKey = ['admin', 'uploads', string | null, string | null, number | null, number | null];
export type AdminUserWalletConnectionSummary = {
primary_address: string | null;
active_count: number;
total_count: number;
last_connected_at: string | null;
connections: Array<{
id: number;
address: string;
network: string;
invalidated: boolean;
created_at: string | null;
updated_at: string | null;
}>;
};
export type AdminUserContentSummary = {
total: number;
onchain: number;
local: number;
disabled: number;
};
export type AdminUserLicensesSummary = {
total: number;
active: number;
by_type: Record<string, number>;
by_status: Record<string, number>;
};
export type AdminUserStarsSummary = {
total: number;
paid: number;
unpaid: number;
amount_total: number;
amount_paid: number;
amount_unpaid: number;
};
export type AdminUserIpActivity = {
last: {
ip: string | null;
type: string | null;
seen_at: string | null;
} | null;
unique_ips: number;
recent: Array<{
ip: string | null;
type: string | null;
seen_at: string | null;
}>;
};
export type AdminUserItem = {
id: number;
is_admin: boolean;
telegram_id: number;
username: string | null;
first_name: string | null;
last_name: string | null;
lang_code: string | null;
created_at: string | null;
updated_at: string | null;
last_use: string | null;
meta: {
ref_id?: string | null;
referrer_id?: string | null;
};
wallets: AdminUserWalletConnectionSummary;
content: AdminUserContentSummary;
licenses: AdminUserLicensesSummary;
stars: AdminUserStarsSummary;
ip_activity: AdminUserIpActivity;
};
export type AdminEventItem = {
id: number;
origin_public_key: string | null;
origin_host: string | null;
seq: number;
uid: string;
event_type: string;
status: string;
created_at: string | null;
received_at: string | null;
applied_at: string | null;
payload: Record<string, unknown>;
links: Record<string, string | null>;
};
export type AdminEventsResponse = {
total: number;
limit: number;
offset: number;
filters?: Record<string, unknown>;
items: AdminEventItem[];
available_filters: {
types: Record<string, number>;
statuses: Record<string, number>;
origins: Record<string, number>;
};
};
export type AdminEventsQueryParams = {
limit?: number;
offset?: number;
type?: string | string[];
status?: string | string[];
origin?: string | string[];
search?: string;
};
type AdminEventsQueryKey = ['admin', 'events', string];
export type AdminUsersSummary = {
users_returned: number;
admins_total: number;
wallets_total: number;
wallets_active: number;
licenses_total: number;
licenses_active: number;
stars_total: number;
stars_paid: number;
stars_unpaid: number;
stars_amount_total: number;
stars_amount_paid: number;
stars_amount_unpaid: number;
unique_ips_total: number;
};
export type AdminUsersResponse = {
total: number;
limit: number;
offset: number;
search?: string | null;
filters?: Record<string, unknown>;
has_more: boolean;
items: AdminUserItem[];
summary: AdminUsersSummary;
};
export type AdminUsersQueryParams = {
limit?: number;
offset?: number;
search?: string;
};
type AdminUsersQueryKey = ['admin', 'users', string];
export type AdminLicenseItem = {
id: number;
type: string | null;
status: string | null;
license_type: number | null;
onchain_address: string | null;
owner_address: string | null;
user: {
id: number;
telegram_id: number;
username: string | null;
first_name: string | null;
last_name: string | null;
} | null;
wallet_connection: {
id: number;
address: string;
network: string;
invalidated: boolean;
created_at: string | null;
updated_at: string | null;
} | null;
content: {
id: number | null;
hash: string | null;
cid: string | null;
title: string | null;
type: string | null;
owner_address: string | null;
onchain_index: number | null;
user_id: number | null;
download_url: string | null;
} | null;
created_at: string | null;
updated_at: string | null;
meta: Record<string, unknown>;
links: {
tonviewer: string | null;
content_view: string | null;
};
};
export type AdminLicensesCounts = {
status: Record<string, number>;
type: Record<string, number>;
license_type: Record<string, number>;
};
export type AdminLicensesResponse = {
total: number;
limit: number;
offset: number;
search?: string | null;
filters?: Record<string, unknown>;
has_more: boolean;
items: AdminLicenseItem[];
counts: AdminLicensesCounts;
};
export type AdminLicensesQueryParams = {
limit?: number;
offset?: number;
search?: string;
type?: string | string[];
status?: string | string[];
license_type?: number | string | Array<number | string>;
user_id?: number;
owner?: string;
address?: string;
content_hash?: string;
};
type AdminLicensesQueryKey = ['admin', 'licenses', string];
export type AdminStarsInvoiceItem = {
id: number;
external_id: string;
type: string | null;
amount: number;
paid: boolean;
invoice_url: string | null;
created_at: string | null;
status: 'paid' | 'pending';
user: {
id: number;
telegram_id: number;
username: string | null;
first_name: string | null;
last_name: string | null;
} | null;
content: {
id: number | null;
hash: string | null;
cid: string | null;
title: string | null;
onchain_index: number | null;
owner_address: string | null;
user_id: number | null;
download_url: string | null;
} | null;
};
export type AdminStarsStats = {
total: number;
paid: number;
unpaid: number;
amount_total: number;
amount_paid: number;
amount_unpaid: number;
by_type: Record<string, {
total: number;
paid: number;
unpaid: number;
amount_total: number;
amount_paid: number;
amount_unpaid: number;
}>;
};
export type AdminStarsResponse = {
total: number;
limit: number;
offset: number;
search?: string | null;
filters?: Record<string, unknown>;
has_more: boolean;
items: AdminStarsInvoiceItem[];
stats: AdminStarsStats;
};
export type AdminStarsQueryParams = {
limit?: number;
offset?: number;
search?: string;
type?: string | string[];
paid?: boolean;
user_id?: number;
content_hash?: string;
};
type AdminStarsQueryKey = ['admin', 'stars', string];
export type AdminSystemResponse = {
env: Record<string, string | null | undefined>;
service_config: Array<{
key: string;
value: string | null;
raw: string | null;
}>;
services: AdminServiceState[];
blockchain_tasks: Record<string, number>;
latest_index_items: Array<{
encrypted_cid: string | null;
updated_at: string;
}>;
telegram_bots: Array<{
role: string;
username: string;
url: string;
}>;
};
export type AdminBlockchainResponse = {
counts: Record<string, number>;
recent: Array<{
id: string;
destination: string | null;
amount: string | null;
status: string;
epoch: number | null;
seqno: number | null;
transaction_hash: string | null;
updated: string;
}>;
};
export type AdminNodesResponse = {
items: Array<{
ip: string | null;
port: number | null;
public_key: string | null;
role: 'trusted' | 'read-only' | 'deny';
version?: string | null;
last_seen?: string | null;
notes?: string | null;
}>;
};
// --------- Состояние сети (новый раздел) ---------
export type AdminNetworkMember = {
node_id: string;
public_key: string | null;
public_host: string | null;
version: string | null;
role: string;
ip: string | null;
asn: number | null;
ip_first_octet: number | null;
reachability_ratio: number;
last_update: number | null;
accepts_inbound: boolean;
is_bootstrap: boolean;
receipts_total?: number;
receipts_asn_unique?: number;
};
export type AdminNetworkPerNodeReplication = Record<
string,
{
leases_held: number;
leaderships: number;
sample_contents: string[];
}
>;
export type AdminNetworkResponse = {
summary: {
n_estimate: number;
n_estimate_trusted: number;
active_trusted: number;
members_total: number;
active: number;
islands: number;
replication_conflicts: { under: number; over: number };
config: {
heartbeat_interval: number;
lease_ttl: number;
gossip_interval_sec: number;
gossip_backoff_base_sec: number;
gossip_backoff_cap_sec: number;
};
};
members: AdminNetworkMember[];
per_node_replication: AdminNetworkPerNodeReplication;
receipts: Array<{
target_id: string;
issuer_id: string;
asn: number | null;
timestamp: number | null;
status: 'valid' | 'bad_signature' | 'unknown_issuer' | 'mismatch_node_id' | 'unknown';
}>;
};
export const useAdminNetwork = (
options?: QueryOptions<AdminNetworkResponse, ['admin', 'network']>,
) => {
return useQuery<AdminNetworkResponse, AxiosError, AdminNetworkResponse, ['admin', 'network']>(
['admin', 'network'],
async () => {
const { data } = await request.get<AdminNetworkResponse>('/admin.network');
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export type AdminStatusResponse = {
ipfs: {
bitswap: Record<string, unknown>;
repo: Record<string, unknown>;
};
pin_counts: Record<string, number>;
derivatives: {
ready: number;
processing: number;
pending: number;
failed: number;
total_bytes: number;
};
convert_backlog: number;
limits: {
DERIVATIVE_CACHE_MAX_GB: number;
DERIVATIVE_CACHE_TTL_DAYS: number;
SYNC_MAX_CONCURRENT_PINS: number;
SYNC_DISK_LOW_WATERMARK_PCT: number;
};
};
export type AdminCacheSetLimitsPayload = {
max_gb: number;
ttl_days: number;
};
export type AdminCacheCleanupPayload =
| {
mode: 'ttl';
}
| {
mode?: 'fit';
max_gb: number;
};
export type AdminSyncSetLimitsPayload = {
max_concurrent_pins: number;
disk_low_watermark_pct: number;
};
export type AdminNodeSetRolePayload = {
public_key?: string;
host?: string;
role: 'trusted' | 'read-only' | 'deny';
};
const defaultQueryOptions = {
staleTime: 30_000,
refetchOnWindowFocus: false,
} as const;
type QueryOptions<TData, TQueryKey extends readonly unknown[]> = UseQueryOptions<
TData,
AxiosError,
TData,
TQueryKey
>;
type MutationOptions<TData, TVariables> = UseMutationOptions<
TData,
AxiosError,
TVariables
>;
export const useAdminOverview = (
options?: QueryOptions<AdminOverviewResponse, ['admin', 'overview']>,
) => {
return useQuery<AdminOverviewResponse, AxiosError, AdminOverviewResponse, ['admin', 'overview']>(
['admin', 'overview'],
async () => {
const { data } = await request.get<AdminOverviewResponse>('/admin.overview');
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminStorage = (
options?: QueryOptions<AdminStorageResponse, ['admin', 'storage']>,
) => {
return useQuery<AdminStorageResponse, AxiosError, AdminStorageResponse, ['admin', 'storage']>(
['admin', 'storage'],
async () => {
const { data } = await request.get<AdminStorageResponse>('/admin.storage');
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminUploads = (
params?: AdminUploadsQueryParams,
options?: QueryOptions<AdminUploadsResponse, AdminUploadsQueryKey>,
) => {
const filterParts = Array.isArray(params?.filter)
? params.filter.filter(Boolean)
: params?.filter
? [params.filter]
: [];
const filterValue = filterParts.length > 0 ? filterParts.join(',') : null;
const searchValue = params?.search?.trim() || null;
const limitValue = params?.limit ?? null;
const scanValue = params?.scan ?? null;
const queryKey: AdminUploadsQueryKey = ['admin', 'uploads', filterValue, searchValue, limitValue, scanValue];
const queryParams: Record<string, string | number | undefined> = {
filter: filterValue ?? undefined,
search: searchValue ?? undefined,
limit: limitValue ?? undefined,
scan: scanValue ?? undefined,
};
return useQuery<AdminUploadsResponse, AxiosError, AdminUploadsResponse, AdminUploadsQueryKey>(
queryKey,
async () => {
const { data } = await request.get<AdminUploadsResponse>('/admin.uploads', {
params: queryParams,
});
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminUsers = (
params?: AdminUsersQueryParams,
options?: QueryOptions<AdminUsersResponse, AdminUsersQueryKey>,
) => {
const normalizedSearch = params?.search?.trim() || null;
const paramsKeyPayload = {
limit: params?.limit ?? null,
offset: params?.offset ?? null,
search: normalizedSearch,
};
const paramsKey = JSON.stringify(paramsKeyPayload);
const queryParams: Record<string, string | number | undefined> = {
limit: params?.limit,
offset: params?.offset,
search: normalizedSearch ?? undefined,
};
return useQuery<AdminUsersResponse, AxiosError, AdminUsersResponse, AdminUsersQueryKey>(
['admin', 'users', paramsKey],
async () => {
const { data } = await request.get<AdminUsersResponse>('/admin.users', {
params: queryParams,
});
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminLicenses = (
params?: AdminLicensesQueryParams,
options?: QueryOptions<AdminLicensesResponse, AdminLicensesQueryKey>,
) => {
const normalizedSearch = params?.search?.trim() || null;
const typeValue = Array.isArray(params?.type)
? params.type.filter(Boolean).join(',')
: params?.type ?? null;
const statusValue = Array.isArray(params?.status)
? params.status.filter(Boolean).join(',')
: params?.status ?? null;
const licenseTypeValue = Array.isArray(params?.license_type)
? params.license_type.filter((value) => value !== undefined && value !== null).join(',')
: params?.license_type ?? null;
const paramsKeyPayload = {
limit: params?.limit ?? null,
offset: params?.offset ?? null,
search: normalizedSearch,
type: typeValue,
status: statusValue,
license_type: licenseTypeValue,
user_id: params?.user_id ?? null,
owner: params?.owner ?? null,
address: params?.address ?? null,
content_hash: params?.content_hash ?? null,
};
const paramsKey = JSON.stringify(paramsKeyPayload);
const queryParams: Record<string, string | number | undefined> = {
limit: params?.limit,
offset: params?.offset,
search: normalizedSearch ?? undefined,
type: typeValue ?? undefined,
status: statusValue ?? undefined,
license_type: licenseTypeValue ?? undefined,
user_id: params?.user_id,
owner: params?.owner ?? undefined,
address: params?.address ?? undefined,
content_hash: params?.content_hash ?? undefined,
};
return useQuery<AdminLicensesResponse, AxiosError, AdminLicensesResponse, AdminLicensesQueryKey>(
['admin', 'licenses', paramsKey],
async () => {
const { data } = await request.get<AdminLicensesResponse>('/admin.licenses', {
params: queryParams,
});
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminStars = (
params?: AdminStarsQueryParams,
options?: QueryOptions<AdminStarsResponse, AdminStarsQueryKey>,
) => {
const normalizedSearch = params?.search?.trim() || null;
const typeValue = Array.isArray(params?.type)
? params.type.filter(Boolean).join(',')
: params?.type ?? null;
const paramsKeyPayload = {
limit: params?.limit ?? null,
offset: params?.offset ?? null,
search: normalizedSearch,
type: typeValue,
paid: typeof params?.paid === 'boolean' ? params.paid : null,
user_id: params?.user_id ?? null,
content_hash: params?.content_hash ?? null,
};
const paramsKey = JSON.stringify(paramsKeyPayload);
const queryParams: Record<string, string | number | undefined> = {
limit: params?.limit,
offset: params?.offset,
search: normalizedSearch ?? undefined,
type: typeValue ?? undefined,
user_id: params?.user_id,
content_hash: params?.content_hash ?? undefined,
};
if (typeof params?.paid === 'boolean') {
queryParams.paid = params.paid ? 1 : 0;
}
return useQuery<AdminStarsResponse, AxiosError, AdminStarsResponse, AdminStarsQueryKey>(
['admin', 'stars', paramsKey],
async () => {
const { data } = await request.get<AdminStarsResponse>('/admin.stars', {
params: queryParams,
});
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminEvents = (
params?: AdminEventsQueryParams,
options?: QueryOptions<AdminEventsResponse, AdminEventsQueryKey>,
) => {
const normalizedSearch = params?.search?.trim() || null;
const typeValue = Array.isArray(params?.type)
? params.type.filter(Boolean).join(',')
: params?.type ?? null;
const statusValue = Array.isArray(params?.status)
? params.status.filter(Boolean).join(',')
: params?.status ?? null;
const originValue = Array.isArray(params?.origin)
? params.origin.filter(Boolean).join(',')
: params?.origin ?? null;
const paramsKeyPayload = {
limit: params?.limit ?? null,
offset: params?.offset ?? null,
search: normalizedSearch,
type: typeValue,
status: statusValue,
origin: originValue,
};
const paramsKey = JSON.stringify(paramsKeyPayload);
const queryParams: Record<string, string | number | undefined> = {
limit: params?.limit,
offset: params?.offset,
search: normalizedSearch ?? undefined,
type: typeValue ?? undefined,
status: statusValue ?? undefined,
origin: originValue ?? undefined,
};
return useQuery<AdminEventsResponse, AxiosError, AdminEventsResponse, AdminEventsQueryKey>(
['admin', 'events', paramsKey],
async () => {
const { data } = await request.get<AdminEventsResponse>('/admin.events', {
params: queryParams,
});
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminSystem = (
options?: QueryOptions<AdminSystemResponse, ['admin', 'system']>,
) => {
return useQuery<AdminSystemResponse, AxiosError, AdminSystemResponse, ['admin', 'system']>(
['admin', 'system'],
async () => {
const { data } = await request.get<AdminSystemResponse>('/admin.system');
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminBlockchain = (
options?: QueryOptions<AdminBlockchainResponse, ['admin', 'blockchain']>,
) => {
return useQuery<AdminBlockchainResponse, AxiosError, AdminBlockchainResponse, ['admin', 'blockchain']>(
['admin', 'blockchain'],
async () => {
const { data } = await request.get<AdminBlockchainResponse>('/admin.blockchain');
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminNodes = (
options?: QueryOptions<AdminNodesResponse, ['admin', 'nodes']>,
) => {
return useQuery<AdminNodesResponse, AxiosError, AdminNodesResponse, ['admin', 'nodes']>(
['admin', 'nodes'],
async () => {
const { data } = await request.get<AdminNodesResponse>('/admin.nodes');
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export const useAdminStatus = (
options?: QueryOptions<AdminStatusResponse, ['admin', 'status']>,
) => {
return useQuery<AdminStatusResponse, AxiosError, AdminStatusResponse, ['admin', 'status']>(
['admin', 'status'],
async () => {
const { data } = await request.get<AdminStatusResponse>('/admin.status');
return data;
},
{
...defaultQueryOptions,
...options,
},
);
};
export type AdminLoginResponse = {
ok: true;
cookie_name?: string;
header_name?: string;
max_age?: number;
};
export const useAdminLogin = (
options?: MutationOptions<AdminLoginResponse, { secret: string }>,
) => {
return useMutation<AdminLoginResponse, AxiosError, { secret: string }>(
async ({ secret }) => {
const { data } = await request.post<AdminLoginResponse>('/admin.login', { secret });
persistAdminAuth({
token: secret,
headerName: data.header_name,
cookieName: data.cookie_name,
maxAge: data.max_age,
});
return data;
},
options,
);
};
export const useAdminLogout = (
options?: MutationOptions<{ ok: true }, void>,
) => {
return useMutation<{ ok: true }, AxiosError, void>(
async () => {
const { data } = await request.post<{ ok: true }>('/admin.logout');
clearAdminAuth();
return data;
},
options,
);
};
export const useAdminCacheSetLimits = (
options?: MutationOptions<{ ok: true }, AdminCacheSetLimitsPayload>,
) => {
return useMutation<{ ok: true }, AxiosError, AdminCacheSetLimitsPayload>(
async (payload) => {
const { data } = await request.post<{ ok: true }>('/admin.cache.setLimits', payload);
return data;
},
options,
);
};
export const useAdminCacheCleanup = (
options?: MutationOptions<{ ok: true; removed?: number }, AdminCacheCleanupPayload>,
) => {
return useMutation<{ ok: true; removed?: number }, AxiosError, AdminCacheCleanupPayload>(
async (payload) => {
const { data } = await request.post<{ ok: true; removed?: number }>('/admin.cache.cleanup', payload);
return data;
},
options,
);
};
export const useAdminSyncSetLimits = (
options?: MutationOptions<{ ok: true }, AdminSyncSetLimitsPayload>,
) => {
return useMutation<{ ok: true }, AxiosError, AdminSyncSetLimitsPayload>(
async (payload) => {
const { data } = await request.post<{ ok: true }>('/admin.sync.setLimits', payload);
return data;
},
options,
);
};
export const useAdminNodeSetRole = (
options?: MutationOptions<{ ok: true; node: { ip: string | null; public_key: string | null; role: string } }, AdminNodeSetRolePayload>,
) => {
return useMutation<
{ ok: true; node: { ip: string | null; public_key: string | null; role: string } },
AxiosError,
AdminNodeSetRolePayload
>(
async (payload) => {
const { data } = await request.post<{ ok: true; node: { ip: string | null; public_key: string | null; role: string } }>(
'/admin.node.setRole',
payload,
);
return data;
},
options,
);
};
export const useAdminSetUserAdmin = (
options?: MutationOptions<{ ok: true; user: { id: number; is_admin: boolean } }, { user_id: number; is_admin: boolean }>,
) => {
return useMutation<{ ok: true; user: { id: number; is_admin: boolean } }, AxiosError, { user_id: number; is_admin: boolean }>(
async (payload) => {
const { data } = await request.post<{ ok: true; user: { id: number; is_admin: boolean } }>('/admin.users.setAdmin', payload);
return data;
},
options,
);
};
export const useAdminSyncLimits = () => {
const cacheSetLimits = useAdminCacheSetLimits();
const syncSetLimits = useAdminSyncSetLimits();
return { cacheSetLimits, syncSetLimits };
};
export const isUnauthorizedError = (error: unknown) => {
if (!error) {
return false;
}
if (axios.isAxiosError(error)) {
return error.response?.status === 401;
}
return false;
};