Files
Commilitia-Drop/desktop/platform/config.go
T
admin f21fa5b5e8 cdrop — 跨 OS 剪贴板与文件传输服务
Commilitia Drop:自托管的跨设备剪贴板同步与点对点文件传输。

- 后端 Go(chi / SQLite WAL / SSE Hub / WebRTC signaling + 状态机 / Relay ring buffer),编译进单个 distroless 镜像(前端 go:embed)。
- 前端 React + TanStack Router + Zustand,自实现 SSE + WebRTC P2P,NAT 受阻时回退服务端中继;聚珍(Juzhen)CJK 综合排版。
- 桌面端 Wails v2(macOS / Windows),瘦客户端复用 web。
- 鉴权 OIDC PKCE(自建 Casdoor 等),refresh_token 信封加密存系统密钥库;iOS Shortcut 用 HS256 scoped token。

架构文档与变更记录见 docs 分支(PROJECT_BRIEF / FRONTEND_DESIGN / CHANGELOG)。

本次为公开发布初始提交:完整开发历史(含部署细节)留存于私有归档,公开仓库自此干净起步。
2026-06-15 21:38:28 +08:00

57 lines
1.8 KiB
Go

package platform
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
"time"
)
// FetchOAuthConfig pulls the provider coordinates from the cdrop backend's
// /api/auth/config. The desktop reuses the same OAuth client as the web app
// (the client_id published there) and runs its own loopback PKCE flow against
// the provider, instead of the browser's in-page redirect + /api/auth/exchange
// proxy. apiBase is the backend origin, e.g. https://drop.commilitia.net.
func FetchOAuthConfig(ctx context.Context, apiBase string) (OAuthConfig, error) {
endpoint := strings.TrimRight(apiBase, "/") + "/api/auth/config"
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return OAuthConfig{}, fmt.Errorf("oauth: build config request: %w", err)
}
req.Header.Set("Accept", "application/json")
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil {
return OAuthConfig{}, fmt.Errorf("oauth: fetch config: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return OAuthConfig{}, fmt.Errorf("oauth: config endpoint status %d", resp.StatusCode)
}
var c struct {
AuthorizeURL string `json:"authorize_url"`
TokenURL string `json:"token_url"`
ClientID string `json:"client_id"`
Scopes string `json:"scopes"`
}
if err := json.NewDecoder(resp.Body).Decode(&c); err != nil {
return OAuthConfig{}, fmt.Errorf("oauth: decode config: %w", err)
}
cfg := OAuthConfig{
AuthorizeURL: c.AuthorizeURL,
TokenURL: c.TokenURL,
ClientID: c.ClientID,
Scopes: c.Scopes,
}
if cfg.AuthorizeURL == "" || cfg.TokenURL == "" || cfg.ClientID == "" {
return OAuthConfig{}, errors.New("oauth: backend config missing authorize_url / token_url / client_id")
}
return cfg, nil
}