feat: sing-box Clash template support + Docker CI + frontend scaffold
- Clash→sing-box template conversion engine (singbox_template.go) - Auto-map 40+ Clash rule-providers to sing-box .srs binary rule-sets - Fix sing-box 1.11+/1.12+ migrations (sniff/block/WireGuard/DNS/rule_set) - Fix WireGuard URI '+' parsing bug (rawParamGet) - Add REJECT block outbound for selector group references - Skip rules referencing rule-sets with no sing-box equivalent - Verified: sing-box run succeeds with ACL4SSR template (16 rule-sets loaded) - Add Dockerfile (multi-stage Go build) - Add GitHub Actions workflow (multi-arch: amd64+arm64, push to ghcr.io) - Add frontend scaffold (Vue3 + Vite + Tailwind)
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Token management — the page MUST be opened with ?token=xxx
|
||||
* The token is validated against the backend /api/env endpoint.
|
||||
* If invalid or missing, the router guard shows a 404 page.
|
||||
*/
|
||||
|
||||
const TOKEN_KEY = 'sub_store_admin_token'
|
||||
const VALIDATED_KEY = 'sub_store_token_validated'
|
||||
|
||||
/** Extract token from URL query string */
|
||||
export function getTokenFromURL() {
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
return params.get('token') || ''
|
||||
}
|
||||
|
||||
/** Store token in localStorage (persists across page reloads) */
|
||||
export function storeToken(token) {
|
||||
if (token) {
|
||||
localStorage.setItem(TOKEN_KEY, token)
|
||||
localStorage.setItem(VALIDATED_KEY, 'true')
|
||||
}
|
||||
}
|
||||
|
||||
/** Get stored token */
|
||||
export function getStoredToken() {
|
||||
return localStorage.getItem(TOKEN_KEY) || ''
|
||||
}
|
||||
|
||||
/** Check if token has been validated */
|
||||
export function isTokenValidated() {
|
||||
return localStorage.getItem(VALIDATED_KEY) === 'true'
|
||||
}
|
||||
|
||||
/** Clear token (logout) */
|
||||
export function clearToken() {
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
localStorage.removeItem(VALIDATED_KEY)
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate token against backend by calling /api/env.
|
||||
* Returns true if token is valid, false otherwise.
|
||||
*/
|
||||
export async function validateToken(token) {
|
||||
if (!token) return false
|
||||
try {
|
||||
const base = (window.SUB_STORE_CONFIG?.apiBaseUrl) || ''
|
||||
const resp = await fetch(`${base}/api/env?token=${encodeURIComponent(token)}`)
|
||||
if (!resp.ok) return false
|
||||
const data = await resp.json()
|
||||
return data.status === 'success'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective token: from URL if present, otherwise from storage.
|
||||
* This is used by the API layer to always send the token.
|
||||
*/
|
||||
export function getEffectiveToken() {
|
||||
const urlToken = getTokenFromURL()
|
||||
if (urlToken) return urlToken
|
||||
return getStoredToken()
|
||||
}
|
||||
Reference in New Issue
Block a user