Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1be2708d15 | |||
| 037ea2da32 |
@@ -10,6 +10,7 @@ dist
|
|||||||
|
|
||||||
# Secrets — never commit
|
# Secrets — never commit
|
||||||
.gitea-token
|
.gitea-token
|
||||||
|
.update-token
|
||||||
|
|
||||||
# VS Code user settings (workspace settings/.vscode/launch.json are committed)
|
# VS Code user settings (workspace settings/.vscode/launch.json are committed)
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
|
|||||||
@@ -1,10 +1,28 @@
|
|||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
import { existsSync, readFileSync } from 'fs'
|
||||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
// Read-only Gitea token compiled into the main bundle so the auto-updater can
|
||||||
|
// read the PRIVATE release repo without user setup (see config.ts BAKED_UPDATE_TOKEN).
|
||||||
|
// Source order: AEROFETCH_UPDATE_TOKEN env var (CI/secret), else a gitignored
|
||||||
|
// .update-token file (local builds). Absent → empty string → no token baked in.
|
||||||
|
// Keep this a dedicated read-only service-account token; the shipped bundle is public.
|
||||||
|
function bakedUpdateToken(): string {
|
||||||
|
const fromEnv = process.env.AEROFETCH_UPDATE_TOKEN?.trim()
|
||||||
|
if (fromEnv) return fromEnv
|
||||||
|
const file = resolve('.update-token')
|
||||||
|
return existsSync(file) ? readFileSync(file, 'utf8').trim() : ''
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
main: {
|
main: {
|
||||||
plugins: [externalizeDepsPlugin()],
|
plugins: [externalizeDepsPlugin()],
|
||||||
|
// Textually replaces the __AEROFETCH_UPDATE_TOKEN__ identifier in main-process
|
||||||
|
// code with the token literal at build time — value never lands in source/git.
|
||||||
|
define: {
|
||||||
|
__AEROFETCH_UPDATE_TOKEN__: JSON.stringify(bakedUpdateToken())
|
||||||
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@shared': resolve('src/shared')
|
'@shared': resolve('src/shared')
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "aerofetch",
|
"name": "aerofetch",
|
||||||
"version": "0.6.0",
|
"version": "0.6.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "aerofetch",
|
"name": "aerofetch",
|
||||||
"version": "0.6.0",
|
"version": "0.6.1",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron-toolkit/utils": "^4.0.0",
|
"@electron-toolkit/utils": "^4.0.0",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aerofetch",
|
"name": "aerofetch",
|
||||||
"version": "0.6.0",
|
"version": "0.6.1",
|
||||||
"description": "A yt-dlp frontend for Windows",
|
"description": "A yt-dlp frontend for Windows",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "AeroFetch",
|
"author": "AeroFetch",
|
||||||
|
|||||||
+24
-3
@@ -4,12 +4,33 @@
|
|||||||
* timeouts, caps, tickers) and from user settings (settings.ts). Retarget a
|
* timeouts, caps, tickers) and from user settings (settings.ts). Retarget a
|
||||||
* fork's update source by editing these three values.
|
* fork's update source by editing these three values.
|
||||||
*
|
*
|
||||||
* IMPORTANT: the update repo's releases must be ANONYMOUSLY readable — i.e. a
|
* The update repo is PRIVATE, so the release API + downloads require a token.
|
||||||
* public repo on a Gitea instance that permits anonymous API + downloads.
|
* A build-time read-only token (BAKED_UPDATE_TOKEN below) lets a shipped client
|
||||||
* AeroFetch never ships a token; on a sign-in-required instance the update
|
* reach it without the user configuring anything; a user-set updateToken in
|
||||||
|
* Settings still takes precedence. On a build with no token baked in, the update
|
||||||
* check simply reports that it couldn't reach the server.
|
* check simply reports that it couldn't reach the server.
|
||||||
*/
|
*/
|
||||||
export const UPDATE_HOST = 'https://gitea.netbird.zimspace.uk:5938'
|
export const UPDATE_HOST = 'https://gitea.netbird.zimspace.uk:5938'
|
||||||
export const UPDATE_OWNER = 'debont80'
|
export const UPDATE_OWNER = 'debont80'
|
||||||
export const UPDATE_REPO = 'AeroFetch'
|
export const UPDATE_REPO = 'AeroFetch'
|
||||||
export const RELEASE_API = `${UPDATE_HOST}/api/v1/repos/${UPDATE_OWNER}/${UPDATE_REPO}/releases/latest`
|
export const RELEASE_API = `${UPDATE_HOST}/api/v1/repos/${UPDATE_OWNER}/${UPDATE_REPO}/releases/latest`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read-only Gitea token baked in at build time so the auto-updater can read the
|
||||||
|
* PRIVATE release repo without each user pasting a token into Settings. Injected
|
||||||
|
* by electron.vite.config's `define` from the AEROFETCH_UPDATE_TOKEN env var (or a
|
||||||
|
* gitignored .update-token file) — so the real value lives only in the built
|
||||||
|
* bundle, never in source or git.
|
||||||
|
*
|
||||||
|
* SECURITY: a shipped client is decompilable, so treat this as PUBLIC. It MUST be
|
||||||
|
* a token from a dedicated service account with read-only access to ONLY this repo
|
||||||
|
* — never a personal/push-capable token. The user's own updateToken overrides it
|
||||||
|
* (see authHeader in updater.ts), so a private fork can point elsewhere.
|
||||||
|
*
|
||||||
|
* `__AEROFETCH_UPDATE_TOKEN__` is a `define`-replaced literal in built code; under
|
||||||
|
* plain vitest (no define) the identifier is undeclared, so the `typeof` guard
|
||||||
|
* keeps this from throwing and falls back to empty (no token).
|
||||||
|
*/
|
||||||
|
declare const __AEROFETCH_UPDATE_TOKEN__: string
|
||||||
|
export const BAKED_UPDATE_TOKEN: string =
|
||||||
|
typeof __AEROFETCH_UPDATE_TOKEN__ === 'string' ? __AEROFETCH_UPDATE_TOKEN__ : ''
|
||||||
|
|||||||
+7
-5
@@ -4,7 +4,7 @@ import { stat, unlink } from 'fs/promises'
|
|||||||
import { join, normalize, dirname } from 'path'
|
import { join, normalize, dirname } from 'path'
|
||||||
import { createHash } from 'crypto'
|
import { createHash } from 'crypto'
|
||||||
import { getSettings } from './settings'
|
import { getSettings } from './settings'
|
||||||
import { UPDATE_HOST, RELEASE_API } from './config'
|
import { UPDATE_HOST, RELEASE_API, BAKED_UPDATE_TOKEN } from './config'
|
||||||
import {
|
import {
|
||||||
IpcChannels,
|
IpcChannels,
|
||||||
type AppUpdateInfo,
|
type AppUpdateInfo,
|
||||||
@@ -13,9 +13,11 @@ import {
|
|||||||
} from '@shared/ipc'
|
} from '@shared/ipc'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorization header for the update host. Empty unless the user has set an
|
* Authorization header for the update host. The user's updateToken from Settings
|
||||||
* updateToken in Settings — needed when the release repo is private or the Gitea
|
* wins if set (lets a private fork target its own repo); otherwise it falls back
|
||||||
* instance requires sign-in for anonymous access (the default on this instance).
|
* to BAKED_UPDATE_TOKEN — the read-only token compiled in at build time so a
|
||||||
|
* stock client can read the private release repo with no setup. Empty (no header)
|
||||||
|
* only when neither is present.
|
||||||
*
|
*
|
||||||
* The token must never reach an origin other than the host-pinned UPDATE_HOST.
|
* The token must never reach an origin other than the host-pinned UPDATE_HOST.
|
||||||
* Every request that carries it guards against that on its own terms: the REST
|
* Every request that carries it guards against that on its own terms: the REST
|
||||||
@@ -24,7 +26,7 @@ import {
|
|||||||
* a redirect can't bounce the header to another host on any path.
|
* a redirect can't bounce the header to another host on any path.
|
||||||
*/
|
*/
|
||||||
function authHeader(): Record<string, string> {
|
function authHeader(): Record<string, string> {
|
||||||
const tok = getSettings().updateToken?.trim()
|
const tok = getSettings().updateToken?.trim() || BAKED_UPDATE_TOKEN
|
||||||
return tok ? { Authorization: `token ${tok}` } : {}
|
return tok ? { Authorization: `token ${tok}` } : {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user