mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-21 12:06:08 +00:00
fix(settings): normalize API token timestamps (#5599)
* fix(settings): normalize API token timestamps * refactor(api-token): share timestamp threshold --------- Co-authored-by: Tomilla <5007859+Tomilla@users.noreply.github.com>
This commit is contained in:
@@ -13,7 +13,7 @@ import {
|
||||
message,
|
||||
} from 'antd';
|
||||
import { ApiOutlined, SafetyOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { ClipboardManager, HttpUtil, RandomUtil } from '@/utils';
|
||||
import { ClipboardManager, HttpUtil, IntlUtil, RandomUtil } from '@/utils';
|
||||
import type { AllSetting } from '@/models/setting';
|
||||
import { SettingListItem } from '@/components/ui';
|
||||
import { useMediaQuery } from '@/hooks/useMediaQuery';
|
||||
@@ -39,6 +39,12 @@ interface SecurityTabProps {
|
||||
updateSetting: (patch: Partial<AllSetting>) => void;
|
||||
}
|
||||
|
||||
const UNIX_MILLISECONDS_THRESHOLD = 100_000_000_000;
|
||||
|
||||
function apiTokenCreatedAtMilliseconds(createdAt: number): number {
|
||||
return createdAt < UNIX_MILLISECONDS_THRESHOLD ? createdAt * 1000 : createdAt;
|
||||
}
|
||||
|
||||
type TfaType = 'set' | 'confirm';
|
||||
|
||||
interface TfaState {
|
||||
@@ -194,7 +200,7 @@ export default function SecurityTab({ allSetting, updateSetting }: SecurityTabPr
|
||||
|
||||
function formatTokenDate(ts: number): string {
|
||||
if (!ts) return '';
|
||||
return new Date(ts * 1000).toLocaleString();
|
||||
return IntlUtil.formatDate(apiTokenCreatedAtMilliseconds(ts));
|
||||
}
|
||||
|
||||
function toggleTwoFactor() {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import type { AllSetting } from '@/models/setting';
|
||||
import SecurityTab from '@/pages/settings/SecurityTab';
|
||||
import { HttpUtil } from '@/utils';
|
||||
|
||||
describe('API token creation date', () => {
|
||||
it('renders both API seconds and legacy millisecond timestamps', async () => {
|
||||
vi.spyOn(HttpUtil, 'get').mockResolvedValueOnce({
|
||||
success: true,
|
||||
msg: '',
|
||||
obj: [
|
||||
{
|
||||
id: 2,
|
||||
name: 'seconds-token',
|
||||
enabled: true,
|
||||
createdAt: 1782485394,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'legacy-milliseconds-token',
|
||||
enabled: true,
|
||||
createdAt: 1782485394270,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
render(<SecurityTab allSetting={{} as AllSetting} updateSetting={vi.fn()} />);
|
||||
fireEvent.click(screen.getByRole('tab', { name: /API Token/ }));
|
||||
|
||||
expect(await screen.findByText('seconds-token')).toBeTruthy();
|
||||
expect(screen.getByText('legacy-milliseconds-token')).toBeTruthy();
|
||||
expect(screen.getAllByText(/2026/)).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user