mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-18 10:40:50 +08:00
Revert "feat(auth-files): add external migration modal for antigravity credentials"
This reverts commit 2086c348a9.
This commit is contained in:
@@ -330,17 +330,6 @@
|
|||||||
"title": "Auth Files Management",
|
"title": "Auth Files Management",
|
||||||
"title_section": "Auth Files",
|
"title_section": "Auth Files",
|
||||||
"description": "Manage all CLI Proxy JSON auth files here (e.g. Qwen, Gemini, Vertex). Uploading a credential immediately enables the corresponding AI integration.",
|
"description": "Manage all CLI Proxy JSON auth files here (e.g. Qwen, Gemini, Vertex). Uploading a credential immediately enables the corresponding AI integration.",
|
||||||
"migrate_button": "Import from external?",
|
|
||||||
"migrate_title": "External Migration",
|
|
||||||
"migrate_subtitle": "gcli2api",
|
|
||||||
"migrate_email_label": "Email",
|
|
||||||
"migrate_email_placeholder": "Enter email to generate the credential",
|
|
||||||
"migrate_email_hint": "Used for the email field and the file name",
|
|
||||||
"migrate_email_required": "Enter an email first",
|
|
||||||
"migrate_upload_button": "Antigrvity Credential",
|
|
||||||
"migrate_parse_error": "Unable to parse credential file",
|
|
||||||
"migrate_missing_fields": "Credential missing required fields: {{fields}}",
|
|
||||||
"migrate_success": "Migration complete. Credential uploaded.",
|
|
||||||
"upload_button": "Upload File",
|
"upload_button": "Upload File",
|
||||||
"delete_all_button": "Delete All",
|
"delete_all_button": "Delete All",
|
||||||
"empty_title": "No Auth Files",
|
"empty_title": "No Auth Files",
|
||||||
|
|||||||
@@ -330,17 +330,6 @@
|
|||||||
"title": "认证文件管理",
|
"title": "认证文件管理",
|
||||||
"title_section": "认证文件",
|
"title_section": "认证文件",
|
||||||
"description": "这里集中管理 CLI Proxy 支持的所有 JSON 认证文件(如 Qwen、Gemini、Vertex 等),上传后即可在运行时启用相应的 AI 服务。",
|
"description": "这里集中管理 CLI Proxy 支持的所有 JSON 认证文件(如 Qwen、Gemini、Vertex 等),上传后即可在运行时启用相应的 AI 服务。",
|
||||||
"migrate_button": "从外部迁移?",
|
|
||||||
"migrate_title": "外部迁移",
|
|
||||||
"migrate_subtitle": "gcli2api",
|
|
||||||
"migrate_email_label": "邮箱",
|
|
||||||
"migrate_email_placeholder": "输入邮箱用于生成认证文件",
|
|
||||||
"migrate_email_hint": "该邮箱将写入凭证并生成文件名",
|
|
||||||
"migrate_email_required": "请先填写邮箱",
|
|
||||||
"migrate_upload_button": "Antigrvity凭证",
|
|
||||||
"migrate_parse_error": "无法解析凭证文件",
|
|
||||||
"migrate_missing_fields": "凭证缺少必要字段: {{fields}}",
|
|
||||||
"migrate_success": "迁移完成,凭证已上传",
|
|
||||||
"upload_button": "上传文件",
|
"upload_button": "上传文件",
|
||||||
"delete_all_button": "删除全部",
|
"delete_all_button": "删除全部",
|
||||||
"empty_title": "暂无认证文件",
|
"empty_title": "暂无认证文件",
|
||||||
|
|||||||
@@ -32,23 +32,6 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.migrationContent {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: $spacing-md;
|
|
||||||
|
|
||||||
:global(.form-group) {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.migrationSubtitle {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-tertiary);
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titleWrapper {
|
.titleWrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ const OAUTH_PROVIDER_EXCLUDES = new Set(['all', 'unknown', 'empty']);
|
|||||||
const MIN_CARD_PAGE_SIZE = 3;
|
const MIN_CARD_PAGE_SIZE = 3;
|
||||||
const MAX_CARD_PAGE_SIZE = 30;
|
const MAX_CARD_PAGE_SIZE = 30;
|
||||||
const MAX_AUTH_FILE_SIZE = 50 * 1024;
|
const MAX_AUTH_FILE_SIZE = 50 * 1024;
|
||||||
const MIGRATION_EXPIRES_IN = 3599;
|
|
||||||
|
|
||||||
const clampCardPageSize = (value: number) =>
|
const clampCardPageSize = (value: number) =>
|
||||||
Math.min(MAX_CARD_PAGE_SIZE, Math.max(MIN_CARD_PAGE_SIZE, Math.round(value)));
|
Math.min(MAX_CARD_PAGE_SIZE, Math.max(MIN_CARD_PAGE_SIZE, Math.round(value)));
|
||||||
@@ -179,10 +178,6 @@ export function AuthFilesPage() {
|
|||||||
const [deletingAll, setDeletingAll] = useState(false);
|
const [deletingAll, setDeletingAll] = useState(false);
|
||||||
const [keyStats, setKeyStats] = useState<KeyStats>({ bySource: {}, byAuthIndex: {} });
|
const [keyStats, setKeyStats] = useState<KeyStats>({ bySource: {}, byAuthIndex: {} });
|
||||||
const [usageDetails, setUsageDetails] = useState<UsageDetail[]>([]);
|
const [usageDetails, setUsageDetails] = useState<UsageDetail[]>([]);
|
||||||
|
|
||||||
const [migrationModalOpen, setMigrationModalOpen] = useState(false);
|
|
||||||
const [migrationEmail, setMigrationEmail] = useState('');
|
|
||||||
const [migrationUploading, setMigrationUploading] = useState(false);
|
|
||||||
|
|
||||||
// 详情弹窗相关
|
// 详情弹窗相关
|
||||||
const [detailModalOpen, setDetailModalOpen] = useState(false);
|
const [detailModalOpen, setDetailModalOpen] = useState(false);
|
||||||
@@ -214,7 +209,6 @@ export function AuthFilesPage() {
|
|||||||
const [savingMappings, setSavingMappings] = useState(false);
|
const [savingMappings, setSavingMappings] = useState(false);
|
||||||
|
|
||||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
const migrationFileInputRef = useRef<HTMLInputElement | null>(null);
|
|
||||||
const loadingKeyStatsRef = useRef(false);
|
const loadingKeyStatsRef = useRef(false);
|
||||||
const excludedUnsupportedRef = useRef(false);
|
const excludedUnsupportedRef = useRef(false);
|
||||||
const mappingsUnsupportedRef = useRef(false);
|
const mappingsUnsupportedRef = useRef(false);
|
||||||
@@ -431,13 +425,9 @@ export function AuthFilesPage() {
|
|||||||
const handleUploadClick = () => {
|
const handleUploadClick = () => {
|
||||||
fileInputRef.current?.click();
|
fileInputRef.current?.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMigrationFilePick = () => {
|
|
||||||
migrationFileInputRef.current?.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理文件上传(支持多选)
|
// 处理文件上传(支持多选)
|
||||||
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const fileList = event.target.files;
|
const fileList = event.target.files;
|
||||||
if (!fileList || fileList.length === 0) return;
|
if (!fileList || fileList.length === 0) return;
|
||||||
|
|
||||||
@@ -500,102 +490,8 @@ export function AuthFilesPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setUploading(false);
|
setUploading(false);
|
||||||
event.target.value = '';
|
event.target.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMigrationFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const file = event.target.files?.[0];
|
|
||||||
if (!file) return;
|
|
||||||
|
|
||||||
const trimmedEmail = migrationEmail.trim();
|
|
||||||
if (!trimmedEmail) {
|
|
||||||
showNotification(t('auth_files.migrate_email_required'), 'warning');
|
|
||||||
event.target.value = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file.name.endsWith('.json')) {
|
|
||||||
showNotification(t('auth_files.upload_error_json'), 'error');
|
|
||||||
event.target.value = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.size > MAX_AUTH_FILE_SIZE) {
|
|
||||||
showNotification(
|
|
||||||
t('auth_files.upload_error_size', { maxSize: formatFileSize(MAX_AUTH_FILE_SIZE) }),
|
|
||||||
'error'
|
|
||||||
);
|
|
||||||
event.target.value = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setMigrationUploading(true);
|
|
||||||
try {
|
|
||||||
const raw = await file.text();
|
|
||||||
let payloadSource: Record<string, unknown> | null = null;
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(raw);
|
|
||||||
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
||||||
payloadSource = parsed as Record<string, unknown>;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
payloadSource = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!payloadSource) {
|
|
||||||
showNotification(t('auth_files.migrate_parse_error'), 'error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = typeof payloadSource.token === 'string' ? payloadSource.token : '';
|
|
||||||
const refreshToken =
|
|
||||||
typeof payloadSource.refresh_token === 'string' ? payloadSource.refresh_token : '';
|
|
||||||
const projectId = typeof payloadSource.project_id === 'string' ? payloadSource.project_id : '';
|
|
||||||
const expiry = typeof payloadSource.expiry === 'string' ? payloadSource.expiry : '';
|
|
||||||
|
|
||||||
const missingFields: string[] = [];
|
|
||||||
if (!token) missingFields.push('token');
|
|
||||||
if (!expiry) missingFields.push('expiry');
|
|
||||||
if (!refreshToken) missingFields.push('refresh_token');
|
|
||||||
if (!projectId) missingFields.push('project_id');
|
|
||||||
|
|
||||||
if (missingFields.length > 0) {
|
|
||||||
showNotification(
|
|
||||||
t('auth_files.migrate_missing_fields', { fields: missingFields.join(', ') }),
|
|
||||||
'error'
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const migratedPayload = {
|
|
||||||
access_token: token,
|
|
||||||
email: trimmedEmail,
|
|
||||||
expired: expiry,
|
|
||||||
expires_in: MIGRATION_EXPIRES_IN,
|
|
||||||
project_id: projectId,
|
|
||||||
refresh_token: refreshToken,
|
|
||||||
timestamp: Date.now(),
|
|
||||||
type: 'antigravity'
|
|
||||||
};
|
|
||||||
|
|
||||||
const fileName = `antigravity-${trimmedEmail.replace(/@/g, '_')}.json`;
|
|
||||||
const migratedFile = new File([JSON.stringify(migratedPayload)], fileName, {
|
|
||||||
type: 'application/json'
|
|
||||||
});
|
|
||||||
|
|
||||||
await authFilesApi.upload(migratedFile);
|
|
||||||
showNotification(t('auth_files.migrate_success'), 'success');
|
|
||||||
await loadFiles();
|
|
||||||
await loadKeyStats();
|
|
||||||
setMigrationModalOpen(false);
|
|
||||||
} catch (err: unknown) {
|
|
||||||
const errorMessage = err instanceof Error ? err.message : '';
|
|
||||||
showNotification(`${t('notification.upload_failed')}: ${errorMessage}`, 'error');
|
|
||||||
} finally {
|
|
||||||
setMigrationUploading(false);
|
|
||||||
event.target.value = '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 删除单个文件
|
// 删除单个文件
|
||||||
const handleDelete = async (name: string) => {
|
const handleDelete = async (name: string) => {
|
||||||
@@ -1119,14 +1015,6 @@ export function AuthFilesPage() {
|
|||||||
title={titleNode}
|
title={titleNode}
|
||||||
extra={
|
extra={
|
||||||
<div className={styles.headerActions}>
|
<div className={styles.headerActions}>
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => setMigrationModalOpen(true)}
|
|
||||||
disabled={disableControls}
|
|
||||||
>
|
|
||||||
{t('auth_files.migrate_button')}
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -1147,10 +1035,10 @@ export function AuthFilesPage() {
|
|||||||
<Button size="sm" onClick={handleUploadClick} disabled={disableControls || uploading} loading={uploading}>
|
<Button size="sm" onClick={handleUploadClick} disabled={disableControls || uploading} loading={uploading}>
|
||||||
{t('auth_files.upload_button')}
|
{t('auth_files.upload_button')}
|
||||||
</Button>
|
</Button>
|
||||||
<input
|
<input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
type="file"
|
type="file"
|
||||||
accept=".json,application/json"
|
accept=".json,application/json"
|
||||||
multiple
|
multiple
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
onChange={handleFileChange}
|
onChange={handleFileChange}
|
||||||
@@ -1229,48 +1117,9 @@ export function AuthFilesPage() {
|
|||||||
{t('auth_files.pagination_next')}
|
{t('auth_files.pagination_next')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Modal
|
|
||||||
open={migrationModalOpen}
|
|
||||||
onClose={() => setMigrationModalOpen(false)}
|
|
||||||
title={t('auth_files.migrate_title')}
|
|
||||||
footer={
|
|
||||||
<Button variant="secondary" onClick={() => setMigrationModalOpen(false)} disabled={migrationUploading}>
|
|
||||||
{t('common.close')}
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className={styles.migrationContent}>
|
|
||||||
<div className={styles.migrationSubtitle}>{t('auth_files.migrate_subtitle')}</div>
|
|
||||||
<Input
|
|
||||||
label={t('auth_files.migrate_email_label')}
|
|
||||||
hint={t('auth_files.migrate_email_hint')}
|
|
||||||
placeholder={t('auth_files.migrate_email_placeholder')}
|
|
||||||
value={migrationEmail}
|
|
||||||
onChange={(e) => setMigrationEmail(e.target.value)}
|
|
||||||
disabled={migrationUploading}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
fullWidth
|
|
||||||
onClick={handleMigrationFilePick}
|
|
||||||
disabled={disableControls || migrationUploading}
|
|
||||||
loading={migrationUploading}
|
|
||||||
>
|
|
||||||
{t('auth_files.migrate_upload_button')}
|
|
||||||
</Button>
|
|
||||||
<input
|
|
||||||
ref={migrationFileInputRef}
|
|
||||||
type="file"
|
|
||||||
accept=".json,application/json"
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
onChange={handleMigrationFileChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
{/* OAuth 排除列表卡片 */}
|
{/* OAuth 排除列表卡片 */}
|
||||||
<Card
|
<Card
|
||||||
title={t('oauth_excluded.title')}
|
title={t('oauth_excluded.title')}
|
||||||
|
|||||||
Reference in New Issue
Block a user