Files
transfer-site/internal/oauth/gitea.go
zhilv 8265df0dcd feat: 初始提交 - Code Server Bridge完整实现
- OAuth认证系统(Gitea + Lua扩展)
- Git自动化操作(本地/SSH远程)
- 实时进度WebSocket推送
- 现代化Tab界面UI
- Cobra CLI命令行(init/version/serve)
- 完整构建系统(Makefile + Taskfile)
- UPX压缩支持(体积减少70%)
2026-01-08 23:32:29 +08:00

112 lines
3.1 KiB
Go

package oauth
import (
"cs-bridge/internal/auth"
"cs-bridge/internal/config"
"cs-bridge/pkg/httpclient"
"encoding/json"
"fmt"
"net/url"
"time"
)
type Gitea struct {
cfg config.Provider
redirectURI string
}
// Name implements [Provider].
func (g Gitea) Name() string {
return "gitea"
}
// AuthURL implements [Provider].
func (g Gitea) AuthURL(state string) (string, error) {
u, _ := url.Parse(g.cfg.BaseURL + g.cfg.AuthorizeURL)
q := u.Query()
q.Set("client_id", g.cfg.ClientID)
q.Set("redirect_uri", g.redirectURI)
q.Set("response_type", "code")
q.Set("scope", "read:user")
q.Set("state", state)
u.RawQuery = q.Encode()
return u.String(), nil
}
// Exchange implements [Provider].
func (g Gitea) Exchange(code string) (string, error) {
resp, err := httpclient.Default.R().
SetHeader("Accept", "application/json").
SetFormData(map[string]string{
"client_id": g.cfg.ClientID,
"client_secret": g.cfg.ClientSecret,
"code": code,
"grant_type": "authorization_code",
"redirect_uri": g.redirectURI,
}).
Post(fmt.Sprintf("%s%s", g.cfg.BaseURL, g.cfg.TokenURL))
if err != nil {
return "", err
}
var out struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn string `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
}
json.NewDecoder(resp.Body).Decode(&out)
return out.AccessToken, nil
}
// UserInfo implements [Provider].
func (g Gitea) UserInfo(token string) (auth.Identify, error) {
resp, err := httpclient.Default.R().
SetHeader("Authorization", fmt.Sprintf("bearer %s", token)).
Get(fmt.Sprintf("%s%s", g.cfg.BaseURL, g.cfg.UserURL))
if err != nil {
return auth.Identify{}, err
}
var raw raw
json.NewDecoder(resp.Body).Decode(&raw)
return auth.Identify{
Provider: g.Name(),
UserId: fmt.Sprint(raw.ID),
Username: raw.Login,
Avatar: raw.AvatarURL,
}, nil
}
func NewGitea(cfg config.Provider, redirectURI string) Gitea {
return Gitea{
cfg: cfg,
redirectURI: redirectURI,
}
}
type raw struct {
ID int `json:"id"`
Login string `json:"login"`
LoginName string `json:"login_name"`
SourceID int `json:"source_id"`
FullName string `json:"full_name"`
Email string `json:"email"`
AvatarURL string `json:"avatar_url"`
HTMLURL string `json:"html_url"`
Language string `json:"language"`
IsAdmin bool `json:"is_admin"`
LastLogin time.Time `json:"last_login"`
Created time.Time `json:"created"`
Restricted bool `json:"restricted"`
Active bool `json:"active"`
ProhibitLogin bool `json:"prohibit_login"`
Location string `json:"location"`
Website string `json:"website"`
Description string `json:"description"`
Visibility string `json:"visibility"`
FollowersCount int `json:"followers_count"`
FollowingCount int `json:"following_count"`
StarredReposCount int `json:"starred_repos_count"`
Username string `json:"username"`
}