Skip to content

Commit ac7704d

Browse files
authored
Merge pull request #456 from LydiaCai1203/fix-lost-gitee-implement
fix:gitee 相关方法丢失实现
2 parents b3163f8 + e8c5163 commit ac7704d

4 files changed

Lines changed: 246 additions & 16 deletions

File tree

backend/biz/git/usecase/identity.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,15 @@ func (u *GitIdentityUsecase) List(ctx context.Context, uid uuid.UUID) ([]*domain
4949
return cvt.Iter(identities, func(_ int, identity *db.GitIdentity) *domain.GitIdentity {
5050
tmp := cvt.From(identity, &domain.GitIdentity{})
5151
if client := u.gitClienter(identity); client != nil {
52+
token, err := u.tokenProvider.GetToken(ctx, identity.ID)
53+
if err != nil {
54+
u.logger.WarnContext(ctx, "failed to get token", "error", err, "platform", identity.Platform, "identity_id", identity.ID)
55+
return tmp
56+
}
5257
repos, err := client.Repositories(ctx, &domain.RepositoryOptions{
53-
Token: identity.AccessToken,
58+
Token: token,
5459
InstallID: identity.InstallationID,
60+
IsOAuth: identity.OauthRefreshToken != "",
5561
})
5662
if err != nil {
5763
u.logger.WarnContext(ctx, "failed to get authorized repositories", "error", err, "platform", identity.Platform, "identity_id", identity.ID)
@@ -68,7 +74,7 @@ func (u *GitIdentityUsecase) gitClienter(identity *db.GitIdentity) domain.GitCli
6874
case consts.GitPlatformGithub:
6975
return github.NewGithub(u.logger, u.cfg)
7076
case consts.GitPlatformGitLab:
71-
return gitlab.NewGitlab(identity.BaseURL, identity.AccessToken, u.logger)
77+
return gitlab.NewGitlabForBaseURL(identity.BaseURL, u.logger)
7278
case consts.GitPlatformGitea:
7379
return gitea.NewGitea(u.logger, identity.BaseURL)
7480
case consts.GitPlatformGitee:
@@ -91,9 +97,15 @@ func (u *GitIdentityUsecase) Get(ctx context.Context, uid uuid.UUID, id uuid.UUI
9197
gi := cvt.From(identity, &domain.GitIdentity{})
9298

9399
if client := u.gitClienter(identity); client != nil {
100+
token, err := u.tokenProvider.GetToken(ctx, identity.ID)
101+
if err != nil {
102+
u.logger.WarnContext(ctx, "failed to get token", "error", err, "platform", identity.Platform, "identity_id", id)
103+
return gi, nil
104+
}
94105
repos, err := client.Repositories(ctx, &domain.RepositoryOptions{
95-
Token: identity.AccessToken,
106+
Token: token,
96107
InstallID: identity.InstallationID,
108+
IsOAuth: identity.OauthRefreshToken != "",
97109
})
98110
if err != nil {
99111
u.logger.WarnContext(ctx, "failed to get authorized repositories", "error", err, "platform", identity.Platform, "identity_id", id)
@@ -199,8 +211,13 @@ func (u *GitIdentityUsecase) ListBranches(ctx context.Context, uid uuid.UUID, id
199211
return nil, errcode.ErrInvalidPlatform
200212
}
201213

214+
token, err := u.tokenProvider.GetToken(ctx, identity.ID)
215+
if err != nil {
216+
return nil, fmt.Errorf("get token: %w", err)
217+
}
218+
202219
branches, err := client.Branches(ctx, &domain.BranchesOptions{
203-
Token: identity.AccessToken, Owner: owner, Repo: repo,
220+
Token: token, Owner: owner, Repo: repo,
204221
Page: page, PerPage: perPage,
205222
InstallID: identity.InstallationID, IsOAuth: identity.OauthRefreshToken != "",
206223
})

backend/pkg/git/gitea/operation.go

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,102 @@ func (g *Gitea) Branches(ctx context.Context, opts *domain.BranchesOptions) ([]*
483483

484484
// DeleteWebhook 实现 GitPlatformClient 接口
485485
func (g *Gitea) DeleteWebhook(ctx context.Context, opts *domain.WebhookOptions) error {
486-
// TODO: 实现 Gitea webhook 删除
487-
return fmt.Errorf("not implemented")
486+
owner, repo, err := parseGiteaRepoPath(opts.RepoURL)
487+
if err != nil {
488+
return err
489+
}
490+
491+
client := &http.Client{Timeout: 30 * time.Second}
492+
493+
for page := 1; ; page++ {
494+
apiURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/hooks?page=%d&limit=50",
495+
g.baseURL, url.PathEscape(owner), url.PathEscape(repo), page)
496+
body, err := giteaAPIGet(ctx, apiURL, opts.Token)
497+
if err != nil {
498+
return fmt.Errorf("list hooks: %w", err)
499+
}
500+
501+
var hooks []struct {
502+
ID int64 `json:"id"`
503+
Config struct {
504+
URL string `json:"url"`
505+
} `json:"config"`
506+
}
507+
if err := json.Unmarshal(body, &hooks); err != nil {
508+
return fmt.Errorf("unmarshal hooks: %w", err)
509+
}
510+
if len(hooks) == 0 {
511+
break
512+
}
513+
for _, hook := range hooks {
514+
if hook.Config.URL == opts.WebhookURL {
515+
deleteURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/hooks/%d",
516+
g.baseURL, url.PathEscape(owner), url.PathEscape(repo), hook.ID)
517+
delReq, err := http.NewRequestWithContext(ctx, http.MethodDelete, deleteURL, nil)
518+
if err != nil {
519+
return fmt.Errorf("create delete request: %w", err)
520+
}
521+
delReq.Header.Set("Authorization", fmt.Sprintf("token %s", opts.Token))
522+
delResp, err := client.Do(delReq)
523+
if err != nil {
524+
return fmt.Errorf("delete hook %d: %w", hook.ID, err)
525+
}
526+
delResp.Body.Close()
527+
if delResp.StatusCode != http.StatusOK && delResp.StatusCode != http.StatusNoContent {
528+
return fmt.Errorf("delete hook %d returned status %d", hook.ID, delResp.StatusCode)
529+
}
530+
return nil
531+
}
532+
}
533+
}
534+
return nil
488535
}
489536

490537
// CreateWebhook 实现 GitPlatformClient 接口
491538
func (g *Gitea) CreateWebhook(ctx context.Context, opts *domain.CreateWebhookOptions) error {
492-
// TODO: 实现 Gitea webhook 创建
493-
return fmt.Errorf("not implemented")
539+
owner, repo, err := parseGiteaRepoPath(opts.RepoURL)
540+
if err != nil {
541+
return err
542+
}
543+
544+
events := opts.Events
545+
if len(events) == 0 {
546+
events = []string{"push", "pull_request", "issue_comment"}
547+
}
548+
549+
payload := map[string]any{
550+
"type": "gitea",
551+
"config": map[string]string{
552+
"url": opts.WebhookURL,
553+
"content_type": "json",
554+
"secret": opts.SecretToken,
555+
},
556+
"events": events,
557+
"active": true,
558+
}
559+
jsonBody, err := json.Marshal(payload)
560+
if err != nil {
561+
return fmt.Errorf("marshal payload: %w", err)
562+
}
563+
564+
apiURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/hooks",
565+
g.baseURL, url.PathEscape(owner), url.PathEscape(repo))
566+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(jsonBody))
567+
if err != nil {
568+
return fmt.Errorf("create request: %w", err)
569+
}
570+
req.Header.Set("Content-Type", "application/json")
571+
req.Header.Set("Authorization", fmt.Sprintf("token %s", opts.Token))
572+
573+
client := &http.Client{Timeout: 30 * time.Second}
574+
resp, err := client.Do(req)
575+
if err != nil {
576+
return fmt.Errorf("create webhook: %w", err)
577+
}
578+
defer resp.Body.Close()
579+
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
580+
body, _ := io.ReadAll(resp.Body)
581+
return fmt.Errorf("create webhook returned status %d: %s", resp.StatusCode, string(body))
582+
}
583+
return nil
494584
}

backend/pkg/git/gitee/operation.go

Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -445,18 +445,133 @@ func (g *Gitee) Archive(ctx context.Context, opts *domain.ArchiveOptions) (*doma
445445

446446
// Branches 实现 GitPlatformClient 接口
447447
func (g *Gitee) Branches(ctx context.Context, opts *domain.BranchesOptions) ([]*domain.BranchInfo, error) {
448-
// TODO: 实现 Gitee branches 列表
449-
return nil, fmt.Errorf("not implemented")
448+
resp, err := ListBranches(ctx, opts.Token, opts.Owner, opts.Repo, opts.Page, opts.PerPage, opts.IsOAuth)
449+
if err != nil {
450+
return nil, err
451+
}
452+
result := make([]*domain.BranchInfo, 0, len(resp))
453+
for _, b := range resp {
454+
result = append(result, &domain.BranchInfo{Name: b.Name})
455+
}
456+
return result, nil
450457
}
451458

452459
// DeleteWebhook 实现 GitPlatformClient 接口
453460
func (g *Gitee) DeleteWebhook(ctx context.Context, opts *domain.WebhookOptions) error {
454-
// TODO: 实现 Gitee webhook 删除
455-
return fmt.Errorf("not implemented")
461+
owner, repo, err := parseGiteeRepoPath(opts.RepoURL)
462+
if err != nil {
463+
return err
464+
}
465+
466+
client := &http.Client{Timeout: 30 * time.Second}
467+
468+
// 分页查找匹配的 webhook
469+
for page := 1; ; page++ {
470+
apiURL := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/%s/hooks?page=%d&per_page=100",
471+
url.PathEscape(owner), url.PathEscape(repo), page)
472+
if opts.IsOAuth {
473+
apiURL += "&access_token=" + url.QueryEscape(opts.Token)
474+
}
475+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL, nil)
476+
if err != nil {
477+
return fmt.Errorf("create request: %w", err)
478+
}
479+
if !opts.IsOAuth {
480+
req.Header.Set("Authorization", "token "+opts.Token)
481+
}
482+
resp, err := client.Do(req)
483+
if err != nil {
484+
return fmt.Errorf("list hooks: %w", err)
485+
}
486+
body, _ := io.ReadAll(resp.Body)
487+
resp.Body.Close()
488+
if resp.StatusCode != http.StatusOK {
489+
return fmt.Errorf("list hooks returned status %d: %s", resp.StatusCode, string(body))
490+
}
491+
492+
var hooks []struct {
493+
ID int64 `json:"id"`
494+
URL string `json:"url"`
495+
}
496+
if err := json.Unmarshal(body, &hooks); err != nil {
497+
return fmt.Errorf("unmarshal hooks: %w", err)
498+
}
499+
if len(hooks) == 0 {
500+
break
501+
}
502+
for _, hook := range hooks {
503+
if hook.URL == opts.WebhookURL {
504+
deleteURL := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/%s/hooks/%d",
505+
url.PathEscape(owner), url.PathEscape(repo), hook.ID)
506+
if opts.IsOAuth {
507+
deleteURL += "?access_token=" + url.QueryEscape(opts.Token)
508+
}
509+
delReq, err := http.NewRequestWithContext(ctx, http.MethodDelete, deleteURL, nil)
510+
if err != nil {
511+
return fmt.Errorf("create delete request: %w", err)
512+
}
513+
if !opts.IsOAuth {
514+
delReq.Header.Set("Authorization", "token "+opts.Token)
515+
}
516+
delResp, err := client.Do(delReq)
517+
if err != nil {
518+
return fmt.Errorf("delete hook %d: %w", hook.ID, err)
519+
}
520+
delResp.Body.Close()
521+
if delResp.StatusCode != http.StatusOK && delResp.StatusCode != http.StatusNoContent {
522+
return fmt.Errorf("delete hook %d returned status %d", hook.ID, delResp.StatusCode)
523+
}
524+
return nil
525+
}
526+
}
527+
}
528+
return nil
456529
}
457530

458531
// CreateWebhook 实现 GitPlatformClient 接口
459532
func (g *Gitee) CreateWebhook(ctx context.Context, opts *domain.CreateWebhookOptions) error {
460-
// TODO: 实现 Gitee webhook 创建
461-
return fmt.Errorf("not implemented")
533+
owner, repo, err := parseGiteeRepoPath(opts.RepoURL)
534+
if err != nil {
535+
return err
536+
}
537+
538+
client := &http.Client{Timeout: 30 * time.Second}
539+
apiURL := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/%s/hooks",
540+
url.PathEscape(owner), url.PathEscape(repo))
541+
542+
payload := map[string]any{
543+
"url": opts.WebhookURL,
544+
"password": opts.SecretToken,
545+
"push_events": true,
546+
"merge_requests_events": true,
547+
"note_events": true,
548+
}
549+
if opts.IsOAuth {
550+
payload["access_token"] = opts.Token
551+
}
552+
553+
jsonBody, err := json.Marshal(payload)
554+
if err != nil {
555+
return fmt.Errorf("marshal payload: %w", err)
556+
}
557+
558+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(jsonBody))
559+
if err != nil {
560+
return fmt.Errorf("create request: %w", err)
561+
}
562+
req.Header.Set("Content-Type", "application/json")
563+
if !opts.IsOAuth {
564+
req.Header.Set("Authorization", "token "+opts.Token)
565+
}
566+
567+
resp, err := client.Do(req)
568+
if err != nil {
569+
return fmt.Errorf("create webhook: %w", err)
570+
}
571+
defer resp.Body.Close()
572+
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
573+
body, _ := io.ReadAll(resp.Body)
574+
return fmt.Errorf("create webhook returned status %d: %s", resp.StatusCode, string(body))
575+
}
576+
return nil
462577
}

backend/pkg/git/gitlab/operation.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,11 @@ func (g *Gitlab) UserInfo(ctx context.Context, token string) (*domain.PlatformUs
369369

370370
// Repositories 实现 GitPlatformClient 接口
371371
func (g *Gitlab) Repositories(ctx context.Context, opts *domain.RepositoryOptions) ([]domain.AuthRepository, error) {
372-
return g.GetAuthorizedRepositories(ctx, opts.Token)
372+
client, err := g.newClientWithToken(opts.Token, opts.IsOAuth)
373+
if err != nil {
374+
return nil, fmt.Errorf("new client: %w", err)
375+
}
376+
return g.listProjects(ctx, client)
373377
}
374378

375379
// Tree 实现 GitPlatformClient 接口
@@ -433,7 +437,11 @@ func (g *Gitlab) Archive(ctx context.Context, opts *domain.ArchiveOptions) (*dom
433437

434438
// Branches 实现 GitPlatformClient 接口
435439
func (g *Gitlab) Branches(ctx context.Context, opts *domain.BranchesOptions) ([]*domain.BranchInfo, error) {
436-
resp, err := g.ListBranches(ctx, opts.Token, opts.Owner, opts.IsOAuth, opts.Page, opts.PerPage)
440+
projectPath := opts.Owner
441+
if opts.Repo != "" {
442+
projectPath = opts.Owner + "/" + opts.Repo
443+
}
444+
resp, err := g.ListBranches(ctx, opts.Token, projectPath, opts.IsOAuth, opts.Page, opts.PerPage)
437445
if err != nil {
438446
return nil, err
439447
}

0 commit comments

Comments
 (0)