feat: 初始提交 - Code Server Bridge完整实现
- OAuth认证系统(Gitea + Lua扩展) - Git自动化操作(本地/SSH远程) - 实时进度WebSocket推送 - 现代化Tab界面UI - Cobra CLI命令行(init/version/serve) - 完整构建系统(Makefile + Taskfile) - UPX压缩支持(体积减少70%)
This commit is contained in:
103
cmd/server/cmd/init.go
Normal file
103
cmd/server/cmd/init.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"cs-bridge/internal/config"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-yaml/yaml"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "初始化配置文件",
|
||||
Long: `生成默认的config.yaml配置文件和scripts目录`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
configPath, _ := cmd.Flags().GetString("output")
|
||||
force, _ := cmd.Flags().GetBool("force")
|
||||
|
||||
// 检查文件是否存在
|
||||
if _, err := os.Stat(configPath); err == nil && !force {
|
||||
fmt.Printf("❌ 配置文件已存在: %s\n", configPath)
|
||||
fmt.Println("使用 --force 强制覆盖")
|
||||
return
|
||||
}
|
||||
|
||||
// 创建默认配置文件
|
||||
cfg := config.DefaultConfig()
|
||||
defaultConfig, err := yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 生成配置失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 写入配置文件
|
||||
if err := os.WriteFile(configPath, defaultConfig, 0644); err != nil {
|
||||
fmt.Printf("❌ 创建配置文件失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("✅ 配置文件已创建: %s\n", configPath)
|
||||
|
||||
// 创建scripts目录和示例Lua脚本
|
||||
scriptsDir := "scripts/oauth"
|
||||
if err := os.MkdirAll(scriptsDir, 0755); err != nil {
|
||||
fmt.Printf("⚠️ 创建scripts目录失败: %v\n", err)
|
||||
} else {
|
||||
// 创建示例Lua脚本
|
||||
luaScript := `-- Gitea OAuth Provider
|
||||
-- 此脚本定义了Gitea OAuth认证流程
|
||||
|
||||
function auth_url(cfg, state)
|
||||
local params = {
|
||||
"client_id=" .. util.url_encode(cfg.client_id),
|
||||
"redirect_uri=" .. util.url_encode(cfg.redirect_uri),
|
||||
"response_type=code",
|
||||
"scope=read:user",
|
||||
"state=" .. util.url_encode(state)
|
||||
}
|
||||
|
||||
return cfg.base_url .. "/login/oauth/authorize?" .. table.concat(params, "&")
|
||||
end
|
||||
|
||||
function exchange(cfg, code)
|
||||
local body = {
|
||||
client_id = cfg.client_id,
|
||||
client_secret = cfg.client_secret,
|
||||
code = code,
|
||||
grant_type = "authorization_code",
|
||||
redirect_uri = cfg.redirect_uri
|
||||
}
|
||||
|
||||
return util.http_post_json(cfg.base_url .. "/login/oauth/access_token", body)
|
||||
end
|
||||
|
||||
function user_info(cfg, token)
|
||||
local headers = {
|
||||
Authorization = "Bearer " .. token
|
||||
}
|
||||
|
||||
return util.http_get_json(cfg.base_url .. "/api/v1/user", headers)
|
||||
end
|
||||
`
|
||||
luaPath := filepath.Join(scriptsDir, "gitea.lua")
|
||||
if err := os.WriteFile(luaPath, []byte(luaScript), 0644); err != nil {
|
||||
fmt.Printf("⚠️ 创建Lua脚本失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("✅ 示例Lua脚本已创建: %s\n", luaPath)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("\n📝 下一步:")
|
||||
fmt.Printf("1. 编辑配置文件: %s\n", configPath)
|
||||
fmt.Println("2. 配置OAuth客户端信息")
|
||||
fmt.Println("3. 运行服务: code-server-bridge")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
initCmd.Flags().StringP("output", "o", "config.yaml", "配置文件输出路径")
|
||||
initCmd.Flags().BoolP("force", "f", false, "强制覆盖已存在的文件")
|
||||
rootCmd.AddCommand(initCmd)
|
||||
}
|
||||
42
cmd/server/cmd/root.go
Normal file
42
cmd/server/cmd/root.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
// 版本信息,构建时注入
|
||||
Version = "dev"
|
||||
BuildTime = "unknown"
|
||||
GitCommit = "unknown"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "code-server-bridge",
|
||||
Short: "Code Server Bridge - OAuth认证和Git仓库准备工具",
|
||||
Long: `Code Server Bridge 是一个为code-server提供OAuth认证和Git仓库自动准备的桥接服务。
|
||||
|
||||
功能特性:
|
||||
- OAuth认证 (支持Gitea等)
|
||||
- Git仓库自动克隆/更新
|
||||
- 实时进度显示
|
||||
- Workspace自动管理
|
||||
|
||||
使用 'code-server-bridge serve' 启动服务器
|
||||
使用 'code-server-bridge init' 初始化配置文件`,
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 全局flags
|
||||
rootCmd.PersistentFlags().StringP("config", "c", "config.yaml", "配置文件路径")
|
||||
}
|
||||
80
cmd/server/cmd/serve.go
Normal file
80
cmd/server/cmd/serve.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"cs-bridge/internal/config"
|
||||
"cs-bridge/internal/db"
|
||||
"cs-bridge/internal/http"
|
||||
"cs-bridge/internal/oauth"
|
||||
"cs-bridge/pkg/httpclient"
|
||||
"cs-bridge/pkg/logger"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverCmd = &cobra.Command{
|
||||
Use: "serve",
|
||||
Short: "启动服务器",
|
||||
Long: `启动Code Server Bridge服务器`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
configPath, _ := rootCmd.PersistentFlags().GetString("config")
|
||||
|
||||
// 加载配置
|
||||
os.Setenv("CONFIG_PATH", configPath)
|
||||
cfg := config.NewConfig()
|
||||
|
||||
logger.Init(cfg.Log)
|
||||
db.InitDB(cfg.Database, logger.GetLogger())
|
||||
|
||||
httpclient.Init()
|
||||
|
||||
mgr := oauth.NewManager()
|
||||
for _, p := range cfg.OAuth.Providers {
|
||||
redirect := cfg.OAuth.BaseURL + "/oauth/" + p.Name + "/callback"
|
||||
|
||||
switch strings.ToLower(p.Type) {
|
||||
case "gitea":
|
||||
// 优先尝试使用Lua Provider
|
||||
scriptPath := fmt.Sprintf("scripts/oauth/%s.lua", p.Name)
|
||||
if _, err := os.Stat(scriptPath); err == nil {
|
||||
// Lua脚本存在,使用Lua Provider
|
||||
logger.GetLogger().Info(fmt.Sprintf("使用Lua脚本加载OAuth Provider: %s (%s)", p.Name, scriptPath))
|
||||
|
||||
luaProvider, err := oauth.NewLuaProvider(
|
||||
oauth.ProviderModel{
|
||||
Name: p.Name,
|
||||
Type: p.Type,
|
||||
BaseURL: p.BaseURL,
|
||||
ClientID: p.ClientID,
|
||||
ClientSecret: p.ClientSecret,
|
||||
AuthorizeURL: p.AuthorizeURL,
|
||||
TokenURL: p.TokenURL,
|
||||
UserURL: p.UserURL,
|
||||
},
|
||||
redirect,
|
||||
scriptPath,
|
||||
)
|
||||
if err != nil {
|
||||
logger.GetLogger().Error(fmt.Sprintf("加载Lua Provider失败: %v,回退到原生实现", err))
|
||||
mgr.Register(oauth.NewGitea(p, redirect))
|
||||
} else {
|
||||
mgr.Register(luaProvider)
|
||||
}
|
||||
} else {
|
||||
// Lua脚本不存在,使用原生Go实现
|
||||
logger.GetLogger().Info(fmt.Sprintf("使用原生Go实现加载OAuth Provider: %s", p.Name))
|
||||
mgr.Register(oauth.NewGitea(p, redirect))
|
||||
}
|
||||
}
|
||||
}
|
||||
r := http.NewRouter(cfg, mgr)
|
||||
|
||||
r.ListenAndServe()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serverCmd)
|
||||
}
|
||||
23
cmd/server/cmd/version.go
Normal file
23
cmd/server/cmd/version.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "显示版本信息",
|
||||
Long: `显示程序的版本号、构建时间和Git提交信息`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Printf("Code Server Bridge\n\n")
|
||||
fmt.Printf("Version: %s\n", Version)
|
||||
fmt.Printf("Build Time: %s\n", BuildTime)
|
||||
fmt.Printf("Git Commit: %s\n", GitCommit)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
25
cmd/server/main.go
Normal file
25
cmd/server/main.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"cs-bridge/cmd/server/cmd"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 版本信息,编译时通过ldflags注入
|
||||
var (
|
||||
Version = "dev"
|
||||
BuildTime = "unknown"
|
||||
GitCommit = "unknown"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 设置版本信息到cmd包
|
||||
cmd.Version = Version
|
||||
cmd.BuildTime = BuildTime
|
||||
cmd.GitCommit = GitCommit
|
||||
|
||||
// 启动信息
|
||||
fmt.Printf("🚀 启动 code-server-bridge v%s by zhilv666\n", Version)
|
||||
|
||||
cmd.Execute()
|
||||
}
|
||||
Reference in New Issue
Block a user