mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-16 12:42:06 +00:00
feat(plugin): support authenticated proxy (#3175)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: JellyBrick <shlee1503@naver.com> Co-authored-by: qiye45 <qiye45@users.noreply.github.com>
This commit is contained in:
@ -295,6 +295,7 @@
|
|||||||
"semver": "7.7.1",
|
"semver": "7.7.1",
|
||||||
"serve": "14.2.4",
|
"serve": "14.2.4",
|
||||||
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
|
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
|
||||||
|
"socks": "2.8.4",
|
||||||
"solid-floating-ui": "0.3.1",
|
"solid-floating-ui": "0.3.1",
|
||||||
"solid-js": "1.9.5",
|
"solid-js": "1.9.5",
|
||||||
"solid-styled-components": "0.28.5",
|
"solid-styled-components": "0.28.5",
|
||||||
|
|||||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -201,6 +201,9 @@ importers:
|
|||||||
simple-youtube-age-restriction-bypass:
|
simple-youtube-age-restriction-bypass:
|
||||||
specifier: github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9
|
specifier: github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9
|
||||||
version: https://codeload.github.com/organization/Simple-YouTube-Age-Restriction-Bypass/tar.gz/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6
|
version: https://codeload.github.com/organization/Simple-YouTube-Age-Restriction-Bypass/tar.gz/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6
|
||||||
|
socks:
|
||||||
|
specifier: ^2.8.4
|
||||||
|
version: 2.8.4
|
||||||
solid-floating-ui:
|
solid-floating-ui:
|
||||||
specifier: 0.3.1
|
specifier: 0.3.1
|
||||||
version: 0.3.1(@floating-ui/dom@1.6.13)(solid-js@1.9.5)
|
version: 0.3.1(@floating-ui/dom@1.6.13)(solid-js@1.9.5)
|
||||||
|
|||||||
@ -333,6 +333,30 @@
|
|||||||
"description": "Apply compression to audio (lowers the volume of the loudest parts of the signal and raises the volume of the softest parts)",
|
"description": "Apply compression to audio (lowers the volume of the loudest parts of the signal and raises the volume of the softest parts)",
|
||||||
"name": "Audio Compressor"
|
"name": "Audio Compressor"
|
||||||
},
|
},
|
||||||
|
"auth-proxy-adapter": {
|
||||||
|
"name": "Auth Proxy Adapter",
|
||||||
|
"description": "Support for the use of authentication proxy services",
|
||||||
|
"menu": {
|
||||||
|
"disable": "Disable Proxy Adapter",
|
||||||
|
"enable": "Enable Proxy Adapter",
|
||||||
|
"hostname": {
|
||||||
|
"label": "Hostname"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "Port"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"hostname": {
|
||||||
|
"title": "Proxy Hostname",
|
||||||
|
"label": "Enter hostname for local proxy server (requires restart):"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"title": "Proxy Port",
|
||||||
|
"label": "Enter port for local proxy server (requires restart):"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"blur-nav-bar": {
|
"blur-nav-bar": {
|
||||||
"description": "Makes navigation bar transparent and blurry",
|
"description": "Makes navigation bar transparent and blurry",
|
||||||
"name": "Blur Navigation Bar"
|
"name": "Blur Navigation Bar"
|
||||||
|
|||||||
@ -333,6 +333,30 @@
|
|||||||
"description": "对音频应用压缩(压低响亮部分,提升柔和部分)",
|
"description": "对音频应用压缩(压低响亮部分,提升柔和部分)",
|
||||||
"name": "音频压缩器"
|
"name": "音频压缩器"
|
||||||
},
|
},
|
||||||
|
"auth-proxy-adapter": {
|
||||||
|
"name": "认证代理适配",
|
||||||
|
"description": "支持使用需要身份验证的代理",
|
||||||
|
"menu": {
|
||||||
|
"disable": "禁用代理适配",
|
||||||
|
"enable": "启用代理适配",
|
||||||
|
"hostname": {
|
||||||
|
"label": "主机名"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"label": "端口"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"hostname": {
|
||||||
|
"title": "代理主机名",
|
||||||
|
"label": "请输入本地代理服务器的主机名(需要重启):"
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"title": "代理端口",
|
||||||
|
"label": "请输入本地代理服务器的端口号(需要重启):"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"blur-nav-bar": {
|
"blur-nav-bar": {
|
||||||
"description": "让导航栏透明及模糊",
|
"description": "让导航栏透明及模糊",
|
||||||
"name": "模糊导航栏"
|
"name": "模糊导航栏"
|
||||||
|
|||||||
21
src/index.ts
21
src/index.ts
@ -57,6 +57,8 @@ import { loadI18n, setLanguage, t } from '@/i18n';
|
|||||||
|
|
||||||
import ErrorHtmlAsset from '@assets/error.html?asset';
|
import ErrorHtmlAsset from '@assets/error.html?asset';
|
||||||
|
|
||||||
|
import { defaultAuthProxyConfig } from '@/plugins/auth-proxy-adapter/config';
|
||||||
|
|
||||||
import type { PluginConfig } from '@/types/plugins';
|
import type { PluginConfig } from '@/types/plugins';
|
||||||
|
|
||||||
if (!is.macOS()) {
|
if (!is.macOS()) {
|
||||||
@ -141,7 +143,24 @@ if (is.linux()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.get('options.proxy')) {
|
if (config.get('options.proxy')) {
|
||||||
app.commandLine.appendSwitch('proxy-server', config.get('options.proxy'));
|
const authProxyEnabled = config.plugins.isEnabled('auth-proxy-adapter');
|
||||||
|
|
||||||
|
let proxyToUse = '';
|
||||||
|
if (authProxyEnabled) {
|
||||||
|
// Use proxy from Auth-Proxy-Adapter plugin
|
||||||
|
const authProxyConfig = deepmerge(
|
||||||
|
defaultAuthProxyConfig,
|
||||||
|
config.get('plugins.auth-proxy-adapter') ?? {},
|
||||||
|
) as typeof defaultAuthProxyConfig;
|
||||||
|
|
||||||
|
const { hostname, port } = authProxyConfig;
|
||||||
|
proxyToUse = `socks5://${hostname}:${port}`;
|
||||||
|
} else if (config.get('options.proxy')) {
|
||||||
|
// Use global proxy settings
|
||||||
|
proxyToUse = config.get('options.proxy');
|
||||||
|
}
|
||||||
|
console.log(LoggerPrefix, `Using proxy: ${proxyToUse}`);
|
||||||
|
app.commandLine.appendSwitch('proxy-server', proxyToUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds debug features like hotkeys for triggering dev tools and reload
|
// Adds debug features like hotkeys for triggering dev tools and reload
|
||||||
|
|||||||
246
src/plugins/auth-proxy-adapter/backend/index.ts
Normal file
246
src/plugins/auth-proxy-adapter/backend/index.ts
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
import net from 'net';
|
||||||
|
|
||||||
|
import { SocksClient, SocksClientOptions } from 'socks';
|
||||||
|
|
||||||
|
import is from 'electron-is';
|
||||||
|
|
||||||
|
import { createBackend, LoggerPrefix } from '@/utils';
|
||||||
|
|
||||||
|
import { BackendType } from './types';
|
||||||
|
|
||||||
|
import config from '@/config';
|
||||||
|
|
||||||
|
import { AuthProxyConfig, defaultAuthProxyConfig } from '../config';
|
||||||
|
|
||||||
|
import type { BackendContext } from '@/types/contexts';
|
||||||
|
|
||||||
|
// Parsing the upstream authentication SOCK proxy URL
|
||||||
|
const parseSocksUrl = (socksUrl: string) => {
|
||||||
|
// Format: socks5://username:password@your_server_ip:port
|
||||||
|
|
||||||
|
const url = new URL(socksUrl);
|
||||||
|
return {
|
||||||
|
host: url.hostname,
|
||||||
|
port: parseInt(url.port, 10),
|
||||||
|
type: url.protocol === 'socks5:' ? 5 : 4,
|
||||||
|
username: url.username,
|
||||||
|
password: url.password,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const backend = createBackend<BackendType, AuthProxyConfig>({
|
||||||
|
async start(ctx: BackendContext<AuthProxyConfig>) {
|
||||||
|
const pluginConfig = await ctx.getConfig();
|
||||||
|
this.startServer(pluginConfig);
|
||||||
|
},
|
||||||
|
stop() {
|
||||||
|
this.stopServer();
|
||||||
|
},
|
||||||
|
onConfigChange(config: AuthProxyConfig) {
|
||||||
|
if (
|
||||||
|
this.oldConfig?.hostname === config.hostname &&
|
||||||
|
this.oldConfig?.port === config.port
|
||||||
|
) {
|
||||||
|
this.oldConfig = config;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.stopServer();
|
||||||
|
this.startServer(config);
|
||||||
|
|
||||||
|
this.oldConfig = config;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Custom
|
||||||
|
// Start proxy server - SOCKS5
|
||||||
|
startServer(serverConfig: AuthProxyConfig) {
|
||||||
|
if (this.server) {
|
||||||
|
this.stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { port, hostname } = serverConfig;
|
||||||
|
// Upstream proxy from system settings
|
||||||
|
const upstreamProxyUrl = config.get('options.proxy');
|
||||||
|
// Create SOCKS proxy server
|
||||||
|
const socksServer = net.createServer((socket) => {
|
||||||
|
socket.once('data', (chunk) => {
|
||||||
|
if (chunk[0] === 0x05) {
|
||||||
|
// SOCKS5
|
||||||
|
this.handleSocks5(socket, chunk, upstreamProxyUrl);
|
||||||
|
} else {
|
||||||
|
socket.end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('error', (err) => {
|
||||||
|
console.error(LoggerPrefix, '[SOCKS] Socket error:', err.message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen for errors
|
||||||
|
socksServer.on('error', (err) => {
|
||||||
|
console.error(LoggerPrefix, '[SOCKS Server Error]', err.message);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start server
|
||||||
|
socksServer.listen(port, hostname, () => {
|
||||||
|
console.log(LoggerPrefix, '===========================================');
|
||||||
|
console.log(
|
||||||
|
LoggerPrefix,
|
||||||
|
`[Auth-Proxy-Adapter] Enable SOCKS proxy at socks5://${hostname}:${port}`,
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
LoggerPrefix,
|
||||||
|
`[Auth-Proxy-Adapter] Using upstream proxy: ${upstreamProxyUrl}`,
|
||||||
|
);
|
||||||
|
console.log(LoggerPrefix, '===========================================');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.server = socksServer;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handle SOCKS5 request
|
||||||
|
handleSocks5(
|
||||||
|
clientSocket: net.Socket,
|
||||||
|
chunk: Buffer,
|
||||||
|
upstreamProxyUrl: string,
|
||||||
|
) {
|
||||||
|
// Handshake phase
|
||||||
|
const numMethods = chunk[1];
|
||||||
|
const methods = chunk.subarray(2, 2 + numMethods);
|
||||||
|
|
||||||
|
// Check if client supports no authentication method (0x00)
|
||||||
|
if (methods.includes(0x00)) {
|
||||||
|
// Reply to client, choose no authentication method
|
||||||
|
clientSocket.write(Buffer.from([0x05, 0x00]));
|
||||||
|
|
||||||
|
// Wait for client's connection request
|
||||||
|
clientSocket.once('data', (data) => {
|
||||||
|
this.processSocks5Request(clientSocket, data, upstreamProxyUrl);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Authentication methods not supported by the client
|
||||||
|
clientSocket.write(Buffer.from([0x05, 0xff]));
|
||||||
|
clientSocket.end();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handle SOCKS5 connection request
|
||||||
|
processSocks5Request(
|
||||||
|
clientSocket: net.Socket,
|
||||||
|
data: Buffer,
|
||||||
|
upstreamProxyUrl: string,
|
||||||
|
) {
|
||||||
|
// Parse target address and port
|
||||||
|
let targetHost, targetPort;
|
||||||
|
const cmd = data[1]; // Command: 0x01=CONNECT, 0x02=BIND, 0x03=UDP
|
||||||
|
const atyp = data[3]; // Address type: 0x01=IPv4, 0x03=Domain, 0x04=IPv6
|
||||||
|
|
||||||
|
if (cmd !== 0x01) {
|
||||||
|
// Currently only support CONNECT command
|
||||||
|
clientSocket.write(
|
||||||
|
Buffer.from([0x05, 0x07, 0x00, 0x01, 0, 0, 0, 0, 0, 0]),
|
||||||
|
);
|
||||||
|
clientSocket.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atyp === 0x01) {
|
||||||
|
// IPv4
|
||||||
|
targetHost = `${data[4]}.${data[5]}.${data[6]}.${data[7]}`;
|
||||||
|
targetPort = data.readUInt16BE(8);
|
||||||
|
} else if (atyp === 0x03) {
|
||||||
|
// Domain
|
||||||
|
const hostLen = data[4];
|
||||||
|
targetHost = data.subarray(5, 5 + hostLen).toString();
|
||||||
|
targetPort = data.readUInt16BE(5 + hostLen);
|
||||||
|
} else if (atyp === 0x04) {
|
||||||
|
// IPv6
|
||||||
|
const ipv6Buffer = data.subarray(4, 20);
|
||||||
|
targetHost = Array.from(new Array(8), (_, i) =>
|
||||||
|
ipv6Buffer.readUInt16BE(i * 2).toString(16),
|
||||||
|
).join(':');
|
||||||
|
targetPort = data.readUInt16BE(20);
|
||||||
|
}
|
||||||
|
if (is.dev()) {
|
||||||
|
console.debug(
|
||||||
|
LoggerPrefix,
|
||||||
|
`[SOCKS5] Request to connect to ${targetHost}:${targetPort}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const socksProxy = parseSocksUrl(upstreamProxyUrl);
|
||||||
|
|
||||||
|
if (!socksProxy) {
|
||||||
|
// Failed to parse proxy URL
|
||||||
|
clientSocket.write(
|
||||||
|
Buffer.from([0x05, 0x01, 0x00, 0x01, 0, 0, 0, 0, 0, 0]),
|
||||||
|
);
|
||||||
|
clientSocket.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: SocksClientOptions = {
|
||||||
|
proxy: {
|
||||||
|
host: socksProxy.host,
|
||||||
|
port: socksProxy.port,
|
||||||
|
type: socksProxy.type as 4 | 5,
|
||||||
|
userId: socksProxy.username,
|
||||||
|
password: socksProxy.password,
|
||||||
|
},
|
||||||
|
command: 'connect',
|
||||||
|
destination: {
|
||||||
|
host: targetHost || defaultAuthProxyConfig.hostname,
|
||||||
|
port: targetPort || defaultAuthProxyConfig.port,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
SocksClient.createConnection(options)
|
||||||
|
.then((info) => {
|
||||||
|
const { socket: proxySocket } = info;
|
||||||
|
|
||||||
|
// Connection successful, send success response to client
|
||||||
|
const responseBuffer = Buffer.from([
|
||||||
|
0x05, // VER: SOCKS5
|
||||||
|
0x00, // REP: Success
|
||||||
|
0x00, // RSV: Reserved field
|
||||||
|
0x01, // ATYP: IPv4
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0, // BND.ADDR: 0.0.0.0 (Bound address, usually not important)
|
||||||
|
0,
|
||||||
|
0, // BND.PORT: 0 (Bound port, usually not important)
|
||||||
|
]);
|
||||||
|
clientSocket.write(responseBuffer);
|
||||||
|
|
||||||
|
// Establish bidirectional data stream
|
||||||
|
proxySocket.pipe(clientSocket);
|
||||||
|
clientSocket.pipe(proxySocket);
|
||||||
|
|
||||||
|
proxySocket.on('error', (error) => {
|
||||||
|
console.error(LoggerPrefix, '[SOCKS5] Proxy socket error:', error);
|
||||||
|
if (clientSocket.writable) clientSocket.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
clientSocket.on('error', (error) => {
|
||||||
|
console.error(LoggerPrefix, '[SOCKS5] Client socket error:', error);
|
||||||
|
if (proxySocket.writable) proxySocket.end();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(LoggerPrefix, '[SOCKS5] Connection error:', error);
|
||||||
|
// Send failure response to client
|
||||||
|
clientSocket.write(
|
||||||
|
Buffer.from([0x05, 0x05, 0x00, 0x01, 0, 0, 0, 0, 0, 0]),
|
||||||
|
);
|
||||||
|
clientSocket.end();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Stop proxy server
|
||||||
|
stopServer() {
|
||||||
|
if (this.server) {
|
||||||
|
this.server.close();
|
||||||
|
this.server = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
21
src/plugins/auth-proxy-adapter/backend/types.ts
Normal file
21
src/plugins/auth-proxy-adapter/backend/types.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import net from 'net';
|
||||||
|
|
||||||
|
import type { AuthProxyConfig } from '../config';
|
||||||
|
import type { Server } from 'http';
|
||||||
|
|
||||||
|
export type BackendType = {
|
||||||
|
server?: Server | net.Server;
|
||||||
|
oldConfig?: AuthProxyConfig;
|
||||||
|
startServer: (serverConfig: AuthProxyConfig) => void;
|
||||||
|
stopServer: () => void;
|
||||||
|
handleSocks5: (
|
||||||
|
clientSocket: net.Socket,
|
||||||
|
chunk: Buffer,
|
||||||
|
upstreamProxyUrl: string,
|
||||||
|
) => void;
|
||||||
|
processSocks5Request: (
|
||||||
|
clientSocket: net.Socket,
|
||||||
|
data: Buffer,
|
||||||
|
upstreamProxyUrl: string,
|
||||||
|
) => void;
|
||||||
|
};
|
||||||
11
src/plugins/auth-proxy-adapter/config.ts
Normal file
11
src/plugins/auth-proxy-adapter/config.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface AuthProxyConfig {
|
||||||
|
enabled: boolean;
|
||||||
|
hostname: string;
|
||||||
|
port: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultAuthProxyConfig: AuthProxyConfig = {
|
||||||
|
enabled: false,
|
||||||
|
hostname: '127.0.0.1',
|
||||||
|
port: 4545,
|
||||||
|
};
|
||||||
16
src/plugins/auth-proxy-adapter/index.ts
Normal file
16
src/plugins/auth-proxy-adapter/index.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { createPlugin } from '@/utils';
|
||||||
|
import { t } from '@/i18n';
|
||||||
|
|
||||||
|
import { defaultAuthProxyConfig } from './config';
|
||||||
|
import { onMenu } from './menu';
|
||||||
|
import { backend } from './backend';
|
||||||
|
|
||||||
|
export default createPlugin({
|
||||||
|
name: () => t('plugins.auth-proxy-adapter.name'),
|
||||||
|
description: () => t('plugins.auth-proxy-adapter.description'),
|
||||||
|
restartNeeded: true,
|
||||||
|
config: defaultAuthProxyConfig,
|
||||||
|
addedVersion: '3.10.X',
|
||||||
|
menu: onMenu,
|
||||||
|
backend,
|
||||||
|
});
|
||||||
68
src/plugins/auth-proxy-adapter/menu.ts
Normal file
68
src/plugins/auth-proxy-adapter/menu.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import prompt from 'custom-electron-prompt';
|
||||||
|
|
||||||
|
import { t } from '@/i18n';
|
||||||
|
import promptOptions from '@/providers/prompt-options';
|
||||||
|
|
||||||
|
import { type AuthProxyConfig, defaultAuthProxyConfig } from './config';
|
||||||
|
|
||||||
|
import type { MenuContext } from '@/types/contexts';
|
||||||
|
import type { MenuTemplate } from '@/menu';
|
||||||
|
|
||||||
|
export const onMenu = async ({
|
||||||
|
getConfig,
|
||||||
|
setConfig,
|
||||||
|
window,
|
||||||
|
}: MenuContext<AuthProxyConfig>): Promise<MenuTemplate> => {
|
||||||
|
await getConfig();
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: t('plugins.auth-proxy-adapter.menu.hostname.label'),
|
||||||
|
type: 'normal',
|
||||||
|
async click() {
|
||||||
|
const config = await getConfig();
|
||||||
|
|
||||||
|
const newHostname =
|
||||||
|
(await prompt(
|
||||||
|
{
|
||||||
|
title: t('plugins.auth-proxy-adapter.prompt.hostname.title'),
|
||||||
|
label: t('plugins.auth-proxy-adapter.prompt.hostname.label'),
|
||||||
|
value: config.hostname,
|
||||||
|
type: 'input',
|
||||||
|
width: 380,
|
||||||
|
...promptOptions(),
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
)) ??
|
||||||
|
config.hostname ??
|
||||||
|
defaultAuthProxyConfig.hostname;
|
||||||
|
|
||||||
|
setConfig({ ...config, hostname: newHostname });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('plugins.auth-proxy-adapter.menu.port.label'),
|
||||||
|
type: 'normal',
|
||||||
|
async click() {
|
||||||
|
const config = await getConfig();
|
||||||
|
|
||||||
|
const newPort =
|
||||||
|
(await prompt(
|
||||||
|
{
|
||||||
|
title: t('plugins.auth-proxy-adapter.prompt.port.title'),
|
||||||
|
label: t('plugins.auth-proxy-adapter.prompt.port.label'),
|
||||||
|
value: config.port,
|
||||||
|
type: 'counter',
|
||||||
|
counterOptions: { minimum: 0, maximum: 65535 },
|
||||||
|
width: 380,
|
||||||
|
...promptOptions(),
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
)) ??
|
||||||
|
config.port ??
|
||||||
|
defaultAuthProxyConfig.port;
|
||||||
|
|
||||||
|
setConfig({ ...config, port: newPort });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user