diff --git a/README.md b/README.md index 48870ed..134c8ac 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,4 @@ - [ ] Web 钩子触发更新 - [ ] 内容缓存 - [ ] OAuth2 授权访问私有页面 + diff --git a/config.go b/config.go index 10955a0..62608ca 100644 --- a/config.go +++ b/config.go @@ -5,19 +5,24 @@ import ( ) type Config struct { - Bind string `yaml:"bind"` // HTTP 绑定 + Bind string `yaml:"bind"` // HTTP 绑定 + Domain string `yaml:"domain"` // 基础域名 - Auth ConfigAuth `yaml:"auth"` // Gitea 认证配置 + Auth ConfigAuth `yaml:"auth"` // 后端认证配置 - Cache string `yaml:"cache"` // + Cache ConfigCache `yaml:"cache"` // 缓存配置 Storage string `yaml:"storage"` // 持久化配置 } type ConfigAuth struct { + // 后端类型 + Type string `yaml:"type"` + // 服务器地址 Server string `yaml:"server"` - Token string `yaml:"token"` + // 会话 Id + Token string `yaml:"token"` } type ConfigCache struct { diff --git a/go.mod b/go.mod index de522c9..5cac566 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,16 @@ module code.d7z.net/d7z-project/gitea-pages go 1.23.2 +require code.gitea.io/sdk/gitea v0.19.0 + require ( - code.gitea.io/sdk/gitea v0.19.0 // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/go-fed/httpsig v1.1.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/patrickmn/go-cache v2.1.0+incompatible // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/sys v0.19.0 // indirect + github.com/ncruces/go-sqlite3 v0.21.3 // indirect + github.com/ncruces/julianday v1.0.0 // indirect + github.com/stretchr/testify v1.8.1 // indirect + github.com/tetratelabs/wazero v1.8.2 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/sys v0.28.0 // indirect ) diff --git a/go.sum b/go.sum index 0ad26c9..c48fa48 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,35 @@ code.gitea.io/sdk/gitea v0.19.0 h1:8I6s1s4RHgzxiPHhOQdgim1RWIRcr0LVMbHBjBFXq4Y= code.gitea.io/sdk/gitea v0.19.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE= github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/ncruces/go-sqlite3 v0.21.3 h1:hHkfNQLcbnxPJZhC/RGw9SwP3bfkv/Y0xUHWsr1CdMQ= +github.com/ncruces/go-sqlite3 v0.21.3/go.mod h1:zxMOaSG5kFYVFK4xQa0pdwIszqxqJ0W0BxBgwdrNjuA= +github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M= +github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4= +github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -20,7 +37,16 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/models/page.go b/pkg/models/page.go new file mode 100644 index 0000000..65ce77a --- /dev/null +++ b/pkg/models/page.go @@ -0,0 +1,10 @@ +package models + +type PageConfig struct { + // pages 分支 + Branch string `json:"branch" yaml:"branch"` + // 匹配的域名和路径 + Domain string `json:"domain" yaml:"domain"` + // 路由模式 (default / history) + RouteMode string `json:"route" yaml:"route"` +} diff --git a/pkg/providers/backend.go b/pkg/providers/backend.go deleted file mode 100644 index e7060aa..0000000 --- a/pkg/providers/backend.go +++ /dev/null @@ -1,15 +0,0 @@ -package providers - -import "io" - -type Blob struct { - MediaType string - io.ReadCloser -} - -type Backend interface { - Owners() ([]string, error) - Repos(owner string) ([]string, error) - Branches(owner, repo string) ([]string, error) - Open(owner, repo, branch, path string) (Blob, error) -} diff --git a/pkg/providers/gitea.go b/pkg/providers/gitea.go index 799ecaa..44bcdb5 100644 --- a/pkg/providers/gitea.go +++ b/pkg/providers/gitea.go @@ -1,24 +1,122 @@ package providers +import ( + "code.gitea.io/sdk/gitea" + "net/http" + "net/url" + "os" +) + +const GiteaMaxCount = 9999 + type ProviderGitea struct { + BaseUrl string + Token string + + gitea *gitea.Client } -func (g *ProviderGitea) Owners() ([]string, error) { - //TODO implement me - panic("implement me") +func NewGitea(url string, token string) (*ProviderGitea, error) { + client, err := gitea.NewClient(url, gitea.SetGiteaVersion(""), gitea.SetToken(token)) + if err != nil { + return nil, err + } + return &ProviderGitea{ + BaseUrl: url, + Token: token, + gitea: client, + }, nil } -func (g *ProviderGitea) Repos(owner string) ([]string, error) { - //TODO implement me - panic("implement me") +func (g *ProviderGitea) Repos(owner string) (map[string]string, error) { + result := make(map[string]string) + if repos, resp, err := g.gitea.ListOrgRepos(owner, gitea.ListOrgReposOptions{ + ListOptions: gitea.ListOptions{ + PageSize: GiteaMaxCount, + }, + }); err != nil || (resp != nil && resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNotFound) { + if resp != nil { + _ = resp.Body.Close() + } + return nil, err + } else { + if resp != nil { + _ = resp.Body.Close() + } + for _, item := range repos { + result[item.Name] = item.DefaultBranch + } + } + if len(result) == 0 { + if repos, resp, err := g.gitea.ListUserRepos(owner, gitea.ListReposOptions{ + ListOptions: gitea.ListOptions{ + PageSize: GiteaMaxCount, + }, + }); err != nil || (resp != nil && resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNotFound) { + if resp != nil { + _ = resp.Body.Close() + } + return nil, err + } else { + if resp != nil { + _ = resp.Body.Close() + } + for _, item := range repos { + result[item.Name] = item.DefaultBranch + } + } + } + if len(result) == 0 { + return nil, os.ErrNotExist + } + return result, nil + } -func (g *ProviderGitea) Branches(owner, repo string) ([]string, error) { - //TODO implement me - panic("implement me") +func (g *ProviderGitea) Branches(owner, repo string) (map[string]string, error) { + result := make(map[string]string) + if branches, resp, err := g.gitea.ListRepoBranches(owner, repo, gitea.ListRepoBranchesOptions{ + ListOptions: gitea.ListOptions{ + PageSize: GiteaMaxCount, + }, + }); err != nil { + if resp != nil { + _ = resp.Body.Close() + } + return nil, err + } else { + if resp != nil { + _ = resp.Body.Close() + } + for _, branch := range branches { + result[branch.Name] = branch.Commit.ID + } + } + if len(result) == 0 { + return nil, os.ErrNotExist + } + return result, nil } -func (g *ProviderGitea) Open(owner, repo, branch, path string) (Blob, error) { - //TODO implement me - panic("implement me") +func (g *ProviderGitea) Open(client http.Client, owner, repo, commit, path string, headers map[string]string) (*http.Response, error) { + giteaURL, err := url.JoinPath(g.BaseUrl, "api/v1/repos", owner, repo, "media", path) + if err != nil { + return nil, err + } + giteaURL += "?ref=" + url.QueryEscape(commit) + req, err := http.NewRequest(http.MethodGet, giteaURL, nil) + if err != nil { + return nil, err + } + if headers != nil { + for key, value := range headers { + req.Header.Add(key, value) + } + } + req.Header.Add("Authorization", "token "+g.Token) + resp, err := client.Do(req) + if err != nil && resp == nil { + return nil, err + } + return resp, nil } diff --git a/pkg/server.go b/pkg/server.go new file mode 100644 index 0000000..d092a8d --- /dev/null +++ b/pkg/server.go @@ -0,0 +1,16 @@ +package pkg + +import ( + "code.d7z.net/d7z-project/gitea-pages/pkg/services" +) + +type ServerOptions struct { + Domain string +} + +type Server struct { +} + +func NewServer(backend services.Backend, options *ServerOptions) *Server { + +} diff --git a/pkg/services/backend.go b/pkg/services/backend.go new file mode 100644 index 0000000..153f2eb --- /dev/null +++ b/pkg/services/backend.go @@ -0,0 +1,14 @@ +package services + +import ( + "net/http" +) + +type Backend interface { + // Repos return repo name + default branch + Repos(owner string) (map[string]string, error) + // Branches return branch + commit id + Branches(owner, repo string) (map[string]string, error) + // Open return file or error + Open(client http.Client, owner, repo, commit, path string, headers map[string]string) (*http.Response, error) +} diff --git a/pkg/services/cache.go b/pkg/services/cache.go new file mode 100644 index 0000000..6525513 --- /dev/null +++ b/pkg/services/cache.go @@ -0,0 +1,7 @@ +package services + +type Cache interface { + Put(key string, value []byte) error + Get(key string) ([]byte, error) + Delete(key string) error +}