release: v1.1.3 — dual-domain separation and URL options
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s

Add admin/image domain separation with host isolation middleware,
optional hide-folder public URLs, GitHub release update check, and
Lucky/Nginx deployment docs. Switch license to GPL-3.0-only.
This commit is contained in:
O96u committed 2026-08-27 12:13:58 +08:00
1 parent 55effa204e
commit d8c1303c32
41 files changed
+2170 -299

No files matched your search

+56 -2
View File
@@ -8,18 +8,23 @@ import {
getAutoDeleteDays,
getAutoDeleteDaysSource,
getRefererSource,
getSiteBaseUrl,
getSiteBaseUrlConfigured,
getSiteBaseUrlSource,
getWebpQuality,
getWebpQualitySource,
isApiUploadTokenEnvConfigured,
isAutoDeleteDaysEnvConfigured,
isRefererEnvConfigured,
isWebpQualityEnvConfigured
isWebpQualityEnvConfigured,
validateDomainSeparationPair
} from './env'
import {
getSetting,
SETTINGS_ALLOWED_REFERER_HOSTS,
SETTINGS_API_UPLOAD_TOKEN,
SETTINGS_AUTO_DELETE_DAYS,
SETTINGS_SITE_BASE_URL,
SETTINGS_WEBP_QUALITY,
generateApiUploadToken
} from './db'
@@ -34,9 +39,13 @@ vi.mock('./db', async (importOriginal) => {
})
vi.stubGlobal('useRuntimeConfig', () => ({
apiUploadToken: ''
apiUploadToken: '',
siteBaseUrl: '',
imageBaseUrl: ''
}))
vi.stubGlobal('getRequestURL', () => new URL('https://fallback.example.com'))
function mockEvent(): H3Event {
return {
node: { req: {}, res: {} },
@@ -201,3 +210,48 @@ describe('getAutoDeleteDays priority', () => {
expect(getAutoDeleteDaysSource()).toBe('default')
})
})
describe('getSiteBaseUrl priority', () => {
afterEach(() => {
vi.clearAllMocks()
delete process.env.SITE_BASE_URL
})
it('prefers database over environment variable', () => {
process.env.SITE_BASE_URL = 'https://env.example.com'
vi.mocked(getSetting).mockImplementation(key =>
key === SETTINGS_SITE_BASE_URL ? 'https://db.example.com' : null
)
const event = mockEvent()
expect(getSiteBaseUrlConfigured(event)).toBe('https://db.example.com')
expect(getSiteBaseUrlSource(event)).toBe('db')
expect(getSiteBaseUrl(event)).toBe('https://db.example.com')
})
it('falls back to request origin when unset', () => {
vi.mocked(getSetting).mockReturnValue(null)
const event = mockEvent()
expect(getSiteBaseUrl(event)).toBe('https://fallback.example.com')
expect(getSiteBaseUrlSource(event)).toBe('none')
})
})
describe('validateDomainSeparationPair', () => {
it('rejects missing values', () => {
expect(validateDomainSeparationPair('', 'https://pic.example.com')).toContain('同时填写')
})
it('rejects identical hostnames', () => {
expect(validateDomainSeparationPair(
'https://same.example.com',
'https://same.example.com'
)).toContain('相同主机名')
})
it('accepts different hostnames', () => {
expect(validateDomainSeparationPair(
'https://admin.example.com',
'https://pic.example.com'
)).toBeNull()
})
})