mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-19 14:05:31 +00:00
parent
c986c7f5ee
commit
0b2b776ed8
13 changed files with 27 additions and 356 deletions
|
@ -164,11 +164,6 @@ var flags = []cli.Flag{
|
|||
Name: "registry-service",
|
||||
Usage: "registry plugin endpoint",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
EnvVars: []string{"WOODPECKER_GATEKEEPER_ENDPOINT"},
|
||||
Name: "gating-service",
|
||||
Usage: "gated build endpoint",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
EnvVars: []string{"WOODPECKER_CONFIG_SERVICE_ENDPOINT"},
|
||||
Name: "config-service-endpoint",
|
||||
|
|
|
@ -43,7 +43,6 @@ import (
|
|||
"github.com/woodpecker-ci/woodpecker/server/logging"
|
||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||
"github.com/woodpecker-ci/woodpecker/server/plugins/configuration"
|
||||
"github.com/woodpecker-ci/woodpecker/server/plugins/sender"
|
||||
"github.com/woodpecker-ci/woodpecker/server/pubsub"
|
||||
"github.com/woodpecker-ci/woodpecker/server/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/server/router"
|
||||
|
@ -266,13 +265,8 @@ func setupEvilGlobals(c *cli.Context, v store.Store, r remote.Remote) {
|
|||
}
|
||||
server.Config.Services.Registries = setupRegistryService(c, v)
|
||||
server.Config.Services.Secrets = setupSecretService(c, v)
|
||||
server.Config.Services.Senders = sender.New(v, v)
|
||||
server.Config.Services.Environ = setupEnvironService(c, v)
|
||||
|
||||
if endpoint := c.String("gating-service"); endpoint != "" {
|
||||
server.Config.Services.Senders = sender.NewRemote(endpoint)
|
||||
}
|
||||
|
||||
if endpoint := c.String("config-service-endpoint"); endpoint != "" {
|
||||
secret := c.String("config-service-secret")
|
||||
if secret == "" {
|
||||
|
|
|
@ -33,7 +33,6 @@ var Config = struct {
|
|||
Pubsub pubsub.Publisher
|
||||
Queue queue.Queue
|
||||
Logs logging.Log
|
||||
Senders model.SenderService
|
||||
Secrets model.SecretService
|
||||
Registries model.RegistryService
|
||||
Environ model.EnvironService
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
// Copyright 2021 Woodpecker Authors
|
||||
// Copyright 2018 Drone.IO 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 model
|
||||
|
||||
type SenderService interface {
|
||||
SenderAllowed(*User, *Repo, *Build, *Config) (bool, error)
|
||||
SenderCreate(*Repo, *Sender) error
|
||||
SenderUpdate(*Repo, *Sender) error
|
||||
SenderDelete(*Repo, string) error
|
||||
SenderList(*Repo) ([]*Sender, error)
|
||||
}
|
||||
|
||||
type SenderStore interface {
|
||||
SenderFind(*Repo, string) (*Sender, error)
|
||||
SenderList(*Repo) ([]*Sender, error)
|
||||
SenderCreate(*Sender) error
|
||||
SenderUpdate(*Sender) error
|
||||
SenderDelete(*Sender) error
|
||||
}
|
||||
|
||||
type Sender struct {
|
||||
ID int64 `json:"-" xorm:"pk autoincr 'sender_id'"`
|
||||
RepoID int64 `json:"-" xorm:"UNIQUE(s) INDEX 'sender_repo_id'"`
|
||||
Login string `json:"login" xorm:"UNIQUE(s) 'sender_login'"`
|
||||
Allow bool `json:"allow" xorm:"sender_allow"`
|
||||
Block bool `json:"block" xorm:"sender_block"`
|
||||
Branch []string `json:"branch" xorm:"-"`
|
||||
Deploy []string `json:"deploy" xorm:"-"`
|
||||
Event []string `json:"event" xorm:"-"`
|
||||
}
|
||||
|
||||
// TableName return database table name for xorm
|
||||
func (Sender) TableName() string {
|
||||
return "senders"
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package sender
|
||||
|
||||
import (
|
||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||
)
|
||||
|
||||
type builtin struct {
|
||||
store model.SenderStore
|
||||
conf model.ConfigStore
|
||||
}
|
||||
|
||||
// New returns a new local gating service.
|
||||
func New(store model.SenderStore, conf model.ConfigStore) model.SenderService {
|
||||
return &builtin{store, conf}
|
||||
}
|
||||
|
||||
func (b *builtin) SenderAllowed(user *model.User, repo *model.Repo, build *model.Build, conf *model.Config) (bool, error) {
|
||||
if build.Event == model.EventPull && build.Sender != user.Login {
|
||||
// check to see if the configuration has already been used in an
|
||||
// existing build. If yes it is considered approved.
|
||||
if ok, _ := b.conf.ConfigFindApproved(conf); ok {
|
||||
return true, nil
|
||||
}
|
||||
// else check to see if the configuration is sent from a user
|
||||
// account that is a repositroy approver themselves.
|
||||
sender, err := b.store.SenderFind(repo, build.Sender)
|
||||
if err != nil || sender.Block {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (b *builtin) SenderCreate(repo *model.Repo, sender *model.Sender) error {
|
||||
return b.store.SenderCreate(sender)
|
||||
}
|
||||
|
||||
func (b *builtin) SenderUpdate(repo *model.Repo, sender *model.Sender) error {
|
||||
return b.store.SenderUpdate(sender)
|
||||
}
|
||||
|
||||
func (b *builtin) SenderDelete(repo *model.Repo, login string) error {
|
||||
sender, err := b.store.SenderFind(repo, login)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.store.SenderDelete(sender)
|
||||
}
|
||||
|
||||
func (b *builtin) SenderList(repo *model.Repo) ([]*model.Sender, error) {
|
||||
return b.store.SenderList(repo)
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package sender
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||
"github.com/woodpecker-ci/woodpecker/server/plugins/internal"
|
||||
)
|
||||
|
||||
type plugin struct {
|
||||
endpoint string
|
||||
}
|
||||
|
||||
// NewRemote returns a new remote gating service.
|
||||
func NewRemote(endpoint string) model.SenderService {
|
||||
return &plugin{endpoint}
|
||||
}
|
||||
|
||||
func (p *plugin) SenderAllowed(user *model.User, repo *model.Repo, build *model.Build, conf *model.Config) (bool, error) {
|
||||
path := fmt.Sprintf("%s/senders/%s/%s/%s/verify", p.endpoint, repo.Owner, repo.Name, build.Sender)
|
||||
data := map[string]interface{}{
|
||||
"build": build,
|
||||
"config": conf,
|
||||
}
|
||||
err := internal.Send(context.TODO(), "POST", path, &data, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
func (p *plugin) SenderCreate(repo *model.Repo, sender *model.Sender) error {
|
||||
path := fmt.Sprintf("%s/senders/%s/%s", p.endpoint, repo.Owner, repo.Name)
|
||||
return internal.Send(context.TODO(), "POST", path, sender, nil)
|
||||
}
|
||||
|
||||
func (p *plugin) SenderUpdate(repo *model.Repo, sender *model.Sender) error {
|
||||
path := fmt.Sprintf("%s/senders/%s/%s", p.endpoint, repo.Owner, repo.Name)
|
||||
return internal.Send(context.TODO(), "PUT", path, sender, nil)
|
||||
}
|
||||
|
||||
func (p *plugin) SenderDelete(repo *model.Repo, login string) error {
|
||||
path := fmt.Sprintf("%s/senders/%s/%s/%s", p.endpoint, repo.Owner, repo.Name, login)
|
||||
return internal.Send(context.TODO(), "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
func (p *plugin) SenderList(repo *model.Repo) (out []*model.Sender, err error) {
|
||||
path := fmt.Sprintf("%s/senders/%s/%s", p.endpoint, repo.Owner, repo.Name)
|
||||
err = internal.Send(context.TODO(), "GET", path, nil, out)
|
||||
return out, err
|
||||
}
|
26
server/store/datastore/migration/005_drop_senders.go
Normal file
26
server/store/datastore/migration/005_drop_senders.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2022 Woodpecker Authors
|
||||
//
|
||||
// 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 migration
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
var dropSenders = task{
|
||||
name: "drop-senders",
|
||||
fn: func(sess *xorm.Session) error {
|
||||
return sess.DropTable("senders")
|
||||
},
|
||||
}
|
|
@ -32,6 +32,7 @@ var migrationTasks = []*task{
|
|||
&alterTableReposDropAllowDeploysAllowTags,
|
||||
&fixPRSecretEventName,
|
||||
&alterTableReposDropCounter,
|
||||
&dropSenders,
|
||||
}
|
||||
|
||||
var allBeans = []interface{}{
|
||||
|
@ -46,7 +47,6 @@ var allBeans = []interface{}{
|
|||
new(model.Registry),
|
||||
new(model.Repo),
|
||||
new(model.Secret),
|
||||
new(model.Sender),
|
||||
new(model.Task),
|
||||
new(model.User),
|
||||
}
|
||||
|
|
|
@ -61,9 +61,6 @@ func (s storage) DeleteRepo(repo *model.Repo) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if _, err := sess.Where("sender_repo_id = ?", repo.ID).Delete(new(model.Sender)); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := sess.Where("config_repo_id = ?", repo.ID).Delete(new(model.Config)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -372,7 +372,6 @@ func TestRepoCrud(t *testing.T) {
|
|||
new(model.Proc),
|
||||
new(model.File),
|
||||
new(model.Secret),
|
||||
new(model.Sender),
|
||||
new(model.Registry),
|
||||
new(model.Config))
|
||||
defer closer()
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
// Copyright 2021 Woodpecker Authors
|
||||
//
|
||||
// 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 datastore
|
||||
|
||||
import (
|
||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||
)
|
||||
|
||||
func (s storage) SenderFind(repo *model.Repo, login string) (*model.Sender, error) {
|
||||
sender := &model.Sender{
|
||||
RepoID: repo.ID,
|
||||
Login: login,
|
||||
}
|
||||
return sender, wrapGet(s.engine.Get(sender))
|
||||
}
|
||||
|
||||
func (s storage) SenderList(repo *model.Repo) ([]*model.Sender, error) {
|
||||
senders := make([]*model.Sender, 0, perPage)
|
||||
return senders, s.engine.Where("sender_repo_id = ?", repo.ID).Find(&senders)
|
||||
}
|
||||
|
||||
func (s storage) SenderCreate(sender *model.Sender) error {
|
||||
// only Insert set auto created ID back to object
|
||||
_, err := s.engine.Insert(sender)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s storage) SenderUpdate(sender *model.Sender) error {
|
||||
_, err := s.engine.ID(sender.ID).AllCols().Update(sender)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s storage) SenderDelete(sender *model.Sender) error {
|
||||
_, err := s.engine.ID(sender.ID).Delete(new(model.Sender))
|
||||
return err
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
// Copyright 2018 Drone.IO 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 datastore
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||
)
|
||||
|
||||
func TestSenderFind(t *testing.T) {
|
||||
store, closer := newTestStore(t, new(model.Sender))
|
||||
defer closer()
|
||||
|
||||
err := store.SenderCreate(&model.Sender{
|
||||
RepoID: 1,
|
||||
Login: "octocat",
|
||||
Allow: true,
|
||||
Block: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: insert secret: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
sender, err := store.SenderFind(&model.Repo{ID: 1}, "octocat")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if got, want := sender.RepoID, int64(1); got != want {
|
||||
t.Errorf("Want repo id %d, got %d", want, got)
|
||||
}
|
||||
if got, want := sender.Login, "octocat"; got != want {
|
||||
t.Errorf("Want sender login %s, got %s", want, got)
|
||||
}
|
||||
if got, want := sender.Allow, true; got != want {
|
||||
t.Errorf("Want sender allow %v, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSenderList(t *testing.T) {
|
||||
store, closer := newTestStore(t, new(model.Sender))
|
||||
defer closer()
|
||||
|
||||
assert.NoError(t, store.SenderCreate(&model.Sender{
|
||||
RepoID: 1,
|
||||
Login: "octocat",
|
||||
Allow: true,
|
||||
Block: false,
|
||||
}))
|
||||
assert.NoError(t, store.SenderCreate(&model.Sender{
|
||||
RepoID: 1,
|
||||
Login: "defunkt",
|
||||
Allow: true,
|
||||
Block: false,
|
||||
}))
|
||||
|
||||
list, err := store.SenderList(&model.Repo{ID: 1})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if got, want := len(list), 2; got != want {
|
||||
t.Errorf("Want %d senders, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSenderUpdate(t *testing.T) {
|
||||
store, closer := newTestStore(t, new(model.Sender))
|
||||
defer closer()
|
||||
|
||||
sender := &model.Sender{
|
||||
RepoID: 1,
|
||||
Login: "octocat",
|
||||
Allow: true,
|
||||
Block: false,
|
||||
}
|
||||
if err := store.SenderCreate(sender); err != nil {
|
||||
t.Errorf("Unexpected error: insert sender: %s", err)
|
||||
return
|
||||
}
|
||||
assert.EqualValues(t, 1, sender.ID)
|
||||
sender.Allow = false
|
||||
if err := store.SenderUpdate(sender); err != nil {
|
||||
t.Errorf("Unexpected error: update sender: %s", err)
|
||||
return
|
||||
}
|
||||
updated, err := store.SenderFind(&model.Repo{ID: 1}, "octocat")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, updated.Allow)
|
||||
}
|
||||
|
||||
func TestSenderIndexes(t *testing.T) {
|
||||
store, closer := newTestStore(t, new(model.Sender))
|
||||
defer closer()
|
||||
|
||||
if err := store.SenderCreate(&model.Sender{
|
||||
RepoID: 1,
|
||||
Login: "octocat",
|
||||
Allow: true,
|
||||
Block: false,
|
||||
}); err != nil {
|
||||
t.Errorf("Unexpected error: insert sender: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// fail due to duplicate name
|
||||
if err := store.SenderCreate(&model.Sender{
|
||||
RepoID: 1,
|
||||
Login: "octocat",
|
||||
Allow: true,
|
||||
Block: false,
|
||||
}); err == nil {
|
||||
t.Errorf("Unexpected error: duplicate login")
|
||||
}
|
||||
}
|
|
@ -104,14 +104,6 @@ type Store interface {
|
|||
ConfigCreate(*model.Config) error
|
||||
BuildConfigCreate(*model.BuildConfig) error
|
||||
|
||||
// Sender
|
||||
SenderFind(*model.Repo, string) (*model.Sender, error)
|
||||
// SenderList TODO: paginate
|
||||
SenderList(*model.Repo) ([]*model.Sender, error)
|
||||
SenderCreate(*model.Sender) error
|
||||
SenderUpdate(*model.Sender) error
|
||||
SenderDelete(*model.Sender) error
|
||||
|
||||
// Secrets
|
||||
SecretFind(*model.Repo, string) (*model.Secret, error)
|
||||
SecretList(*model.Repo) ([]*model.Secret, error)
|
||||
|
|
Loading…
Reference in a new issue