-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathgitlab.go
146 lines (122 loc) · 4.27 KB
/
gitlab.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//
// Copyright 2024 Stacklok, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package gitlab provides the GitLab OAuth provider implementation
package gitlab
import (
"context"
"encoding/json"
"errors"
"net/http"
"golang.org/x/oauth2"
config "github.com/stacklok/minder/internal/config/server"
"github.com/stacklok/minder/internal/db"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
provifv1 "github.com/stacklok/minder/pkg/providers/v1"
)
// Class is the string that represents the GitLab provider class
const Class = "gitlab"
// Implements is the list of provider types that the DockerHub provider implements
var Implements = []db.ProviderType{
db.ProviderTypeGit,
db.ProviderTypeRest,
db.ProviderTypeRepoLister,
}
// AuthorizationFlows is the list of authorization flows that the DockerHub provider supports
var AuthorizationFlows = []db.AuthorizationFlow{
db.AuthorizationFlowUserInput,
db.AuthorizationFlowOauth2AuthorizationCodeFlow,
}
// Ensure that the GitLab provider implements the right interfaces
var _ provifv1.Git = (*gitlabClient)(nil)
var _ provifv1.REST = (*gitlabClient)(nil)
var _ provifv1.RepoLister = (*gitlabClient)(nil)
type gitlabClient struct {
cred provifv1.GitLabCredential
cli *http.Client
glcfg *minderv1.GitLabProviderConfig
webhookURL string
gitConfig config.GitConfig
// secret for the webhook. This is stored in the
// structure to allow efficient fetching.
currentWebhookSecret string
}
// New creates a new GitLab provider
// Note that the webhook URL should already contain the provider class in the path
func New(
cred provifv1.GitLabCredential,
cfg *minderv1.GitLabProviderConfig,
webhookURL string,
currentWebhookSecret string,
) (*gitlabClient, error) {
// TODO: We need a context here.
cli := oauth2.NewClient(context.Background(), cred.GetAsOAuth2TokenSource())
if cfg.Endpoint == "" {
cfg.Endpoint = "https://gitlab.com/api/v4/"
}
if webhookURL == "" {
return nil, errors.New("webhook URL is required")
}
return &gitlabClient{
cred: cred,
cli: cli,
glcfg: cfg,
webhookURL: webhookURL,
currentWebhookSecret: currentWebhookSecret,
// TODO: Add git config
}, nil
}
type glConfigWrapper struct {
GitLab *minderv1.GitLabProviderConfig `json:"gitlab" yaml:"gitlab" mapstructure:"gitlab" validate:"required"`
}
// ParseV1Config parses the raw configuration into a GitLabProviderConfig
//
// TODO: This should be moved to a common location
func ParseV1Config(rawCfg json.RawMessage) (*minderv1.GitLabProviderConfig, error) {
var cfg glConfigWrapper
if err := json.Unmarshal(rawCfg, &cfg); err != nil {
return nil, err
}
if cfg.GitLab == nil {
// Return a default but working config
return &minderv1.GitLabProviderConfig{}, nil
}
return cfg.GitLab, nil
}
// MarshalV1Config marshals and validates the given config
// so it can safely be stored in the database
func MarshalV1Config(rawCfg json.RawMessage) (json.RawMessage, error) {
var w glConfigWrapper
if err := json.Unmarshal(rawCfg, &w); err != nil {
return nil, err
}
// TODO: Add validation
// err := w.GitLab.Validate()
// if err != nil {
// return nil, fmt.Errorf("error validating gitlab config: %w", err)
// }
return json.Marshal(w)
}
// CanImplement returns true if the provider can implement the given trait
func (_ *gitlabClient) CanImplement(trait minderv1.ProviderType) bool {
return trait == minderv1.ProviderType_PROVIDER_TYPE_GIT ||
trait == minderv1.ProviderType_PROVIDER_TYPE_REST
}
func (c *gitlabClient) GetCredential() provifv1.GitLabCredential {
return c.cred
}
// SupportsEntity implements the Provider interface
func (_ *gitlabClient) SupportsEntity(entType minderv1.Entity) bool {
return entType == minderv1.Entity_ENTITY_REPOSITORIES
}