mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-02-10 18:31:20 +02:00
Merge pull request #1737 from tboerger/feature/org-secrets
Organization/Team secrets
This commit is contained in:
commit
abaa02efa2
@ -61,6 +61,15 @@ type Client interface {
|
|||||||
// SecretDel deletes a named repository secret.
|
// SecretDel deletes a named repository secret.
|
||||||
SecretDel(string, string, string) error
|
SecretDel(string, string, string) error
|
||||||
|
|
||||||
|
// TeamSecretList returns a list of all team secrets.
|
||||||
|
TeamSecretList(string) ([]*model.Secret, error)
|
||||||
|
|
||||||
|
// TeamSecretPost create or updates a team secret.
|
||||||
|
TeamSecretPost(string, *model.Secret) error
|
||||||
|
|
||||||
|
// TeamSecretDel deletes a named team secret.
|
||||||
|
TeamSecretDel(string, string) error
|
||||||
|
|
||||||
// Build returns a repository build by number.
|
// Build returns a repository build by number.
|
||||||
Build(string, string, int) (*model.Build, error)
|
Build(string, string, int) (*model.Build, error)
|
||||||
|
|
||||||
|
@ -40,8 +40,10 @@ const (
|
|||||||
pathLog = "%s/api/repos/%s/%s/logs/%d/%d"
|
pathLog = "%s/api/repos/%s/%s/logs/%d/%d"
|
||||||
pathKey = "%s/api/repos/%s/%s/key"
|
pathKey = "%s/api/repos/%s/%s/key"
|
||||||
pathSign = "%s/api/repos/%s/%s/sign"
|
pathSign = "%s/api/repos/%s/%s/sign"
|
||||||
pathSecrets = "%s/api/repos/%s/%s/secrets"
|
pathRepoSecrets = "%s/api/repos/%s/%s/secrets"
|
||||||
pathSecret = "%s/api/repos/%s/%s/secrets/%s"
|
pathRepoSecret = "%s/api/repos/%s/%s/secrets/%s"
|
||||||
|
pathTeamSecrets = "%s/api/teams/%s/secrets"
|
||||||
|
pathTeamSecret = "%s/api/teams/%s/secrets/%s"
|
||||||
pathNodes = "%s/api/nodes"
|
pathNodes = "%s/api/nodes"
|
||||||
pathNode = "%s/api/nodes/%d"
|
pathNode = "%s/api/nodes/%d"
|
||||||
pathUsers = "%s/api/users"
|
pathUsers = "%s/api/users"
|
||||||
@ -265,20 +267,40 @@ func (c *client) Deploy(owner, name string, num int, env string, params map[stri
|
|||||||
// SecretList returns a list of a repository secrets.
|
// SecretList returns a list of a repository secrets.
|
||||||
func (c *client) SecretList(owner, name string) ([]*model.Secret, error) {
|
func (c *client) SecretList(owner, name string) ([]*model.Secret, error) {
|
||||||
var out []*model.Secret
|
var out []*model.Secret
|
||||||
uri := fmt.Sprintf(pathSecrets, c.base, owner, name)
|
uri := fmt.Sprintf(pathRepoSecrets, c.base, owner, name)
|
||||||
err := c.get(uri, &out)
|
err := c.get(uri, &out)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SecretPost create or updates a repository secret.
|
// SecretPost create or updates a repository secret.
|
||||||
func (c *client) SecretPost(owner, name string, secret *model.Secret) error {
|
func (c *client) SecretPost(owner, name string, secret *model.Secret) error {
|
||||||
uri := fmt.Sprintf(pathSecrets, c.base, owner, name)
|
uri := fmt.Sprintf(pathRepoSecrets, c.base, owner, name)
|
||||||
return c.post(uri, secret, nil)
|
return c.post(uri, secret, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SecretDel deletes a named repository secret.
|
// SecretDel deletes a named repository secret.
|
||||||
func (c *client) SecretDel(owner, name, secret string) error {
|
func (c *client) SecretDel(owner, name, secret string) error {
|
||||||
uri := fmt.Sprintf(pathSecret, c.base, owner, name, secret)
|
uri := fmt.Sprintf(pathRepoSecret, c.base, owner, name, secret)
|
||||||
|
return c.delete(uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TeamSecretList returns a list of a repository secrets.
|
||||||
|
func (c *client) TeamSecretList(team string) ([]*model.Secret, error) {
|
||||||
|
var out []*model.Secret
|
||||||
|
uri := fmt.Sprintf(pathTeamSecrets, c.base, team)
|
||||||
|
err := c.get(uri, &out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TeamSecretPost create or updates a repository secret.
|
||||||
|
func (c *client) TeamSecretPost(team string, secret *model.Secret) error {
|
||||||
|
uri := fmt.Sprintf(pathTeamSecrets, c.base, team)
|
||||||
|
return c.post(uri, secret, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TeamSecretDel deletes a named repository secret.
|
||||||
|
func (c *client) TeamSecretDel(team, secret string) error {
|
||||||
|
uri := fmt.Sprintf(pathTeamSecret, c.base, team, secret)
|
||||||
return c.delete(uri)
|
return c.delete(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ func main() {
|
|||||||
signCmd,
|
signCmd,
|
||||||
repoCmd,
|
repoCmd,
|
||||||
userCmd,
|
userCmd,
|
||||||
|
orgCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Run(os.Args)
|
app.Run(os.Args)
|
||||||
|
11
drone/org.go
Normal file
11
drone/org.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/codegangsta/cli"
|
||||||
|
|
||||||
|
var orgCmd = cli.Command{
|
||||||
|
Name: "org",
|
||||||
|
Usage: "manage organizations",
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
orgSecretCmd,
|
||||||
|
},
|
||||||
|
}
|
13
drone/org_secret.go
Normal file
13
drone/org_secret.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/codegangsta/cli"
|
||||||
|
|
||||||
|
var orgSecretCmd = cli.Command{
|
||||||
|
Name: "secret",
|
||||||
|
Usage: "manage secrets",
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
orgSecretAddCmd,
|
||||||
|
orgSecretRemoveCmd,
|
||||||
|
orgSecretListCmd,
|
||||||
|
},
|
||||||
|
}
|
83
drone/org_secret_add.go
Normal file
83
drone/org_secret_add.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
var orgSecretAddCmd = cli.Command{
|
||||||
|
Name: "add",
|
||||||
|
Usage: "adds a secret",
|
||||||
|
ArgsUsage: "[org] [key] [value]",
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
if err := orgSecretAdd(c); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "event",
|
||||||
|
Usage: "inject the secret for these event types",
|
||||||
|
Value: &cli.StringSlice{
|
||||||
|
model.EventPush,
|
||||||
|
model.EventTag,
|
||||||
|
model.EventDeploy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "image",
|
||||||
|
Usage: "inject the secret for these image types",
|
||||||
|
Value: &cli.StringSlice{},
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "input",
|
||||||
|
Usage: "input secret value from a file",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func orgSecretAdd(c *cli.Context) error {
|
||||||
|
if len(c.Args().Tail()) != 3 {
|
||||||
|
cli.ShowSubcommandHelp(c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
team := c.Args().First()
|
||||||
|
name := c.Args().Get(1)
|
||||||
|
value := c.Args().Get(2)
|
||||||
|
|
||||||
|
secret := &model.Secret{}
|
||||||
|
secret.Name = name
|
||||||
|
secret.Value = value
|
||||||
|
secret.Images = c.StringSlice("image")
|
||||||
|
secret.Events = c.StringSlice("event")
|
||||||
|
|
||||||
|
if len(secret.Images) == 0 {
|
||||||
|
return fmt.Errorf("Please specify the --image parameter")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bradrydzewski) below we use an @ sybmol to denote that the secret
|
||||||
|
// value should be loaded from a file (inspired by curl). I'd prefer to use
|
||||||
|
// a --input flag to explicitly specify a filepath instead.
|
||||||
|
|
||||||
|
if strings.HasPrefix(secret.Value, "@") {
|
||||||
|
path := secret.Value[1:]
|
||||||
|
out, ferr := ioutil.ReadFile(path)
|
||||||
|
if ferr != nil {
|
||||||
|
return ferr
|
||||||
|
}
|
||||||
|
secret.Value = string(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.TeamSecretPost(team, secret)
|
||||||
|
}
|
1
drone/org_secret_info.go
Normal file
1
drone/org_secret_info.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package main
|
87
drone/org_secret_list.go
Normal file
87
drone/org_secret_list.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var orgSecretListCmd = cli.Command{
|
||||||
|
Name: "ls",
|
||||||
|
Usage: "list all secrets",
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
if err := orgSecretList(c); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "format",
|
||||||
|
Usage: "format output",
|
||||||
|
Value: tmplOrgSecretList,
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "image",
|
||||||
|
Usage: "filter by image",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "event",
|
||||||
|
Usage: "filter by event",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func orgSecretList(c *cli.Context) error {
|
||||||
|
if len(c.Args().Tail()) != 1 {
|
||||||
|
cli.ShowSubcommandHelp(c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
team := c.Args().First()
|
||||||
|
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets, err := client.TeamSecretList(team)
|
||||||
|
|
||||||
|
if err != nil || len(secrets) == 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl, err := template.New("_").Funcs(orgSecretFuncMap).Parse(c.String("format") + "\n")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, secret := range secrets {
|
||||||
|
if c.String("image") != "" && !stringInSlice(c.String("image"), secret.Images) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.String("event") != "" && !stringInSlice(c.String("event"), secret.Events) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl.Execute(os.Stdout, secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// template for secret list items
|
||||||
|
var tmplOrgSecretList = "\x1b[33m{{ .Name }} \x1b[0m" + `
|
||||||
|
Images: {{ list .Images }}
|
||||||
|
Events: {{ list .Events }}
|
||||||
|
`
|
||||||
|
|
||||||
|
var orgSecretFuncMap = template.FuncMap{
|
||||||
|
"list": func(s []string) string {
|
||||||
|
return strings.Join(s, ", ")
|
||||||
|
},
|
||||||
|
}
|
34
drone/org_secret_rm.go
Normal file
34
drone/org_secret_rm.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var orgSecretRemoveCmd = cli.Command{
|
||||||
|
Name: "rm",
|
||||||
|
Usage: "remove a secret",
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
if err := orgSecretRemove(c); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func orgSecretRemove(c *cli.Context) error {
|
||||||
|
if len(c.Args().Tail()) != 2 {
|
||||||
|
cli.ShowSubcommandHelp(c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
team := c.Args().First()
|
||||||
|
secret := c.Args().Get(1)
|
||||||
|
|
||||||
|
client, err := newClient(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.TeamSecretDel(team, secret)
|
||||||
|
}
|
48
model/repo_secret.go
Normal file
48
model/repo_secret.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type RepoSecret struct {
|
||||||
|
// the id for this secret.
|
||||||
|
ID int64 `json:"id" meddler:"secret_id,pk"`
|
||||||
|
|
||||||
|
// the foreign key for this secret.
|
||||||
|
RepoID int64 `json:"-" meddler:"secret_repo_id"`
|
||||||
|
|
||||||
|
// the name of the secret which will be used as the environment variable
|
||||||
|
// name at runtime.
|
||||||
|
Name string `json:"name" meddler:"secret_name"`
|
||||||
|
|
||||||
|
// the value of the secret which will be provided to the runtime environment
|
||||||
|
// as a named environment variable.
|
||||||
|
Value string `json:"value" meddler:"secret_value"`
|
||||||
|
|
||||||
|
// the secret is restricted to this list of images.
|
||||||
|
Images []string `json:"image,omitempty" meddler:"secret_images,json"`
|
||||||
|
|
||||||
|
// the secret is restricted to this list of events.
|
||||||
|
Events []string `json:"event,omitempty" meddler:"secret_events,json"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secret transforms a repo secret into a simple secret.
|
||||||
|
func (s *RepoSecret) Secret() *Secret {
|
||||||
|
return &Secret{
|
||||||
|
Name: s.Name,
|
||||||
|
Value: s.Value,
|
||||||
|
Images: s.Images,
|
||||||
|
Events: s.Events,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone provides a repo secrets clone without the value.
|
||||||
|
func (s *RepoSecret) Clone() *RepoSecret {
|
||||||
|
return &RepoSecret{
|
||||||
|
ID: s.ID,
|
||||||
|
Name: s.Name,
|
||||||
|
Images: s.Images,
|
||||||
|
Events: s.Events,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates the required fields and formats.
|
||||||
|
func (s *RepoSecret) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,27 +1,23 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import "path/filepath"
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
type Secret struct {
|
type Secret struct {
|
||||||
// the id for this secret.
|
|
||||||
ID int64 `json:"id" meddler:"secret_id,pk"`
|
|
||||||
|
|
||||||
// the foreign key for this secret.
|
|
||||||
RepoID int64 `json:"-" meddler:"secret_repo_id"`
|
|
||||||
|
|
||||||
// the name of the secret which will be used as the environment variable
|
// the name of the secret which will be used as the environment variable
|
||||||
// name at runtime.
|
// name at runtime.
|
||||||
Name string `json:"name" meddler:"secret_name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
// the value of the secret which will be provided to the runtime environment
|
// the value of the secret which will be provided to the runtime environment
|
||||||
// as a named environment variable.
|
// as a named environment variable.
|
||||||
Value string `json:"value" meddler:"secret_value"`
|
Value string `json:"value"`
|
||||||
|
|
||||||
// the secret is restricted to this list of images.
|
// the secret is restricted to this list of images.
|
||||||
Images []string `json:"image,omitempty" meddler:"secret_images,json"`
|
Images []string `json:"image,omitempty"`
|
||||||
|
|
||||||
// the secret is restricted to this list of events.
|
// the secret is restricted to this list of events.
|
||||||
Events []string `json:"event,omitempty" meddler:"secret_events,json"`
|
Events []string `json:"event,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match returns true if an image and event match the restricted list.
|
// Match returns true if an image and event match the restricted list.
|
||||||
@ -55,12 +51,3 @@ func (s *Secret) MatchEvent(event string) bool {
|
|||||||
func (s *Secret) Validate() error {
|
func (s *Secret) Validate() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Secret) Clone() *Secret {
|
|
||||||
return &Secret{
|
|
||||||
ID: s.ID,
|
|
||||||
Name: s.Name,
|
|
||||||
Images: s.Images,
|
|
||||||
Events: s.Events,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
48
model/team_secret.go
Normal file
48
model/team_secret.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type TeamSecret struct {
|
||||||
|
// the id for this secret.
|
||||||
|
ID int64 `json:"id" meddler:"team_secret_id,pk"`
|
||||||
|
|
||||||
|
// the foreign key for this secret.
|
||||||
|
Key string `json:"-" meddler:"team_secret_key"`
|
||||||
|
|
||||||
|
// the name of the secret which will be used as the environment variable
|
||||||
|
// name at runtime.
|
||||||
|
Name string `json:"name" meddler:"team_secret_name"`
|
||||||
|
|
||||||
|
// the value of the secret which will be provided to the runtime environment
|
||||||
|
// as a named environment variable.
|
||||||
|
Value string `json:"value" meddler:"team_secret_value"`
|
||||||
|
|
||||||
|
// the secret is restricted to this list of images.
|
||||||
|
Images []string `json:"image,omitempty" meddler:"team_secret_images,json"`
|
||||||
|
|
||||||
|
// the secret is restricted to this list of events.
|
||||||
|
Events []string `json:"event,omitempty" meddler:"team_secret_events,json"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secret transforms a repo secret into a simple secret.
|
||||||
|
func (s *TeamSecret) Secret() *Secret {
|
||||||
|
return &Secret{
|
||||||
|
Name: s.Name,
|
||||||
|
Value: s.Value,
|
||||||
|
Images: s.Images,
|
||||||
|
Events: s.Events,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone provides a repo secrets clone without the value.
|
||||||
|
func (s *TeamSecret) Clone() *TeamSecret {
|
||||||
|
return &TeamSecret{
|
||||||
|
ID: s.ID,
|
||||||
|
Name: s.Name,
|
||||||
|
Images: s.Images,
|
||||||
|
Events: s.Events,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates the required fields and formats.
|
||||||
|
func (s *TeamSecret) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -122,7 +122,7 @@ func (c *client) Login(res http.ResponseWriter, req *http.Request) (*model.User,
|
|||||||
defer response1.Body.Close()
|
defer response1.Body.Close()
|
||||||
|
|
||||||
contents, err := ioutil.ReadAll(response1.Body)
|
contents, err := ioutil.ReadAll(response1.Body)
|
||||||
if err !=nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ func (*client) Teams(u *model.User) ([]*model.Team, error) {
|
|||||||
|
|
||||||
func (c *client) Repo(u *model.User, owner, name string) (*model.Repo, error) {
|
func (c *client) Repo(u *model.User, owner, name string) (*model.Repo, error) {
|
||||||
client := NewClientWithToken(&c.Consumer, u.Token)
|
client := NewClientWithToken(&c.Consumer, u.Token)
|
||||||
repo , err := c.FindRepo(client,owner,name)
|
repo, err := c.FindRepo(client, owner, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ func (c *client) Perm(u *model.User, owner, repo string) (*model.Perm, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Must have admin to be able to list hooks. If have access the enable perms
|
// Must have admin to be able to list hooks. If have access the enable perms
|
||||||
_, err = client.Get(fmt.Sprintf("%s/rest/api/1.0/projects/%s/repos/%s/settings/hooks/%s", c.URL, owner, repo,"com.atlassian.stash.plugin.stash-web-post-receive-hooks-plugin:postReceiveHook"))
|
_, err = client.Get(fmt.Sprintf("%s/rest/api/1.0/projects/%s/repos/%s/settings/hooks/%s", c.URL, owner, repo, "com.atlassian.stash.plugin.stash-web-post-receive-hooks-plugin:postReceiveHook"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
perms.Push = true
|
perms.Push = true
|
||||||
perms.Admin = true
|
perms.Admin = true
|
||||||
@ -339,7 +339,7 @@ func (bs *client) DeleteHook(client *http.Client, project, slug, hook_key, link
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) FindRepo(client *http.Client, owner string, name string) (*model.Repo, error){
|
func (c *client) FindRepo(client *http.Client, owner string, name string) (*model.Repo, error) {
|
||||||
|
|
||||||
urlString := fmt.Sprintf("%s/rest/api/1.0/projects/%s/repos/%s", c.URL, owner, name)
|
urlString := fmt.Sprintf("%s/rest/api/1.0/projects/%s/repos/%s", c.URL, owner, name)
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ func (c *client) FindRepo(client *http.Client, owner string, name string) (*mode
|
|||||||
contents, err := ioutil.ReadAll(response.Body)
|
contents, err := ioutil.ReadAll(response.Body)
|
||||||
bsRepo := BSRepo{}
|
bsRepo := BSRepo{}
|
||||||
err = json.Unmarshal(contents, &bsRepo)
|
err = json.Unmarshal(contents, &bsRepo)
|
||||||
if err !=nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
repo := &model.Repo{
|
repo := &model.Repo{
|
||||||
|
21
router/middleware/session/team.go
Normal file
21
router/middleware/session/team.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MustTeamAdmin() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
user := User(c)
|
||||||
|
switch {
|
||||||
|
case user == nil:
|
||||||
|
c.String(401, "User not authorized")
|
||||||
|
c.Abort()
|
||||||
|
case user.Admin == false:
|
||||||
|
c.String(413, "User not authorized")
|
||||||
|
c.Abort()
|
||||||
|
default:
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,18 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
|||||||
users.DELETE("/:login", server.DeleteUser)
|
users.DELETE("/:login", server.DeleteUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
teams := e.Group("/api/teams")
|
||||||
|
{
|
||||||
|
user.Use(session.MustTeamAdmin())
|
||||||
|
|
||||||
|
team := teams.Group("/:team")
|
||||||
|
{
|
||||||
|
team.GET("/secrets", server.GetTeamSecrets)
|
||||||
|
team.POST("/secrets", server.PostTeamSecret)
|
||||||
|
team.DELETE("/secrets/:secret", server.DeleteTeamSecret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
repos := e.Group("/api/repos/:owner/:name")
|
repos := e.Group("/api/repos/:owner/:name")
|
||||||
{
|
{
|
||||||
repos.POST("", server.PostRepo)
|
repos.POST("", server.PostRepo)
|
||||||
|
@ -291,7 +291,7 @@ func PostBuild(c *gin.Context) {
|
|||||||
// get the previous build so that we can send
|
// get the previous build so that we can send
|
||||||
// on status change notifications
|
// on status change notifications
|
||||||
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
||||||
secs, err := store.GetSecretList(c, repo)
|
secs, err := store.GetMergedSecretList(c, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
log.Errorf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ func PostHook(c *gin.Context) {
|
|||||||
// get the previous build so that we can send
|
// get the previous build so that we can send
|
||||||
// on status change notifications
|
// on status change notifications
|
||||||
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
||||||
secs, err := store.GetSecretList(c, repo)
|
secs, err := store.GetMergedSecretList(c, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
log.Errorf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ func GetSecrets(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var list []*model.Secret
|
var list []*model.RepoSecret
|
||||||
|
|
||||||
for _, s := range secrets {
|
for _, s := range secrets {
|
||||||
list = append(list, s.Clone())
|
list = append(list, s.Clone())
|
||||||
@ -31,7 +31,7 @@ func GetSecrets(c *gin.Context) {
|
|||||||
func PostSecret(c *gin.Context) {
|
func PostSecret(c *gin.Context) {
|
||||||
repo := session.Repo(c)
|
repo := session.Repo(c)
|
||||||
|
|
||||||
in := &model.Secret{}
|
in := &model.RepoSecret{}
|
||||||
err := c.Bind(in)
|
err := c.Bind(in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusBadRequest, "Invalid JSON input. %s", err.Error())
|
c.String(http.StatusBadRequest, "Invalid JSON input. %s", err.Error())
|
67
server/team_secret.go
Normal file
67
server/team_secret.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/drone/drone/store"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTeamSecrets(c *gin.Context) {
|
||||||
|
team := c.Param("team")
|
||||||
|
secrets, err := store.GetTeamSecretList(c, team)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithStatus(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var list []*model.TeamSecret
|
||||||
|
|
||||||
|
for _, s := range secrets {
|
||||||
|
list = append(list, s.Clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostTeamSecret(c *gin.Context) {
|
||||||
|
team := c.Param("team")
|
||||||
|
|
||||||
|
in := &model.TeamSecret{}
|
||||||
|
err := c.Bind(in)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusBadRequest, "Invalid JSON input. %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
in.ID = 0
|
||||||
|
in.Key = team
|
||||||
|
|
||||||
|
err = store.SetTeamSecret(c, in)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, "Unable to persist team secret. %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.String(http.StatusOK, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteTeamSecret(c *gin.Context) {
|
||||||
|
team := c.Param("team")
|
||||||
|
name := c.Param("secret")
|
||||||
|
|
||||||
|
secret, err := store.GetTeamSecret(c, team, name)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusNotFound, "Cannot find secret %s.", name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = store.DeleteTeamSecret(c, secret)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, "Unable to delete team secret. %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.String(http.StatusOK, "")
|
||||||
|
}
|
19
store/datastore/ddl/mysql/7.sql
Normal file
19
store/datastore/ddl/mysql/7.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
CREATE TABLE team_secrets (
|
||||||
|
team_secret_id INTEGER PRIMARY KEY AUTO_INCREMENT
|
||||||
|
,team_secret_key VARCHAR(255)
|
||||||
|
,team_secret_name VARCHAR(255)
|
||||||
|
,team_secret_value MEDIUMBLOB
|
||||||
|
,team_secret_images VARCHAR(2000)
|
||||||
|
,team_secret_events VARCHAR(2000)
|
||||||
|
|
||||||
|
,UNIQUE(team_secret_name, team_secret_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX ix_team_secrets_key ON team_secrets (team_secret_key);
|
||||||
|
|
||||||
|
-- +migrate Down
|
||||||
|
|
||||||
|
DROP INDEX ix_team_secrets_key;
|
||||||
|
DROP TABLE team_secrets;
|
19
store/datastore/ddl/postgres/7.sql
Normal file
19
store/datastore/ddl/postgres/7.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
CREATE TABLE team_secrets (
|
||||||
|
team_secret_id SERIAL PRIMARY KEY
|
||||||
|
,team_secret_key VARCHAR(255)
|
||||||
|
,team_secret_name VARCHAR(255)
|
||||||
|
,team_secret_value BYTEA
|
||||||
|
,team_secret_images VARCHAR(2000)
|
||||||
|
,team_secret_events VARCHAR(2000)
|
||||||
|
|
||||||
|
,UNIQUE(team_secret_name, team_secret_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX ix_team_secrets_key ON team_secrets (team_secret_key);
|
||||||
|
|
||||||
|
-- +migrate Down
|
||||||
|
|
||||||
|
DROP INDEX ix_team_secrets_key;
|
||||||
|
DROP TABLE team_secrets;
|
19
store/datastore/ddl/sqlite3/7.sql
Normal file
19
store/datastore/ddl/sqlite3/7.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
CREATE TABLE team_secrets (
|
||||||
|
team_secret_id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
|
,team_secret_key TEXT
|
||||||
|
,team_secret_name TEXT
|
||||||
|
,team_secret_value TEXT
|
||||||
|
,team_secret_images TEXT
|
||||||
|
,team_secret_events TEXT
|
||||||
|
|
||||||
|
,UNIQUE(team_secret_name, team_secret_key)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX ix_team_secrets_key ON team_secrets (team_secret_key);
|
||||||
|
|
||||||
|
-- +migrate Down
|
||||||
|
|
||||||
|
DROP INDEX ix_team_secrets_key;
|
||||||
|
DROP TABLE team_secrets;
|
@ -5,20 +5,20 @@ import (
|
|||||||
"github.com/russross/meddler"
|
"github.com/russross/meddler"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (db *datastore) GetSecretList(repo *model.Repo) ([]*model.Secret, error) {
|
func (db *datastore) GetSecretList(repo *model.Repo) ([]*model.RepoSecret, error) {
|
||||||
var secrets = []*model.Secret{}
|
var secrets = []*model.RepoSecret{}
|
||||||
var err = meddler.QueryAll(db, &secrets, rebind(secretListQuery), repo.ID)
|
var err = meddler.QueryAll(db, &secrets, rebind(secretListQuery), repo.ID)
|
||||||
return secrets, err
|
return secrets, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *datastore) GetSecret(repo *model.Repo, name string) (*model.Secret, error) {
|
func (db *datastore) GetSecret(repo *model.Repo, name string) (*model.RepoSecret, error) {
|
||||||
var secret = new(model.Secret)
|
var secret = new(model.RepoSecret)
|
||||||
var err = meddler.QueryRow(db, secret, rebind(secretNameQuery), repo.ID, name)
|
var err = meddler.QueryRow(db, secret, rebind(secretNameQuery), repo.ID, name)
|
||||||
return secret, err
|
return secret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *datastore) SetSecret(sec *model.Secret) error {
|
func (db *datastore) SetSecret(sec *model.RepoSecret) error {
|
||||||
var got = new(model.Secret)
|
var got = new(model.RepoSecret)
|
||||||
var err = meddler.QueryRow(db, got, rebind(secretNameQuery), sec.RepoID, sec.Name)
|
var err = meddler.QueryRow(db, got, rebind(secretNameQuery), sec.RepoID, sec.Name)
|
||||||
if err == nil && got.ID != 0 {
|
if err == nil && got.ID != 0 {
|
||||||
sec.ID = got.ID // update existing id
|
sec.ID = got.ID // update existing id
|
||||||
@ -26,7 +26,7 @@ func (db *datastore) SetSecret(sec *model.Secret) error {
|
|||||||
return meddler.Save(db, secretTable, sec)
|
return meddler.Save(db, secretTable, sec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *datastore) DeleteSecret(sec *model.Secret) error {
|
func (db *datastore) DeleteSecret(sec *model.RepoSecret) error {
|
||||||
_, err := db.Exec(rebind(secretDeleteStmt), sec.ID)
|
_, err := db.Exec(rebind(secretDeleteStmt), sec.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
@ -7,13 +7,13 @@ import (
|
|||||||
"github.com/franela/goblin"
|
"github.com/franela/goblin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSecrets(t *testing.T) {
|
func TestRepoSecrets(t *testing.T) {
|
||||||
db := openTest()
|
db := openTest()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
s := From(db)
|
s := From(db)
|
||||||
g := goblin.Goblin(t)
|
g := goblin.Goblin(t)
|
||||||
g.Describe("Secrets", func() {
|
g.Describe("RepoSecrets", func() {
|
||||||
|
|
||||||
// before each test be sure to purge the package
|
// before each test be sure to purge the package
|
||||||
// table data from the database.
|
// table data from the database.
|
||||||
@ -22,7 +22,7 @@ func TestSecrets(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should set and get a secret", func() {
|
g.It("Should set and get a secret", func() {
|
||||||
secret := &model.Secret{
|
secret := &model.RepoSecret{
|
||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
@ -42,7 +42,7 @@ func TestSecrets(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should update a secret", func() {
|
g.It("Should update a secret", func() {
|
||||||
secret := &model.Secret{
|
secret := &model.RepoSecret{
|
||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
@ -58,12 +58,12 @@ func TestSecrets(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should list secrets", func() {
|
g.It("Should list secrets", func() {
|
||||||
s.SetSecret(&model.Secret{
|
s.SetSecret(&model.RepoSecret{
|
||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
||||||
})
|
})
|
||||||
s.SetSecret(&model.Secret{
|
s.SetSecret(&model.RepoSecret{
|
||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
Name: "bar",
|
Name: "bar",
|
||||||
Value: "baz",
|
Value: "baz",
|
||||||
@ -74,7 +74,7 @@ func TestSecrets(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should delete a secret", func() {
|
g.It("Should delete a secret", func() {
|
||||||
secret := &model.Secret{
|
secret := &model.RepoSecret{
|
||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Value: "bar",
|
Value: "bar",
|
53
store/datastore/team_secret.go
Normal file
53
store/datastore/team_secret.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package datastore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/russross/meddler"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (db *datastore) GetTeamSecretList(team string) ([]*model.TeamSecret, error) {
|
||||||
|
var secrets = []*model.TeamSecret{}
|
||||||
|
var err = meddler.QueryAll(db, &secrets, rebind(teamSecretListQuery), team)
|
||||||
|
return secrets, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) GetTeamSecret(team, name string) (*model.TeamSecret, error) {
|
||||||
|
var secret = new(model.TeamSecret)
|
||||||
|
var err = meddler.QueryRow(db, secret, rebind(teamSecretNameQuery), team, name)
|
||||||
|
return secret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) SetTeamSecret(sec *model.TeamSecret) error {
|
||||||
|
var got = new(model.TeamSecret)
|
||||||
|
var err = meddler.QueryRow(db, got, rebind(teamSecretNameQuery), sec.Key, sec.Name)
|
||||||
|
if err == nil && got.ID != 0 {
|
||||||
|
sec.ID = got.ID // update existing id
|
||||||
|
}
|
||||||
|
return meddler.Save(db, teamSecretTable, sec)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) DeleteTeamSecret(sec *model.TeamSecret) error {
|
||||||
|
_, err := db.Exec(rebind(teamSecretDeleteStmt), sec.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const teamSecretTable = "team_secrets"
|
||||||
|
|
||||||
|
const teamSecretListQuery = `
|
||||||
|
SELECT *
|
||||||
|
FROM team_secrets
|
||||||
|
WHERE team_secret_key = ?
|
||||||
|
`
|
||||||
|
|
||||||
|
const teamSecretNameQuery = `
|
||||||
|
SELECT *
|
||||||
|
FROM team_secrets
|
||||||
|
WHERE team_secret_key = ?
|
||||||
|
AND team_secret_name = ?
|
||||||
|
LIMIT 1;
|
||||||
|
`
|
||||||
|
|
||||||
|
const teamSecretDeleteStmt = `
|
||||||
|
DELETE FROM team_secrets
|
||||||
|
WHERE team_secret_id = ?
|
||||||
|
`
|
94
store/datastore/team_secret_test.go
Normal file
94
store/datastore/team_secret_test.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package datastore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/drone/drone/model"
|
||||||
|
"github.com/franela/goblin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTeamSecrets(t *testing.T) {
|
||||||
|
db := openTest()
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
s := From(db)
|
||||||
|
g := goblin.Goblin(t)
|
||||||
|
g.Describe("TeamSecrets", func() {
|
||||||
|
|
||||||
|
// before each test be sure to purge the package
|
||||||
|
// table data from the database.
|
||||||
|
g.BeforeEach(func() {
|
||||||
|
db.Exec(rebind("DELETE FROM team_secrets"))
|
||||||
|
})
|
||||||
|
|
||||||
|
g.It("Should set and get a secret", func() {
|
||||||
|
secret := &model.TeamSecret{
|
||||||
|
Key: "octocat",
|
||||||
|
Name: "foo",
|
||||||
|
Value: "bar",
|
||||||
|
Images: []string{"docker", "gcr"},
|
||||||
|
Events: []string{"push", "tag"},
|
||||||
|
}
|
||||||
|
err := s.SetTeamSecret(secret)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(secret.ID != 0).IsTrue()
|
||||||
|
|
||||||
|
got, err := s.GetTeamSecret("octocat", secret.Name)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(got.Name).Equal(secret.Name)
|
||||||
|
g.Assert(got.Value).Equal(secret.Value)
|
||||||
|
g.Assert(got.Images).Equal(secret.Images)
|
||||||
|
g.Assert(got.Events).Equal(secret.Events)
|
||||||
|
})
|
||||||
|
|
||||||
|
g.It("Should update a secret", func() {
|
||||||
|
secret := &model.TeamSecret{
|
||||||
|
Key: "octocat",
|
||||||
|
Name: "foo",
|
||||||
|
Value: "bar",
|
||||||
|
}
|
||||||
|
s.SetTeamSecret(secret)
|
||||||
|
secret.Value = "baz"
|
||||||
|
s.SetTeamSecret(secret)
|
||||||
|
|
||||||
|
got, err := s.GetTeamSecret("octocat", secret.Name)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(got.Name).Equal(secret.Name)
|
||||||
|
g.Assert(got.Value).Equal(secret.Value)
|
||||||
|
})
|
||||||
|
|
||||||
|
g.It("Should list secrets", func() {
|
||||||
|
s.SetTeamSecret(&model.TeamSecret{
|
||||||
|
Key: "octocat",
|
||||||
|
Name: "foo",
|
||||||
|
Value: "bar",
|
||||||
|
})
|
||||||
|
s.SetTeamSecret(&model.TeamSecret{
|
||||||
|
Key: "octocat",
|
||||||
|
Name: "bar",
|
||||||
|
Value: "baz",
|
||||||
|
})
|
||||||
|
secrets, err := s.GetTeamSecretList("octocat")
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(len(secrets)).Equal(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
g.It("Should delete a secret", func() {
|
||||||
|
secret := &model.TeamSecret{
|
||||||
|
Key: "octocat",
|
||||||
|
Name: "foo",
|
||||||
|
Value: "bar",
|
||||||
|
}
|
||||||
|
s.SetTeamSecret(secret)
|
||||||
|
|
||||||
|
_, err := s.GetTeamSecret("octocat", secret.Name)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
|
||||||
|
err = s.DeleteTeamSecret(secret)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
|
||||||
|
_, err = s.GetTeamSecret("octocat", secret.Name)
|
||||||
|
g.Assert(err != nil).IsTrue("expect a no rows in result set error")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
@ -59,16 +59,28 @@ type Store interface {
|
|||||||
DeleteRepo(*model.Repo) error
|
DeleteRepo(*model.Repo) error
|
||||||
|
|
||||||
// GetSecretList gets a list of repository secrets
|
// GetSecretList gets a list of repository secrets
|
||||||
GetSecretList(*model.Repo) ([]*model.Secret, error)
|
GetSecretList(*model.Repo) ([]*model.RepoSecret, error)
|
||||||
|
|
||||||
// GetSecret gets the named repository secret.
|
// GetSecret gets the named repository secret.
|
||||||
GetSecret(*model.Repo, string) (*model.Secret, error)
|
GetSecret(*model.Repo, string) (*model.RepoSecret, error)
|
||||||
|
|
||||||
// SetSecret sets the named repository secret.
|
// SetSecret sets the named repository secret.
|
||||||
SetSecret(*model.Secret) error
|
SetSecret(*model.RepoSecret) error
|
||||||
|
|
||||||
// DeleteSecret deletes the named repository secret.
|
// DeleteSecret deletes the named repository secret.
|
||||||
DeleteSecret(*model.Secret) error
|
DeleteSecret(*model.RepoSecret) error
|
||||||
|
|
||||||
|
// GetTeamSecretList gets a list of team secrets
|
||||||
|
GetTeamSecretList(string) ([]*model.TeamSecret, error)
|
||||||
|
|
||||||
|
// GetTeamSecret gets the named team secret.
|
||||||
|
GetTeamSecret(string, string) (*model.TeamSecret, error)
|
||||||
|
|
||||||
|
// SetTeamSecret sets the named team secret.
|
||||||
|
SetTeamSecret(*model.TeamSecret) error
|
||||||
|
|
||||||
|
// DeleteTeamSecret deletes the named team secret.
|
||||||
|
DeleteTeamSecret(*model.TeamSecret) error
|
||||||
|
|
||||||
// GetBuild gets a build by unique ID.
|
// GetBuild gets a build by unique ID.
|
||||||
GetBuild(int64) (*model.Build, error)
|
GetBuild(int64) (*model.Build, error)
|
||||||
@ -202,22 +214,66 @@ func DeleteRepo(c context.Context, repo *model.Repo) error {
|
|||||||
return FromContext(c).DeleteRepo(repo)
|
return FromContext(c).DeleteRepo(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSecretList(c context.Context, r *model.Repo) ([]*model.Secret, error) {
|
func GetSecretList(c context.Context, r *model.Repo) ([]*model.RepoSecret, error) {
|
||||||
return FromContext(c).GetSecretList(r)
|
return FromContext(c).GetSecretList(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSecret(c context.Context, r *model.Repo, name string) (*model.Secret, error) {
|
func GetSecret(c context.Context, r *model.Repo, name string) (*model.RepoSecret, error) {
|
||||||
return FromContext(c).GetSecret(r, name)
|
return FromContext(c).GetSecret(r, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetSecret(c context.Context, s *model.Secret) error {
|
func SetSecret(c context.Context, s *model.RepoSecret) error {
|
||||||
return FromContext(c).SetSecret(s)
|
return FromContext(c).SetSecret(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteSecret(c context.Context, s *model.Secret) error {
|
func DeleteSecret(c context.Context, s *model.RepoSecret) error {
|
||||||
return FromContext(c).DeleteSecret(s)
|
return FromContext(c).DeleteSecret(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetTeamSecretList(c context.Context, team string) ([]*model.TeamSecret, error) {
|
||||||
|
return FromContext(c).GetTeamSecretList(team)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTeamSecret(c context.Context, team, name string) (*model.TeamSecret, error) {
|
||||||
|
return FromContext(c).GetTeamSecret(team, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetTeamSecret(c context.Context, s *model.TeamSecret) error {
|
||||||
|
return FromContext(c).SetTeamSecret(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteTeamSecret(c context.Context, s *model.TeamSecret) error {
|
||||||
|
return FromContext(c).DeleteTeamSecret(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMergedSecretList(c context.Context, r *model.Repo) ([]*model.Secret, error) {
|
||||||
|
var (
|
||||||
|
secrets []*model.Secret
|
||||||
|
)
|
||||||
|
|
||||||
|
repoSecs, err := FromContext(c).GetSecretList(r)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, secret := range repoSecs {
|
||||||
|
secrets = append(secrets, secret.Secret())
|
||||||
|
}
|
||||||
|
|
||||||
|
teamSecs, err := FromContext(c).GetTeamSecretList(r.Owner)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, secret := range teamSecs {
|
||||||
|
secrets = append(secrets, secret.Secret())
|
||||||
|
}
|
||||||
|
|
||||||
|
return secrets, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetBuild(c context.Context, id int64) (*model.Build, error) {
|
func GetBuild(c context.Context, id int64) (*model.Build, error) {
|
||||||
return FromContext(c).GetBuild(id)
|
return FromContext(c).GetBuild(id)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user