diff --git a/build.sh b/build.sh index 35b89b7..85d8a53 100755 --- a/build.sh +++ b/build.sh @@ -20,7 +20,7 @@ echo "Building frp-panel client only linux binaries..." CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o dist/frp-panel-client-linux-amd64 cmd/frppc/*.go CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o dist/frp-panel-client-linux-arm64 cmd/frppc/*.go echo "Building frp-panel client only darwin binaries..." -CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o dist/frp-panel-client-darwin-amd64 cmd/frpp/*.go +CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o dist/frp-panel-client-darwin-amd64 cmd/frppc/*.go CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o dist/frp-panel-client-darwin-arm64 cmd/frppc/*.go echo "Build Done!" \ No newline at end of file diff --git a/cmd/frpp/client.go b/cmd/frpp/client.go index d029d3c..96c1344 100644 --- a/cmd/frpp/client.go +++ b/cmd/frpp/client.go @@ -13,7 +13,11 @@ import ( "github.com/sourcegraph/conc" ) -func runClient(clientID, clientSecret string) { +func runClient() { + var ( + clientID = conf.Get().Client.ID + clientSecret = conf.Get().Client.Secret + ) crypto.DefaultSalt = conf.Get().App.Secret logrus.Infof("start to run client") if len(clientSecret) == 0 { diff --git a/cmd/frpp/cmd.go b/cmd/frpp/cmd.go index 94fa266..a1f7620 100644 --- a/cmd/frpp/cmd.go +++ b/cmd/frpp/cmd.go @@ -36,16 +36,20 @@ func initCommand() { Use: "client [-s client secret] [-i client id] [-a app secret] [-r rpc host] [-c rpc port] [-p api port]", Short: "run managed frpc", Run: func(cmd *cobra.Command, args []string) { - patchConfig(rpcHost, appSecret, rpcPort, apiPort) - runClient(clientID, clientSecret) + patchConfig(rpcHost, appSecret, + clientID, clientSecret, + apiScheme, rpcPort, apiPort) + runClient() }, } serverCmd = &cobra.Command{ Use: "server [-s client secret] [-i client id] [-a app secret] [-r rpc host] [-c rpc port] [-p api port]", Short: "run managed frps", Run: func(cmd *cobra.Command, args []string) { - patchConfig(rpcHost, appSecret, rpcPort, apiPort) - runServer(clientID, clientSecret) + patchConfig(rpcHost, appSecret, + clientID, clientSecret, + apiScheme, rpcPort, apiPort) + runServer() }, } masterCmd = &cobra.Command{ @@ -82,7 +86,7 @@ func initLogger() { logrus.SetReportCaller(true) } -func patchConfig(host, secret string, rpcPort, apiPort int) { +func patchConfig(host, secret, clientID, clientSecret, apiScheme string, rpcPort, apiPort int) { if len(host) != 0 { conf.Get().Master.RPCHost = host conf.Get().Master.APIHost = host @@ -96,4 +100,13 @@ func patchConfig(host, secret string, rpcPort, apiPort int) { if apiPort != 0 { conf.Get().Master.APIPort = apiPort } + if len(apiScheme) != 0 { + conf.Get().Master.APIScheme = apiScheme + } + if len(clientID) != 0 { + conf.Get().Client.ID = clientID + } + if len(clientSecret) != 0 { + conf.Get().Client.Secret = clientSecret + } } diff --git a/cmd/frpp/server.go b/cmd/frpp/server.go index 12898bc..bba46aa 100644 --- a/cmd/frpp/server.go +++ b/cmd/frpp/server.go @@ -14,7 +14,11 @@ import ( "github.com/sourcegraph/conc" ) -func runServer(clientID, clientSecret string) { +func runServer() { + var ( + clientID = conf.Get().Client.ID + clientSecret = conf.Get().Client.Secret + ) crypto.DefaultSalt = conf.Get().App.Secret logrus.Infof("start to run server") diff --git a/cmd/frppc/client.go b/cmd/frppc/client.go index d029d3c..96c1344 100644 --- a/cmd/frppc/client.go +++ b/cmd/frppc/client.go @@ -13,7 +13,11 @@ import ( "github.com/sourcegraph/conc" ) -func runClient(clientID, clientSecret string) { +func runClient() { + var ( + clientID = conf.Get().Client.ID + clientSecret = conf.Get().Client.Secret + ) crypto.DefaultSalt = conf.Get().App.Secret logrus.Infof("start to run client") if len(clientSecret) == 0 { diff --git a/cmd/frppc/cmd.go b/cmd/frppc/cmd.go index b77b055..39a00bf 100644 --- a/cmd/frppc/cmd.go +++ b/cmd/frppc/cmd.go @@ -34,8 +34,10 @@ func initCommand() { Use: "client [-s client secret] [-i client id] [-a app secret] [-r rpc host] [-c rpc port] [-p api port]", Short: "run managed frpc", Run: func(cmd *cobra.Command, args []string) { - patchConfig(rpcHost, appSecret, rpcPort, apiPort) - runClient(clientID, clientSecret) + patchConfig(rpcHost, appSecret, + clientID, clientSecret, + apiScheme, rpcPort, apiPort) + runClient() }, } rootCmd = &cobra.Command{ @@ -58,7 +60,7 @@ func initLogger() { logrus.SetReportCaller(true) } -func patchConfig(host, secret string, rpcPort, apiPort int) { +func patchConfig(host, secret, clientID, clientSecret, apiScheme string, rpcPort, apiPort int) { if len(host) != 0 { conf.Get().Master.RPCHost = host conf.Get().Master.APIHost = host @@ -72,4 +74,13 @@ func patchConfig(host, secret string, rpcPort, apiPort int) { if apiPort != 0 { conf.Get().Master.APIPort = apiPort } + if len(apiScheme) != 0 { + conf.Get().Master.APIScheme = apiScheme + } + if len(clientID) != 0 { + conf.Get().Client.ID = clientID + } + if len(clientSecret) != 0 { + conf.Get().Client.Secret = clientSecret + } } diff --git a/conf/settings.go b/conf/settings.go index 560d66b..36ed6d7 100644 --- a/conf/settings.go +++ b/conf/settings.go @@ -39,6 +39,10 @@ type Config struct { Type string `env:"TYPE" env-default:"sqlite3" env-description:"db type, mysql or sqlite3 and so on"` DSN string `env:"DSN" env-default:"data.db" env-description:"db dsn, for sqlite is path, other is dsn, look at https://github.com/go-sql-driver/mysql#dsn-data-source-name"` } `env-prefix:"DB_"` + Client struct { + ID string `env:"ID" env-description:"client id"` + Secret string `env:"SECRET" env-description:"client secret"` + } `env-prefix:"CLIENT_"` } var ( @@ -56,7 +60,7 @@ func InitConfig() { ) if err = godotenv.Load(); err != nil { - logrus.Infof("Error loading .env file, will use runtime env") + logrus.WithError(err).Infof("Error loading .env file, will use runtime env") } cfg := Config{} diff --git a/www/components/client_item.tsx b/www/components/client_item.tsx index 0073169..aac2bb9 100644 --- a/www/components/client_item.tsx +++ b/www/components/client_item.tsx @@ -22,7 +22,7 @@ import { } from '@/components/ui/dropdown-menu' import { useToast } from './ui/use-toast' import React, { useState } from 'react' -import { ExecCommandStr, LinuxInstallCommand, WindowsInstallCommand } from '@/lib/consts' +import { ClientEnvFile, ExecCommandStr, LinuxInstallCommand, WindowsInstallCommand } from '@/lib/consts' import { useMutation, useQuery } from '@tanstack/react-query' import { deleteClient, listClient } from '@/api/client' import { useRouter } from 'next/router' @@ -211,6 +211,15 @@ export const ClientActions: React.FC = ({ client, table }) => { }, }) + const createAndDownloadFile = (fileName: string, content: string) => { + var aTag = document.createElement('a'); + var blob = new Blob([content]); + aTag.download = fileName; + aTag.href = URL.createObjectURL(blob); + aTag.click(); + URL.revokeObjectURL(aTag.href); + } + return ( @@ -246,6 +255,20 @@ export const ClientActions: React.FC = ({ client, table }) => { > 修改客户端配置 + { + try { + if (platformInfo) { + createAndDownloadFile(`.env`, ClientEnvFile(client, platformInfo)) + } + } + catch (error) { + toast({ description: '获取平台信息失败' }) + } + }} + > + 下载配置文件 + 删除 @@ -269,6 +292,6 @@ export const ClientActions: React.FC = ({ client, table }) => { - + ) } diff --git a/www/components/server_item.tsx b/www/components/server_item.tsx index 068e20f..aada089 100644 --- a/www/components/server_item.tsx +++ b/www/components/server_item.tsx @@ -22,7 +22,7 @@ import { } from '@/components/ui/dropdown-menu' import { useToast } from './ui/use-toast' import React, { useState } from 'react' -import { ExecCommandStr, LinuxInstallCommand, WindowsInstallCommand } from '@/lib/consts' +import { ClientEnvFile, ExecCommandStr, LinuxInstallCommand, WindowsInstallCommand } from '@/lib/consts' import { useMutation, useQuery } from '@tanstack/react-query' import { deleteServer, listServer } from '@/api/server' import { useRouter } from 'next/router' @@ -221,6 +221,16 @@ export const ServerActions: React.FC = ({ server, table }) => { toast({ description: '删除失败' }) }, }) + + const createAndDownloadFile = (fileName: string, content: string) => { + var aTag = document.createElement('a'); + var blob = new Blob([content]); + aTag.download = fileName; + aTag.href = URL.createObjectURL(blob); + aTag.click(); + URL.revokeObjectURL(aTag.href); + } + return ( @@ -261,6 +271,20 @@ export const ServerActions: React.FC = ({ server, table }) => { > 修改服务端配置 + { + try { + if (platformInfo) { + createAndDownloadFile(`.env`, ClientEnvFile(server, platformInfo)) + } + } + catch (error) { + toast({ description: '获取平台信息失败' }) + } + }} + > + 下载配置文件 + 删除 diff --git a/www/lib/consts.ts b/www/lib/consts.ts index 3336b0d..6c98123 100644 --- a/www/lib/consts.ts +++ b/www/lib/consts.ts @@ -23,9 +23,8 @@ export const ExecCommandStr = ( info: GetPlatformInfoResponse, fileName?: string, ) => { - return `${fileName || 'frp-panel'} ${type} -s ${item.secret} -i ${item.id} -a ${info.globalSecret} -r ${ - info.masterRpcHost - } -c ${info.masterRpcPort} -p ${info.masterApiPort} -e ${info.masterApiScheme}` + return `${fileName || 'frp-panel'} ${type} -s ${item.secret} -i ${item.id} -a ${info.globalSecret} -r ${info.masterRpcHost + } -c ${info.masterRpcPort} -p ${info.masterApiPort} -e ${info.masterApiScheme}` } export const WindowsInstallCommand = ( @@ -47,3 +46,17 @@ export const LinuxInstallCommand = ( ) => { return `curl -sSL https://raw.githubusercontent.com/VaalaCat/frp-panel/main/install.sh | bash -s --${ExecCommandStr(type, item, info, ' ')}` } + +export const ClientEnvFile = ( + item: T, + info: GetPlatformInfoResponse, +) => { + return `CLIENT_ID=${item.id} +CLIENT_SECRET=${item.secret} +APP_SECRET=${info.globalSecret} +MASTER_RPC_HOST=${info.masterRpcHost} +MASTER_RPC_PORT=${info.masterRpcPort} +MASTER_API_HOST=${info.masterRpcHost} +MASTER_API_PORT=${info.masterApiPort} +MASTER_API_SCHEME=${info.masterApiScheme}` +} \ No newline at end of file