You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02:00 
			
		
		
		
	bump to 0.5 in master
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -12,7 +12,7 @@ drone/drone | ||||
| .env | ||||
| temp/ | ||||
|  | ||||
| api/swagger/files/* | ||||
| server/swagger/files/*.json | ||||
|  | ||||
| # vendored repositories that we don't actually need | ||||
| # to vendor. so exclude them | ||||
|   | ||||
| @@ -21,4 +21,4 @@ ADD drone/drone /drone | ||||
| #RUN echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf | ||||
|  | ||||
| ENTRYPOINT ["/drone"] | ||||
| CMD ["serve"] | ||||
| CMD ["daemon"] | ||||
|   | ||||
| @@ -1,3 +0,0 @@ | ||||
| package swagger | ||||
|  | ||||
| //go:generate go-bindata -pkg swagger -o swagger_gen.go files/ | ||||
							
								
								
									
										315
									
								
								drone/daemon.go
									
									
									
									
									
								
							
							
						
						
									
										315
									
								
								drone/daemon.go
									
									
									
									
									
								
							| @@ -6,20 +6,9 @@ import ( | ||||
| 	"os" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/drone/drone/bus" | ||||
| 	"github.com/drone/drone/cache" | ||||
| 	"github.com/drone/drone/queue" | ||||
| 	"github.com/drone/drone/remote" | ||||
| 	"github.com/drone/drone/remote/bitbucket" | ||||
| 	"github.com/drone/drone/remote/bitbucketserver" | ||||
| 	"github.com/drone/drone/remote/github" | ||||
| 	"github.com/drone/drone/remote/gitlab" | ||||
| 	"github.com/drone/drone/remote/gogs" | ||||
| 	"github.com/drone/drone/server" | ||||
| 	"github.com/drone/drone/shared/token" | ||||
| 	"github.com/drone/drone/store" | ||||
| 	"github.com/drone/drone/store/datastore" | ||||
| 	"github.com/drone/drone/stream" | ||||
| 	"github.com/drone/drone/router" | ||||
| 	"github.com/drone/drone/router/middleware" | ||||
| 	"github.com/gin-gonic/contrib/ginrus" | ||||
|  | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/codegangsta/cli" | ||||
| @@ -300,22 +289,19 @@ func start(c *cli.Context) error { | ||||
| 		logrus.SetLevel(logrus.WarnLevel) | ||||
| 	} | ||||
|  | ||||
| 	// print the agent secret to the console | ||||
| 	// TODO(bradrydzewski) this overall approach should be re-considered | ||||
| 	if err := printSecret(c); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// setup the server and start the listener | ||||
| 	server := server.Server{ | ||||
| 		Bus:    setupBus(c), | ||||
| 		Cache:  setupCache(c), | ||||
| 		Config: setupConfig(c), | ||||
| 		Queue:  setupQueue(c), | ||||
| 		Remote: setupRemote(c), | ||||
| 		Stream: setupStream(c), | ||||
| 		Store:  setupStore(c), | ||||
| 	} | ||||
| 	handler := router.Load( | ||||
| 		ginrus.Ginrus(logrus.StandardLogger(), time.RFC3339, true), | ||||
| 		middleware.Version, | ||||
| 		middleware.Config(c), | ||||
| 		middleware.Queue(c), | ||||
| 		middleware.Stream(c), | ||||
| 		middleware.Bus(c), | ||||
| 		middleware.Cache(c), | ||||
| 		middleware.Store(c), | ||||
| 		middleware.Remote(c), | ||||
| 		middleware.Agents(c), | ||||
| 	) | ||||
|  | ||||
| 	// start the server with tls enabled | ||||
| 	if c.String("server-cert") != "" { | ||||
| @@ -323,150 +309,151 @@ func start(c *cli.Context) error { | ||||
| 			c.String("server-addr"), | ||||
| 			c.String("server-cert"), | ||||
| 			c.String("server-key"), | ||||
| 			server.Handler(), | ||||
| 			handler, | ||||
| 		) | ||||
| 	} | ||||
|  | ||||
| 	// start the server without tls enabled | ||||
| 	return http.ListenAndServe( | ||||
| 		c.String("server-addr"), | ||||
| 		server.Handler(), | ||||
| 		handler, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func setupCache(c *cli.Context) cache.Cache { | ||||
| 	return cache.NewTTL( | ||||
| 		c.Duration("cache-ttl"), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func setupBus(c *cli.Context) bus.Bus { | ||||
| 	return bus.New() | ||||
| } | ||||
|  | ||||
| func setupQueue(c *cli.Context) queue.Queue { | ||||
| 	return queue.New() | ||||
| } | ||||
|  | ||||
| func setupStream(c *cli.Context) stream.Stream { | ||||
| 	return stream.New() | ||||
| } | ||||
|  | ||||
| func setupStore(c *cli.Context) store.Store { | ||||
| 	return datastore.New( | ||||
| 		c.String("driver"), | ||||
| 		c.String("datasource"), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func setupRemote(c *cli.Context) remote.Remote { | ||||
| 	var remote remote.Remote | ||||
| 	var err error | ||||
| 	switch { | ||||
| 	case c.Bool("github"): | ||||
| 		remote, err = setupGithub(c) | ||||
| 	case c.Bool("gitlab"): | ||||
| 		remote, err = setupGitlab(c) | ||||
| 	case c.Bool("bitbucket"): | ||||
| 		remote, err = setupBitbucket(c) | ||||
| 	case c.Bool("stash"): | ||||
| 		remote, err = setupStash(c) | ||||
| 	case c.Bool("gogs"): | ||||
| 		remote, err = setupGogs(c) | ||||
| 	default: | ||||
| 		err = fmt.Errorf("version control system not configured") | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		logrus.Fatalln(err) | ||||
| 	} | ||||
| 	return remote | ||||
| } | ||||
|  | ||||
| func setupBitbucket(c *cli.Context) (remote.Remote, error) { | ||||
| 	return bitbucket.New( | ||||
| 		c.String("bitbucket-client"), | ||||
| 		c.String("bitbucket-server"), | ||||
| 	), nil | ||||
| } | ||||
|  | ||||
| func setupGogs(c *cli.Context) (remote.Remote, error) { | ||||
| 	return gogs.New(gogs.Opts{ | ||||
| 		URL:         c.String("gogs-server"), | ||||
| 		Username:    c.String("gogs-git-username"), | ||||
| 		Password:    c.String("gogs-git-password"), | ||||
| 		PrivateMode: c.Bool("gogs-private-mode"), | ||||
| 		SkipVerify:  c.Bool("gogs-skip-verify"), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func setupStash(c *cli.Context) (remote.Remote, error) { | ||||
| 	return bitbucketserver.New(bitbucketserver.Opts{ | ||||
| 		URL:         c.String("stash-server"), | ||||
| 		Username:    c.String("stash-git-username"), | ||||
| 		Password:    c.String("stash-git-password"), | ||||
| 		ConsumerKey: c.String("stash-consumer-key"), | ||||
| 		ConsumerRSA: c.String("stash-consumer-rsa"), | ||||
| 		SkipVerify:  c.Bool("stash-skip-verify"), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func setupGitlab(c *cli.Context) (remote.Remote, error) { | ||||
| 	return gitlab.New(gitlab.Opts{ | ||||
| 		URL:         c.String("gitlab-server"), | ||||
| 		Client:      c.String("gitlab-client"), | ||||
| 		Secret:      c.String("gitlab-sercret"), | ||||
| 		Username:    c.String("gitlab-git-username"), | ||||
| 		Password:    c.String("gitlab-git-password"), | ||||
| 		PrivateMode: c.Bool("gitlab-private-mode"), | ||||
| 		SkipVerify:  c.Bool("gitlab-skip-verify"), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func setupGithub(c *cli.Context) (remote.Remote, error) { | ||||
| 	return github.New( | ||||
| 		c.String("github-server"), | ||||
| 		c.String("github-client"), | ||||
| 		c.String("github-sercret"), | ||||
| 		c.StringSlice("github-scope"), | ||||
| 		c.Bool("github-private-mode"), | ||||
| 		c.Bool("github-skip-verify"), | ||||
| 		c.BoolT("github-merge-ref"), | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func setupConfig(c *cli.Context) *server.Config { | ||||
| 	return &server.Config{ | ||||
| 		Open:   c.Bool("open"), | ||||
| 		Yaml:   c.String("yaml"), | ||||
| 		Secret: c.String("agent-secret"), | ||||
| 		Admins: sliceToMap(c.StringSlice("admin")), | ||||
| 		Orgs:   sliceToMap(c.StringSlice("orgs")), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func sliceToMap(s []string) map[string]bool { | ||||
| 	v := map[string]bool{} | ||||
| 	for _, ss := range s { | ||||
| 		v[ss] = true | ||||
| 	} | ||||
| 	return v | ||||
| } | ||||
|  | ||||
| func printSecret(c *cli.Context) error { | ||||
| 	secret := c.String("agent-secret") | ||||
| 	if secret == "" { | ||||
| 		return fmt.Errorf("missing DRONE_AGENT_SECRET configuration parameter") | ||||
| 	} | ||||
| 	t := token.New(secret, "") | ||||
| 	s, err := t.Sign(secret) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("invalid value for DRONE_AGENT_SECRET. %s", s) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Infof("using agent secret %s", secret) | ||||
| 	logrus.Warnf("agents can connect with token %s", s) | ||||
| 	return nil | ||||
| } | ||||
| // | ||||
| // func setupCache(c *cli.Context) cache.Cache { | ||||
| // 	return cache.NewTTL( | ||||
| // 		c.Duration("cache-ttl"), | ||||
| // 	) | ||||
| // } | ||||
| // | ||||
| // func setupBus(c *cli.Context) bus.Bus { | ||||
| // 	return bus.New() | ||||
| // } | ||||
| // | ||||
| // func setupQueue(c *cli.Context) queue.Queue { | ||||
| // 	return queue.New() | ||||
| // } | ||||
| // | ||||
| // func setupStream(c *cli.Context) stream.Stream { | ||||
| // 	return stream.New() | ||||
| // } | ||||
| // | ||||
| // func setupStore(c *cli.Context) store.Store { | ||||
| // 	return datastore.New( | ||||
| // 		c.String("driver"), | ||||
| // 		c.String("datasource"), | ||||
| // 	) | ||||
| // } | ||||
| // | ||||
| // func setupRemote(c *cli.Context) remote.Remote { | ||||
| // 	var remote remote.Remote | ||||
| // 	var err error | ||||
| // 	switch { | ||||
| // 	case c.Bool("github"): | ||||
| // 		remote, err = setupGithub(c) | ||||
| // 	case c.Bool("gitlab"): | ||||
| // 		remote, err = setupGitlab(c) | ||||
| // 	case c.Bool("bitbucket"): | ||||
| // 		remote, err = setupBitbucket(c) | ||||
| // 	case c.Bool("stash"): | ||||
| // 		remote, err = setupStash(c) | ||||
| // 	case c.Bool("gogs"): | ||||
| // 		remote, err = setupGogs(c) | ||||
| // 	default: | ||||
| // 		err = fmt.Errorf("version control system not configured") | ||||
| // 	} | ||||
| // 	if err != nil { | ||||
| // 		logrus.Fatalln(err) | ||||
| // 	} | ||||
| // 	return remote | ||||
| // } | ||||
| // | ||||
| // func setupBitbucket(c *cli.Context) (remote.Remote, error) { | ||||
| // 	return bitbucket.New( | ||||
| // 		c.String("bitbucket-client"), | ||||
| // 		c.String("bitbucket-server"), | ||||
| // 	), nil | ||||
| // } | ||||
| // | ||||
| // func setupGogs(c *cli.Context) (remote.Remote, error) { | ||||
| // 	return gogs.New(gogs.Opts{ | ||||
| // 		URL:         c.String("gogs-server"), | ||||
| // 		Username:    c.String("gogs-git-username"), | ||||
| // 		Password:    c.String("gogs-git-password"), | ||||
| // 		PrivateMode: c.Bool("gogs-private-mode"), | ||||
| // 		SkipVerify:  c.Bool("gogs-skip-verify"), | ||||
| // 	}) | ||||
| // } | ||||
| // | ||||
| // func setupStash(c *cli.Context) (remote.Remote, error) { | ||||
| // 	return bitbucketserver.New(bitbucketserver.Opts{ | ||||
| // 		URL:         c.String("stash-server"), | ||||
| // 		Username:    c.String("stash-git-username"), | ||||
| // 		Password:    c.String("stash-git-password"), | ||||
| // 		ConsumerKey: c.String("stash-consumer-key"), | ||||
| // 		ConsumerRSA: c.String("stash-consumer-rsa"), | ||||
| // 		SkipVerify:  c.Bool("stash-skip-verify"), | ||||
| // 	}) | ||||
| // } | ||||
| // | ||||
| // func setupGitlab(c *cli.Context) (remote.Remote, error) { | ||||
| // 	return gitlab.New(gitlab.Opts{ | ||||
| // 		URL:         c.String("gitlab-server"), | ||||
| // 		Client:      c.String("gitlab-client"), | ||||
| // 		Secret:      c.String("gitlab-sercret"), | ||||
| // 		Username:    c.String("gitlab-git-username"), | ||||
| // 		Password:    c.String("gitlab-git-password"), | ||||
| // 		PrivateMode: c.Bool("gitlab-private-mode"), | ||||
| // 		SkipVerify:  c.Bool("gitlab-skip-verify"), | ||||
| // 	}) | ||||
| // } | ||||
| // | ||||
| // func setupGithub(c *cli.Context) (remote.Remote, error) { | ||||
| // 	return github.New( | ||||
| // 		c.String("github-server"), | ||||
| // 		c.String("github-client"), | ||||
| // 		c.String("github-sercret"), | ||||
| // 		c.StringSlice("github-scope"), | ||||
| // 		c.Bool("github-private-mode"), | ||||
| // 		c.Bool("github-skip-verify"), | ||||
| // 		c.BoolT("github-merge-ref"), | ||||
| // 	) | ||||
| // } | ||||
| // | ||||
| // func setupConfig(c *cli.Context) *server.Config { | ||||
| // 	return &server.Config{ | ||||
| // 		Open:   c.Bool("open"), | ||||
| // 		Yaml:   c.String("yaml"), | ||||
| // 		Secret: c.String("agent-secret"), | ||||
| // 		Admins: sliceToMap(c.StringSlice("admin")), | ||||
| // 		Orgs:   sliceToMap(c.StringSlice("orgs")), | ||||
| // 	} | ||||
| // } | ||||
| // | ||||
| // func sliceToMap(s []string) map[string]bool { | ||||
| // 	v := map[string]bool{} | ||||
| // 	for _, ss := range s { | ||||
| // 		v[ss] = true | ||||
| // 	} | ||||
| // 	return v | ||||
| // } | ||||
| // | ||||
| // func printSecret(c *cli.Context) error { | ||||
| // 	secret := c.String("agent-secret") | ||||
| // 	if secret == "" { | ||||
| // 		return fmt.Errorf("missing DRONE_AGENT_SECRET configuration parameter") | ||||
| // 	} | ||||
| // 	t := token.New(secret, "") | ||||
| // 	s, err := t.Sign(secret) | ||||
| // 	if err != nil { | ||||
| // 		return fmt.Errorf("invalid value for DRONE_AGENT_SECRET. %s", s) | ||||
| // 	} | ||||
| // | ||||
| // 	logrus.Infof("using agent secret %s", secret) | ||||
| // 	logrus.Warnf("agents can connect with token %s", s) | ||||
| // 	return nil | ||||
| // } | ||||
|  | ||||
| var agreement = ` | ||||
| --- | ||||
|   | ||||
							
								
								
									
										26
									
								
								model/config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								model/config.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| package model | ||||
|  | ||||
| // Config defines system configuration parameters. | ||||
| type Config struct { | ||||
| 	Open   bool            // Enables open registration | ||||
| 	Yaml   string          // Customize the Yaml configuration file name | ||||
| 	Shasum string          // Customize the Yaml checksum file name | ||||
| 	Secret string          // Secret token used to authenticate agents | ||||
| 	Admins map[string]bool // Administrative users | ||||
| 	Orgs   map[string]bool // Organization whitelist | ||||
| } | ||||
|  | ||||
| // IsAdmin returns true if the user is a member of the administrator list. | ||||
| func (c *Config) IsAdmin(user *User) bool { | ||||
| 	return c.Admins[user.Login] | ||||
| } | ||||
|  | ||||
| // IsMember returns true if the user is a member of the whitelisted teams. | ||||
| func (c *Config) IsMember(teams []*Team) bool { | ||||
| 	for _, team := range teams { | ||||
| 		if c.Orgs[team.Login] { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| @@ -32,11 +32,17 @@ type User struct { | ||||
| 	Avatar string `json:"avatar_url" meddler:"user_avatar"` | ||||
|  | ||||
| 	// Activate indicates the user is active in the system. | ||||
| 	Active bool `json:"active," meddler:"user_active"` | ||||
| 	Active bool `json:"active" meddler:"user_active"` | ||||
|  | ||||
| 	// Admin indicates the user is a system administrator. | ||||
| 	Admin bool `json:"admin," meddler:"user_admin"` | ||||
| 	// | ||||
| 	// NOTE: This is sourced from the DRONE_ADMINS environment variable and is no | ||||
| 	// longer persisted in the database. | ||||
| 	Admin bool `json:"admin,omitempty" meddler:"-"` | ||||
|  | ||||
| 	// Hash is a unique token used to sign tokens. | ||||
| 	Hash string `json:"-" meddler:"user_hash"` | ||||
|  | ||||
| 	// DEPRECATED Admin indicates the user is a system administrator. | ||||
| 	XAdmin bool `json:"-" meddler:"user_admin"` | ||||
| } | ||||
|   | ||||
| @@ -1,85 +0,0 @@ | ||||
| package remote | ||||
|  | ||||
| import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/drone/drone/model" | ||||
| ) | ||||
|  | ||||
| // WithCache returns a the parent Remote with a front-end Cache. Remote items | ||||
| // are cached for duration d. | ||||
| func WithCache(r Remote, d time.Duration) Remote { | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Cacher implements purge functionality so that we can evict stale data and | ||||
| // force a refresh. The indended use case is when the repository list is out | ||||
| // of date and requires manual refresh. | ||||
| type Cacher interface { | ||||
| 	Purge(*model.User) | ||||
| } | ||||
|  | ||||
| // Because the cache is so closely tied to the remote we should just include | ||||
| // them in the same package together. The below code are stubs for merging | ||||
| // the Cache with the Remote package. | ||||
|  | ||||
| type cache struct { | ||||
| 	Remote | ||||
| } | ||||
|  | ||||
| func (c *cache) Repos(u *model.User) ([]*model.RepoLite, error) { | ||||
| 	// key := fmt.Sprintf("repos:%s", | ||||
| 	// 	user.Login, | ||||
| 	// ) | ||||
| 	// // if we fetch from the cache we can return immediately | ||||
| 	// val, err := Get(c, key) | ||||
| 	// if err == nil { | ||||
| 	// 	return val.([]*model.RepoLite), nil | ||||
| 	// } | ||||
| 	// // else we try to grab from the remote system and | ||||
| 	// // populate our cache. | ||||
| 	// repos, err := remote.Repos(c, user) | ||||
| 	// if err != nil { | ||||
| 	// 	return nil, err | ||||
| 	// } | ||||
| 	// | ||||
| 	// Set(c, key, repos) | ||||
| 	// return repos, nil | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (c *cache) Perm(u *model.User, owner, repo string) (*model.Perm, error) { | ||||
| 	// key := fmt.Sprintf("perms:%s:%s/%s", | ||||
| 	// 	user.Login, | ||||
| 	// 	owner, | ||||
| 	// 	name, | ||||
| 	// ) | ||||
| 	// // if we fetch from the cache we can return immediately | ||||
| 	// val, err := Get(c, key) | ||||
| 	// if err == nil { | ||||
| 	// 	return val.(*model.Perm), nil | ||||
| 	// } | ||||
| 	// // else we try to grab from the remote system and | ||||
| 	// // populate our cache. | ||||
| 	// perm, err := remote.Perm(c, user, owner, name) | ||||
| 	// if err != nil { | ||||
| 	// 	return nil, err | ||||
| 	// } | ||||
| 	// Set(c, key, perm) | ||||
| 	// return perm, nil | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (c *cache) Purge(*model.User) { | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *cache) Refresh(u *model.User) (bool, error) { | ||||
| 	if r, ok := c.Remote.(Refresher); ok { | ||||
| 		return r.Refresh(u) | ||||
| 	} | ||||
| 	return false, nil | ||||
| } | ||||
|  | ||||
| var _ Remote = &cache{} | ||||
| var _ Refresher = &cache{} | ||||
| @@ -1,45 +1,33 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/shared/token" | ||||
|  | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/ianschenck/envflag" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	secret = envflag.String("DRONE_AGENT_SECRET", "", "") | ||||
| 	noauth = envflag.Bool("AGENT_NO_AUTH", false, "") | ||||
| ) | ||||
| const agentKey = "agent" | ||||
|  | ||||
| // Agent is a middleware function that initializes the authorization middleware | ||||
| // Agents is a middleware function that initializes the authorization middleware | ||||
| // for agents to connect to the queue. | ||||
| func AgentMust() gin.HandlerFunc { | ||||
|  | ||||
| 	if *secret == "" { | ||||
| 		logrus.Fatalf("please provide the agent secret to authenticate agent requests") | ||||
| func Agents(cli *cli.Context) gin.HandlerFunc { | ||||
| 	secret := cli.String("agent-secret") | ||||
| 	if secret == "" { | ||||
| 		logrus.Fatalf("failed to generate token from DRONE_AGENT_SECRET") | ||||
| 	} | ||||
|  | ||||
| 	t := token.New(token.AgentToken, "") | ||||
| 	s, err := t.Sign(*secret) | ||||
| 	t := token.New(secret, "") | ||||
| 	s, err := t.Sign(secret) | ||||
| 	if err != nil { | ||||
| 		logrus.Fatalf("invalid agent secret. %s", err) | ||||
| 		logrus.Fatalf("failed to generate token from DRONE_AGENT_SECRET. %s", err) | ||||
| 	} | ||||
|  | ||||
| 	logrus.Infof("using agent secret %s", *secret) | ||||
| 	logrus.Infof("using agent secret %s", secret) | ||||
| 	logrus.Warnf("agents can connect with token %s", s) | ||||
|  | ||||
| 	return func(c *gin.Context) { | ||||
| 		parsed, err := token.ParseRequest(c.Request, func(t *token.Token) (string, error) { | ||||
| 			return *secret, nil | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			c.AbortWithError(403, err) | ||||
| 		} else if parsed.Kind != token.AgentToken { | ||||
| 			c.AbortWithStatus(403) | ||||
| 		} else { | ||||
| 			c.Next() | ||||
| 		} | ||||
| 		c.Set(agentKey, secret) | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										17
									
								
								router/middleware/bus.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								router/middleware/bus.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/bus" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Bus is a middleware function that initializes the Event Bus and attaches to | ||||
| // the context of every http.Request. | ||||
| func Bus(cli *cli.Context) gin.HandlerFunc { | ||||
| 	v := bus.New() | ||||
| 	return func(c *gin.Context) { | ||||
| 		bus.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										24
									
								
								router/middleware/cache.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								router/middleware/cache.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/cache" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Cache is a middleware function that initializes the Cache and attaches to | ||||
| // the context of every http.Request. | ||||
| func Cache(cli *cli.Context) gin.HandlerFunc { | ||||
| 	v := setupCache(cli) | ||||
| 	return func(c *gin.Context) { | ||||
| 		cache.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // helper function to create the cache from the CLI context. | ||||
| func setupCache(c *cli.Context) cache.Cache { | ||||
| 	return cache.NewTTL( | ||||
| 		c.Duration("cache-ttl"), | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										40
									
								
								router/middleware/config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								router/middleware/config.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/model" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| const configKey = "config" | ||||
|  | ||||
| // Config is a middleware function that initializes the Configuration and | ||||
| // attaches to the context of every http.Request. | ||||
| func Config(cli *cli.Context) gin.HandlerFunc { | ||||
| 	v := setupConfig(cli) | ||||
| 	return func(c *gin.Context) { | ||||
| 		c.Set(configKey, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // helper function to create the configuration from the CLI context. | ||||
| func setupConfig(c *cli.Context) *model.Config { | ||||
| 	return &model.Config{ | ||||
| 		Open:   c.Bool("open"), | ||||
| 		Yaml:   c.String("yaml"), | ||||
| 		Shasum: c.String("yaml") + ".sig", | ||||
| 		Secret: c.String("agent-secret"), | ||||
| 		Admins: sliceToMap(c.StringSlice("admin")), | ||||
| 		Orgs:   sliceToMap(c.StringSlice("orgs")), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // helper function to convert a string slice to a map. | ||||
| func sliceToMap(s []string) map[string]bool { | ||||
| 	v := map[string]bool{} | ||||
| 	for _, ss := range s { | ||||
| 		v[ss] = true | ||||
| 	} | ||||
| 	return v | ||||
| } | ||||
							
								
								
									
										17
									
								
								router/middleware/queue.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								router/middleware/queue.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/queue" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Queue is a middleware function that initializes the Queue and attaches to | ||||
| // the context of every http.Request. | ||||
| func Queue(cli *cli.Context) gin.HandlerFunc { | ||||
| 	v := queue.New() | ||||
| 	return func(c *gin.Context) { | ||||
| 		queue.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										102
									
								
								router/middleware/remote.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								router/middleware/remote.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/remote" | ||||
| 	"github.com/drone/drone/remote/bitbucket" | ||||
| 	"github.com/drone/drone/remote/bitbucketserver" | ||||
| 	"github.com/drone/drone/remote/github" | ||||
| 	"github.com/drone/drone/remote/gitlab" | ||||
| 	"github.com/drone/drone/remote/gogs" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Remote is a middleware function that initializes the Remote and attaches to | ||||
| // the context of every http.Request. | ||||
| func Remote(c *cli.Context) gin.HandlerFunc { | ||||
| 	v, err := setupRemote(c) | ||||
| 	if err != nil { | ||||
| 		logrus.Fatalln(err) | ||||
| 	} | ||||
| 	return func(c *gin.Context) { | ||||
| 		remote.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // helper function to setup the remote from the CLI arguments. | ||||
| func setupRemote(c *cli.Context) (remote.Remote, error) { | ||||
| 	switch { | ||||
| 	case c.Bool("github"): | ||||
| 		return setupGithub(c) | ||||
| 	case c.Bool("gitlab"): | ||||
| 		return setupGitlab(c) | ||||
| 	case c.Bool("bitbucket"): | ||||
| 		return setupBitbucket(c) | ||||
| 	case c.Bool("stash"): | ||||
| 		return setupStash(c) | ||||
| 	case c.Bool("gogs"): | ||||
| 		return setupGogs(c) | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("version control system not configured") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // helper function to setup the Bitbucket remote from the CLI arguments. | ||||
| func setupBitbucket(c *cli.Context) (remote.Remote, error) { | ||||
| 	return bitbucket.New( | ||||
| 		c.String("bitbucket-client"), | ||||
| 		c.String("bitbucket-server"), | ||||
| 	), nil | ||||
| } | ||||
|  | ||||
| // helper function to setup the Gogs remote from the CLI arguments. | ||||
| func setupGogs(c *cli.Context) (remote.Remote, error) { | ||||
| 	return gogs.New(gogs.Opts{ | ||||
| 		URL:         c.String("gogs-server"), | ||||
| 		Username:    c.String("gogs-git-username"), | ||||
| 		Password:    c.String("gogs-git-password"), | ||||
| 		PrivateMode: c.Bool("gogs-private-mode"), | ||||
| 		SkipVerify:  c.Bool("gogs-skip-verify"), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // helper function to setup the Stash remote from the CLI arguments. | ||||
| func setupStash(c *cli.Context) (remote.Remote, error) { | ||||
| 	return bitbucketserver.New(bitbucketserver.Opts{ | ||||
| 		URL:         c.String("stash-server"), | ||||
| 		Username:    c.String("stash-git-username"), | ||||
| 		Password:    c.String("stash-git-password"), | ||||
| 		ConsumerKey: c.String("stash-consumer-key"), | ||||
| 		ConsumerRSA: c.String("stash-consumer-rsa"), | ||||
| 		SkipVerify:  c.Bool("stash-skip-verify"), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // helper function to setup the Gitlab remote from the CLI arguments. | ||||
| func setupGitlab(c *cli.Context) (remote.Remote, error) { | ||||
| 	return gitlab.New(gitlab.Opts{ | ||||
| 		URL:         c.String("gitlab-server"), | ||||
| 		Client:      c.String("gitlab-client"), | ||||
| 		Secret:      c.String("gitlab-sercret"), | ||||
| 		Username:    c.String("gitlab-git-username"), | ||||
| 		Password:    c.String("gitlab-git-password"), | ||||
| 		PrivateMode: c.Bool("gitlab-private-mode"), | ||||
| 		SkipVerify:  c.Bool("gitlab-skip-verify"), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // helper function to setup the GitHub remote from the CLI arguments. | ||||
| func setupGithub(c *cli.Context) (remote.Remote, error) { | ||||
| 	return github.New( | ||||
| 		c.String("github-server"), | ||||
| 		c.String("github-client"), | ||||
| 		c.String("github-sercret"), | ||||
| 		c.StringSlice("github-scope"), | ||||
| 		c.Bool("github-private-mode"), | ||||
| 		c.Bool("github-skip-verify"), | ||||
| 		c.BoolT("github-merge-ref"), | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										22
									
								
								router/middleware/session/agent.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								router/middleware/session/agent.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package session | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/shared/token" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // AuthorizeAgent authorizes requsts from build agents to access the queue. | ||||
| func AuthorizeAgent(c *gin.Context) { | ||||
| 	secret := c.MustGet("agent").(string) | ||||
|  | ||||
| 	parsed, err := token.ParseRequest(c.Request, func(t *token.Token) (string, error) { | ||||
| 		return secret, nil | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		c.AbortWithError(403, err) | ||||
| 	} else if parsed.Kind != token.AgentToken { | ||||
| 		c.AbortWithStatus(403) | ||||
| 	} else { | ||||
| 		c.Next() | ||||
| 	} | ||||
| } | ||||
| @@ -44,6 +44,10 @@ func SetUser() gin.HandlerFunc { | ||||
| 			return user.Hash, err | ||||
| 		}) | ||||
| 		if err == nil { | ||||
| 			confv := c.MustGet("config") | ||||
| 			if conf, ok := confv.(*model.Config); ok { | ||||
| 				user.Admin = conf.IsAdmin(user) | ||||
| 			} | ||||
| 			c.Set("user", user) | ||||
|  | ||||
| 			// if this is a session token (ie not the API token) | ||||
|   | ||||
							
								
								
									
										27
									
								
								router/middleware/store.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								router/middleware/store.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/drone/drone/store" | ||||
| 	"github.com/drone/drone/store/datastore" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Store is a middleware function that initializes the Datastore and attaches to | ||||
| // the context of every http.Request. | ||||
| func Store(cli *cli.Context) gin.HandlerFunc { | ||||
| 	v := setupStore(cli) | ||||
| 	return func(c *gin.Context) { | ||||
| 		store.ToContext(c, v) | ||||
| 		c.Next() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // helper function to create the datastore from the CLI context. | ||||
| func setupStore(c *cli.Context) store.Store { | ||||
| 	return datastore.New( | ||||
| 		c.String("driver"), | ||||
| 		c.String("datasource"), | ||||
| 	) | ||||
| } | ||||
							
								
								
									
										17
									
								
								router/middleware/stream.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								router/middleware/stream.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/stream" | ||||
|  | ||||
| 	"github.com/codegangsta/cli" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Stream is a middleware function that initializes the Stream and attaches to | ||||
| // the context of every http.Request. | ||||
| func Stream(cli *cli.Context) gin.HandlerFunc { | ||||
| 	v := stream.New() | ||||
| 	return func(c *gin.Context) { | ||||
| 		stream.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										12
									
								
								router/middleware/version.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								router/middleware/version.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/version" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Version is a middleware function that appends the Drone version information | ||||
| // to the HTTP response. This is intended for debugging and troubleshooting. | ||||
| func Version(c *gin.Context) { | ||||
| 	c.Header("X-DRONE-VERSION", version.Version) | ||||
| } | ||||
							
								
								
									
										394
									
								
								router/router.go
									
									
									
									
									
								
							
							
						
						
									
										394
									
								
								router/router.go
									
									
									
									
									
								
							| @@ -1,201 +1,199 @@ | ||||
| package router | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
|  | ||||
| 	"github.com/drone/drone/router/middleware/header" | ||||
| 	"github.com/drone/drone/router/middleware/session" | ||||
| 	"github.com/drone/drone/router/middleware/token" | ||||
| 	"github.com/drone/drone/server" | ||||
| 	"github.com/drone/drone/static" | ||||
| 	"github.com/drone/drone/template" | ||||
| ) | ||||
|  | ||||
| func Load(middleware ...gin.HandlerFunc) http.Handler { | ||||
|  | ||||
| 	e := gin.New() | ||||
| 	e.Use(gin.Recovery()) | ||||
|  | ||||
| 	e.SetHTMLTemplate(template.Load()) | ||||
| 	e.StaticFS("/static", static.FileSystem()) | ||||
|  | ||||
| 	e.Use(header.NoCache) | ||||
| 	e.Use(header.Options) | ||||
| 	e.Use(header.Secure) | ||||
| 	e.Use(middleware...) | ||||
| 	e.Use(session.SetUser()) | ||||
| 	e.Use(token.Refresh) | ||||
|  | ||||
| 	e.GET("/", server.ShowIndex) | ||||
| 	e.GET("/repos", server.ShowAllRepos) | ||||
| 	e.GET("/login", server.ShowLogin) | ||||
| 	e.GET("/login/form", server.ShowLoginForm) | ||||
| 	e.GET("/logout", server.GetLogout) | ||||
|  | ||||
| 	// TODO below will Go away with React UI | ||||
| 	settings := e.Group("/settings") | ||||
| 	{ | ||||
| 		settings.Use(session.MustUser()) | ||||
| 		settings.GET("/profile", server.ShowUser) | ||||
| 	} | ||||
| 	repo := e.Group("/repos/:owner/:name") | ||||
| 	{ | ||||
| 		repo.Use(session.SetRepo()) | ||||
| 		repo.Use(session.SetPerm()) | ||||
| 		repo.Use(session.MustPull) | ||||
|  | ||||
| 		repo.GET("", server.ShowRepo) | ||||
| 		repo.GET("/builds/:number", server.ShowBuild) | ||||
| 		repo.GET("/builds/:number/:job", server.ShowBuild) | ||||
|  | ||||
| 		repo_settings := repo.Group("/settings") | ||||
| 		{ | ||||
| 			repo_settings.GET("", session.MustPush, server.ShowRepoConf) | ||||
| 			repo_settings.GET("/encrypt", session.MustPush, server.ShowRepoEncrypt) | ||||
| 			repo_settings.GET("/badges", server.ShowRepoBadges) | ||||
| 		} | ||||
| 	} | ||||
| 	// TODO above will Go away with React UI | ||||
|  | ||||
| 	user := e.Group("/api/user") | ||||
| 	{ | ||||
| 		user.Use(session.MustUser()) | ||||
| 		user.GET("", server.GetSelf) | ||||
| 		user.GET("/feed", server.GetFeed) | ||||
| 		user.GET("/repos", server.GetRepos) | ||||
| 		user.GET("/repos/remote", server.GetRemoteRepos) | ||||
| 		user.POST("/token", server.PostToken) | ||||
| 		user.DELETE("/token", server.DeleteToken) | ||||
| 	} | ||||
|  | ||||
| 	users := e.Group("/api/users") | ||||
| 	{ | ||||
| 		users.Use(session.MustAdmin()) | ||||
| 		users.GET("", server.GetUsers) | ||||
| 		users.POST("", server.PostUser) | ||||
| 		users.GET("/:login", server.GetUser) | ||||
| 		users.PATCH("/:login", server.PatchUser) | ||||
| 		users.DELETE("/:login", server.DeleteUser) | ||||
| 	} | ||||
|  | ||||
| 	repos := e.Group("/api/repos/:owner/:name") | ||||
| 	{ | ||||
| 		repos.POST("", server.PostRepo) | ||||
|  | ||||
| 		repo := repos.Group("") | ||||
| 		{ | ||||
| 			repo.Use(session.SetRepo()) | ||||
| 			repo.Use(session.SetPerm()) | ||||
| 			repo.Use(session.MustPull) | ||||
|  | ||||
| 			repo.GET("", server.GetRepo) | ||||
| 			repo.GET("/builds", server.GetBuilds) | ||||
| 			repo.GET("/builds/:number", server.GetBuild) | ||||
| 			repo.GET("/logs/:number/:job", server.GetBuildLogs) | ||||
| 			repo.POST("/sign", session.MustPush, server.Sign) | ||||
|  | ||||
| 			repo.POST("/secrets", session.MustPush, server.PostSecret) | ||||
| 			repo.DELETE("/secrets/:secret", session.MustPush, server.DeleteSecret) | ||||
|  | ||||
| 			// requires push permissions | ||||
| 			repo.PATCH("", session.MustPush, server.PatchRepo) | ||||
| 			repo.DELETE("", session.MustPush, server.DeleteRepo) | ||||
|  | ||||
| 			repo.POST("/builds/:number", session.MustPush, server.PostBuild) | ||||
| 			repo.DELETE("/builds/:number/:job", session.MustPush, server.DeleteBuild) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	badges := e.Group("/api/badges/:owner/:name") | ||||
| 	{ | ||||
| 		badges.GET("/status.svg", server.GetBadge) | ||||
| 		badges.GET("/cc.xml", server.GetCC) | ||||
| 	} | ||||
|  | ||||
| 	e.POST("/hook", server.PostHook) | ||||
| 	e.POST("/api/hook", server.PostHook) | ||||
|  | ||||
| 	stream := e.Group("/api/stream") | ||||
| 	{ | ||||
| 		stream.Use(session.SetRepo()) | ||||
| 		stream.Use(session.SetPerm()) | ||||
| 		stream.Use(session.MustPull) | ||||
|  | ||||
| 		stream.GET("/:owner/:name", server.GetRepoEvents) | ||||
| 		stream.GET("/:owner/:name/:build/:number", server.GetStream) | ||||
| 	} | ||||
|  | ||||
| 	auth := e.Group("/authorize") | ||||
| 	{ | ||||
| 		auth.GET("", server.GetLogin) | ||||
| 		auth.POST("", server.GetLogin) | ||||
| 		auth.POST("/token", server.GetLoginToken) | ||||
| 	} | ||||
|  | ||||
| 	queue := e.Group("/api/queue") | ||||
| 	{ | ||||
| 		queue.Use(session.AuthorizeAgent) | ||||
| 		queue.POST("/pull", server.Pull) | ||||
| 		queue.POST("/pull/:os/:arch", server.Pull) | ||||
| 		queue.POST("/wait/:id", server.Wait) | ||||
| 		queue.POST("/stream/:id", server.Stream) | ||||
| 		queue.POST("/status/:id", server.Update) | ||||
| 	} | ||||
|  | ||||
| 	// DELETE THESE | ||||
| 	// gitlab := e.Group("/gitlab/:owner/:name") | ||||
| 	// { | ||||
| 	// 	gitlab.Use(session.SetRepo()) | ||||
| 	// 	gitlab.GET("/commits/:sha", GetCommit) | ||||
| 	// 	gitlab.GET("/pulls/:number", GetPullRequest) | ||||
| 	// | ||||
| 	// 	redirects := gitlab.Group("/redirect") | ||||
| 	// 	{ | ||||
| 	// 		redirects.GET("/commits/:sha", RedirectSha) | ||||
| 	// 		redirects.GET("/pulls/:number", RedirectPullRequest) | ||||
| 	// 	} | ||||
| 	// } | ||||
|  | ||||
| 	// bots := e.Group("/bots") | ||||
| 	// { | ||||
| 	// 	bots.Use(session.MustUser()) | ||||
| 	// 	bots.POST("/slack", Slack) | ||||
| 	// 	bots.POST("/slack/:command", Slack) | ||||
| 	// } | ||||
|  | ||||
| 	return normalize(e) | ||||
| } | ||||
|  | ||||
| // THIS HACK JOB IS GOING AWAY SOON. | ||||
| // | ||||
| // import ( | ||||
| // 	"net/http" | ||||
| // 	"strings" | ||||
| // | ||||
| // 	"github.com/gin-gonic/gin" | ||||
| // | ||||
| // 	"github.com/drone/drone/api" | ||||
| // 	"github.com/drone/drone/router/middleware" | ||||
| // 	"github.com/drone/drone/router/middleware/header" | ||||
| // 	"github.com/drone/drone/router/middleware/session" | ||||
| // 	"github.com/drone/drone/router/middleware/token" | ||||
| // 	"github.com/drone/drone/static" | ||||
| // 	"github.com/drone/drone/template" | ||||
| // 	"github.com/drone/drone/web" | ||||
| // ) | ||||
| // | ||||
| // func Load(middlewares ...gin.HandlerFunc) http.Handler { | ||||
| // 	e := gin.New() | ||||
| // 	e.Use(gin.Recovery()) | ||||
| // | ||||
| // 	e.SetHTMLTemplate(template.Load()) | ||||
| // 	e.StaticFS("/static", static.FileSystem()) | ||||
| // | ||||
| // 	e.Use(header.NoCache) | ||||
| // 	e.Use(header.Options) | ||||
| // 	e.Use(header.Secure) | ||||
| // 	e.Use(middlewares...) | ||||
| // 	e.Use(session.SetUser()) | ||||
| // 	e.Use(token.Refresh) | ||||
| // | ||||
| // 	e.GET("/", web.ShowIndex) | ||||
| // 	e.GET("/repos", web.ShowAllRepos) | ||||
| // 	e.GET("/login", web.ShowLogin) | ||||
| // 	e.GET("/login/form", web.ShowLoginForm) | ||||
| // 	e.GET("/logout", web.GetLogout) | ||||
| // | ||||
| // 	settings := e.Group("/settings") | ||||
| // 	{ | ||||
| // 		settings.Use(session.MustUser()) | ||||
| // 		settings.GET("/profile", web.ShowUser) | ||||
| // 	} | ||||
| // 	repo := e.Group("/repos/:owner/:name") | ||||
| // 	{ | ||||
| // 		repo.Use(session.SetRepo()) | ||||
| // 		repo.Use(session.SetPerm()) | ||||
| // 		repo.Use(session.MustPull) | ||||
| // | ||||
| // 		repo.GET("", web.ShowRepo) | ||||
| // 		repo.GET("/builds/:number", web.ShowBuild) | ||||
| // 		repo.GET("/builds/:number/:job", web.ShowBuild) | ||||
| // | ||||
| // 		repo_settings := repo.Group("/settings") | ||||
| // 		{ | ||||
| // 			repo_settings.GET("", session.MustPush, web.ShowRepoConf) | ||||
| // 			repo_settings.GET("/encrypt", session.MustPush, web.ShowRepoEncrypt) | ||||
| // 			repo_settings.GET("/badges", web.ShowRepoBadges) | ||||
| // 		} | ||||
| // 	} | ||||
| // | ||||
| // 	user := e.Group("/api/user") | ||||
| // 	{ | ||||
| // 		user.Use(session.MustUser()) | ||||
| // 		user.GET("", api.GetSelf) | ||||
| // 		user.GET("/feed", api.GetFeed) | ||||
| // 		user.GET("/repos", api.GetRepos) | ||||
| // 		user.GET("/repos/remote", api.GetRemoteRepos) | ||||
| // 		user.POST("/token", api.PostToken) | ||||
| // 		user.DELETE("/token", api.DeleteToken) | ||||
| // 	} | ||||
| // | ||||
| // 	users := e.Group("/api/users") | ||||
| // 	{ | ||||
| // 		users.Use(session.MustAdmin()) | ||||
| // 		users.GET("", api.GetUsers) | ||||
| // 		users.POST("", api.PostUser) | ||||
| // 		users.GET("/:login", api.GetUser) | ||||
| // 		users.PATCH("/:login", api.PatchUser) | ||||
| // 		users.DELETE("/:login", api.DeleteUser) | ||||
| // 	} | ||||
| // | ||||
| // 	repos := e.Group("/api/repos/:owner/:name") | ||||
| // 	{ | ||||
| // 		repos.POST("", api.PostRepo) | ||||
| // | ||||
| // 		repo := repos.Group("") | ||||
| // 		{ | ||||
| // 			repo.Use(session.SetRepo()) | ||||
| // 			repo.Use(session.SetPerm()) | ||||
| // 			repo.Use(session.MustPull) | ||||
| // | ||||
| // 			repo.GET("", api.GetRepo) | ||||
| // 			repo.GET("/key", api.GetRepoKey) | ||||
| // 			repo.POST("/key", api.PostRepoKey) | ||||
| // 			repo.GET("/builds", api.GetBuilds) | ||||
| // 			repo.GET("/builds/:number", api.GetBuild) | ||||
| // 			repo.GET("/logs/:number/:job", api.GetBuildLogs) | ||||
| // 			repo.POST("/sign", session.MustPush, api.Sign) | ||||
| // | ||||
| // 			repo.POST("/secrets", session.MustPush, api.PostSecret) | ||||
| // 			repo.DELETE("/secrets/:secret", session.MustPush, api.DeleteSecret) | ||||
| // | ||||
| // 			// requires authenticated user | ||||
| // 			repo.POST("/encrypt", session.MustUser(), api.PostSecure) | ||||
| // | ||||
| // 			// requires push permissions | ||||
| // 			repo.PATCH("", session.MustPush, api.PatchRepo) | ||||
| // 			repo.DELETE("", session.MustPush, api.DeleteRepo) | ||||
| // | ||||
| // 			repo.POST("/builds/:number", session.MustPush, api.PostBuild) | ||||
| // 			repo.DELETE("/builds/:number/:job", session.MustPush, api.DeleteBuild) | ||||
| // 		} | ||||
| // 	} | ||||
| // | ||||
| // 	badges := e.Group("/api/badges/:owner/:name") | ||||
| // 	{ | ||||
| // 		badges.GET("/status.svg", web.GetBadge) | ||||
| // 		badges.GET("/cc.xml", web.GetCC) | ||||
| // 	} | ||||
| // | ||||
| // 	e.POST("/hook", web.PostHook) | ||||
| // 	e.POST("/api/hook", web.PostHook) | ||||
| // | ||||
| // 	stream := e.Group("/api/stream") | ||||
| // 	{ | ||||
| // 		stream.Use(session.SetRepo()) | ||||
| // 		stream.Use(session.SetPerm()) | ||||
| // 		stream.Use(session.MustPull) | ||||
| // | ||||
| // 		stream.GET("/:owner/:name", web.GetRepoEvents) | ||||
| // 		stream.GET("/:owner/:name/:build/:number", web.GetStream) | ||||
| // 	} | ||||
| // | ||||
| // 	bots := e.Group("/bots") | ||||
| // 	{ | ||||
| // 		bots.Use(session.MustUser()) | ||||
| // 		bots.POST("/slack", web.Slack) | ||||
| // 		bots.POST("/slack/:command", web.Slack) | ||||
| // 	} | ||||
| // | ||||
| // 	auth := e.Group("/authorize") | ||||
| // 	{ | ||||
| // 		auth.GET("", web.GetLogin) | ||||
| // 		auth.POST("", web.GetLogin) | ||||
| // 		auth.POST("/token", web.GetLoginToken) | ||||
| // 	} | ||||
| // | ||||
| // 	queue := e.Group("/api/queue") | ||||
| // 	{ | ||||
| // 		queue.Use(middleware.AgentMust()) | ||||
| // 		queue.POST("/pull", api.Pull) | ||||
| // 		queue.POST("/pull/:os/:arch", api.Pull) | ||||
| // 		queue.POST("/wait/:id", api.Wait) | ||||
| // 		queue.POST("/stream/:id", api.Stream) | ||||
| // 		queue.POST("/status/:id", api.Update) | ||||
| // 	} | ||||
| // | ||||
| // 	gitlab := e.Group("/gitlab/:owner/:name") | ||||
| // 	{ | ||||
| // 		gitlab.Use(session.SetRepo()) | ||||
| // 		gitlab.GET("/commits/:sha", web.GetCommit) | ||||
| // 		gitlab.GET("/pulls/:number", web.GetPullRequest) | ||||
| // | ||||
| // 		redirects := gitlab.Group("/redirect") | ||||
| // 		{ | ||||
| // 			redirects.GET("/commits/:sha", web.RedirectSha) | ||||
| // 			redirects.GET("/pulls/:number", web.RedirectPullRequest) | ||||
| // 		} | ||||
| // 	} | ||||
| // | ||||
| // 	return normalize(e) | ||||
| // } | ||||
| // | ||||
| // // normalize is a helper function to work around the following | ||||
| // // issue with gin. https://github.com/gin-gonic/gin/issues/388 | ||||
| // func normalize(h http.Handler) http.Handler { | ||||
| // 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| // | ||||
| // 		parts := strings.Split(r.URL.Path, "/")[1:] | ||||
| // 		switch parts[0] { | ||||
| // 		case "settings", "bots", "repos", "api", "login", "logout", "", "authorize", "hook", "static", "gitlab": | ||||
| // 			// no-op | ||||
| // 		default: | ||||
| // | ||||
| // 			if len(parts) > 2 && parts[2] != "settings" { | ||||
| // 				parts = append(parts[:2], append([]string{"builds"}, parts[2:]...)...) | ||||
| // 			} | ||||
| // | ||||
| // 			// prefix the URL with /repo so that it | ||||
| // 			// can be effectively routed. | ||||
| // 			parts = append([]string{"", "repos"}, parts...) | ||||
| // | ||||
| // 			// reconstruct the path | ||||
| // 			r.URL.Path = strings.Join(parts, "/") | ||||
| // 		} | ||||
| // | ||||
| // 		h.ServeHTTP(w, r) | ||||
| // 	}) | ||||
| // } | ||||
| // normalize is a helper function to work around the following | ||||
| // issue with gin. https://github.com/gin-gonic/gin/issues/388 | ||||
| func normalize(h http.Handler) http.Handler { | ||||
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
|  | ||||
| 		parts := strings.Split(r.URL.Path, "/")[1:] | ||||
| 		switch parts[0] { | ||||
| 		case "settings", "bots", "repos", "api", "login", "logout", "", "authorize", "hook", "static", "gitlab": | ||||
| 			// no-op | ||||
| 		default: | ||||
|  | ||||
| 			if len(parts) > 2 && parts[2] != "settings" { | ||||
| 				parts = append(parts[:2], append([]string{"builds"}, parts[2:]...)...) | ||||
| 			} | ||||
|  | ||||
| 			// prefix the URL with /repo so that it | ||||
| 			// can be effectively routed. | ||||
| 			parts = append([]string{"", "repos"}, parts...) | ||||
|  | ||||
| 			// reconstruct the path | ||||
| 			r.URL.Path = strings.Join(parts, "/") | ||||
| 		} | ||||
|  | ||||
| 		h.ServeHTTP(w, r) | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| package web | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -1,10 +1,8 @@ | ||||
| package api | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| 
 | ||||
| @@ -21,18 +19,6 @@ import ( | ||||
| 	"github.com/drone/drone/router/middleware/session" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	droneYml = os.Getenv("BUILD_CONFIG_FILE") | ||||
| 	droneSec string | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	if droneYml == "" { | ||||
| 		droneYml = ".drone.yml" | ||||
| 	} | ||||
| 	droneSec = fmt.Sprintf("%s.sig", droneYml) | ||||
| } | ||||
| 
 | ||||
| func GetBuilds(c *gin.Context) { | ||||
| 	repo := session.Repo(c) | ||||
| 	builds, err := store.GetBuildList(c, repo) | ||||
| @@ -189,7 +175,8 @@ func PostBuild(c *gin.Context) { | ||||
| 	} | ||||
| 
 | ||||
| 	// fetch the .drone.yml file from the database | ||||
| 	raw, err := remote_.File(user, repo, build, droneYml) | ||||
| 	config := ToConfig(c) | ||||
| 	raw, err := remote_.File(user, repo, build, config.Yaml) | ||||
| 	if err != nil { | ||||
| 		log.Errorf("failure to get build config for %s. %s", repo.FullName, err) | ||||
| 		c.AbortWithError(404, err) | ||||
| @@ -197,7 +184,7 @@ func PostBuild(c *gin.Context) { | ||||
| 	} | ||||
| 
 | ||||
| 	// Fetch secrets file but don't exit on error as it's optional | ||||
| 	sec, err := remote_.File(user, repo, build, droneSec) | ||||
| 	sec, err := remote_.File(user, repo, build, config.Shasum) | ||||
| 	if err != nil { | ||||
| 		log.Debugf("cannot find build secrets for %s. %s", repo.FullName, err) | ||||
| 	} | ||||
| @@ -1,4 +1,4 @@ | ||||
| package web | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -1,85 +0,0 @@ | ||||
| package server | ||||
|  | ||||
| import ( | ||||
| 	"github.com/drone/drone/bus" | ||||
| 	"github.com/drone/drone/cache" | ||||
| 	"github.com/drone/drone/queue" | ||||
| 	"github.com/drone/drone/remote" | ||||
| 	"github.com/drone/drone/store" | ||||
| 	"github.com/drone/drone/stream" | ||||
| 	"github.com/drone/drone/version" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // HandlerCache returns a HandlerFunc that passes a Cache to the Context. | ||||
| func HandlerCache(v cache.Cache) gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		cache.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerBus returns a HandlerFunc that passes a Bus to the Context. | ||||
| func HandlerBus(v bus.Bus) gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		bus.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerStore returns a HandlerFunc that passes a Store to the Context. | ||||
| func HandlerStore(v store.Store) gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		store.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerQueue returns a HandlerFunc that passes a Queue to the Context. | ||||
| func HandlerQueue(v queue.Queue) gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		queue.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerStream returns a HandlerFunc that passes a Stream to the Context. | ||||
| func HandlerStream(v stream.Stream) gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		stream.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerRemote returns a HandlerFunc that passes a Remote to the Context. | ||||
| func HandlerRemote(v remote.Remote) gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		remote.ToContext(c, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerConfig returns a HandlerFunc that passes server Config to the Context. | ||||
| func HandlerConfig(v *Config) gin.HandlerFunc { | ||||
| 	const k = "config" | ||||
| 	return func(c *gin.Context) { | ||||
| 		c.Set(k, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerVersion returns a HandlerFunc that writes the Version information to | ||||
| // the http.Response as a the X-Drone-Version header. | ||||
| func HandlerVersion() gin.HandlerFunc { | ||||
| 	return func(c *gin.Context) { | ||||
| 		c.Header("X-Drone-Version", version.Version) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandlerAgent returns a HandlerFunc that passes an Agent token to the Context. | ||||
| func HandlerAgent(v string) gin.HandlerFunc { | ||||
| 	const k = "agent" | ||||
| 	return func(c *gin.Context) { | ||||
| 		c.Set(k, v) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ToConfig returns the config from the Context | ||||
| func ToConfig(c *gin.Context) *Config { | ||||
| 	v := c.MustGet("config") | ||||
| 	return v.(*Config) | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
| package server | ||||
| @@ -1,8 +1,7 @@ | ||||
| package web | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"regexp" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| @@ -19,18 +18,6 @@ import ( | ||||
| 	"github.com/drone/drone/yaml" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	droneYml = os.Getenv("BUILD_CONFIG_FILE") | ||||
| 	droneSec string | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	if droneYml == "" { | ||||
| 		droneYml = ".drone.yml" | ||||
| 	} | ||||
| 	droneSec = fmt.Sprintf("%s.sig", droneYml) | ||||
| } | ||||
| 
 | ||||
| var skipRe = regexp.MustCompile(`\[(?i:ci *skip|skip *ci)\]`) | ||||
| 
 | ||||
| func PostHook(c *gin.Context) { | ||||
| @@ -135,13 +122,14 @@ func PostHook(c *gin.Context) { | ||||
| 	} | ||||
| 
 | ||||
| 	// fetch the build file from the database | ||||
| 	raw, err := remote_.File(user, repo, build, droneYml) | ||||
| 	config := ToConfig(c) | ||||
| 	raw, err := remote_.File(user, repo, build, config.Yaml) | ||||
| 	if err != nil { | ||||
| 		log.Errorf("failure to get build config for %s. %s", repo.FullName, err) | ||||
| 		c.AbortWithError(404, err) | ||||
| 		return | ||||
| 	} | ||||
| 	sec, err := remote_.File(user, repo, build, droneSec) | ||||
| 	sec, err := remote_.File(user, repo, build, config.Shasum) | ||||
| 	if err != nil { | ||||
| 		log.Debugf("cannot find build secrets for %s. %s", repo.FullName, err) | ||||
| 		// NOTE we don't exit on failure. The sec file is optional | ||||
| @@ -159,3 +159,9 @@ type tokenPayload struct { | ||||
| 	Refresh string `json:"refresh_token,omitempty"` | ||||
| 	Expires int64  `json:"expires_in,omitempty"` | ||||
| } | ||||
|  | ||||
| // ToConfig returns the config from the Context | ||||
| func ToConfig(c *gin.Context) *model.Config { | ||||
| 	v := c.MustGet("config") | ||||
| 	return v.(*model.Config) | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| package web | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package api | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package api | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package api | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/drone/drone/model" | ||||
							
								
								
									
										241
									
								
								server/server.go
									
									
									
									
									
								
							
							
						
						
									
										241
									
								
								server/server.go
									
									
									
									
									
								
							| @@ -1,241 +0,0 @@ | ||||
| package server | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/drone/drone/api" | ||||
| 	"github.com/drone/drone/bus" | ||||
| 	"github.com/drone/drone/cache" | ||||
| 	"github.com/drone/drone/queue" | ||||
| 	"github.com/drone/drone/remote" | ||||
| 	"github.com/drone/drone/router/middleware" | ||||
| 	"github.com/drone/drone/router/middleware/header" | ||||
| 	"github.com/drone/drone/router/middleware/session" | ||||
| 	"github.com/drone/drone/router/middleware/token" | ||||
| 	"github.com/drone/drone/static" | ||||
| 	"github.com/drone/drone/store" | ||||
| 	"github.com/drone/drone/stream" | ||||
| 	"github.com/drone/drone/template" | ||||
| 	"github.com/drone/drone/web" | ||||
|  | ||||
| 	"github.com/gin-gonic/contrib/ginrus" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| // Config defines system configuration parameters. | ||||
| type Config struct { | ||||
| 	Open   bool            // Enables open registration | ||||
| 	Yaml   string          // Customize the Yaml configuration file name | ||||
| 	Secret string          // Secret token used to authenticate agents | ||||
| 	Admins map[string]bool // Administrative users | ||||
| 	Orgs   map[string]bool // Organization whitelist | ||||
| } | ||||
|  | ||||
| // Server defines the server configuration. | ||||
| type Server struct { | ||||
| 	Bus    bus.Bus | ||||
| 	Cache  cache.Cache | ||||
| 	Queue  queue.Queue | ||||
| 	Remote remote.Remote | ||||
| 	Stream stream.Stream | ||||
| 	Store  store.Store | ||||
| 	Config *Config | ||||
| } | ||||
|  | ||||
| // Handler returns an http.Handler for servering Drone requests. | ||||
| func (s *Server) Handler() http.Handler { | ||||
|  | ||||
| 	e := gin.New() | ||||
| 	e.Use(gin.Recovery()) | ||||
|  | ||||
| 	e.SetHTMLTemplate(template.Load()) | ||||
| 	e.StaticFS("/static", static.FileSystem()) | ||||
|  | ||||
| 	e.Use(header.NoCache) | ||||
| 	e.Use(header.Options) | ||||
| 	e.Use(header.Secure) | ||||
| 	e.Use( | ||||
| 		ginrus.Ginrus(logrus.StandardLogger(), time.RFC3339, true), | ||||
| 		HandlerVersion(), | ||||
| 		HandlerQueue(s.Queue), | ||||
| 		HandlerStream(s.Stream), | ||||
| 		HandlerBus(s.Bus), | ||||
| 		HandlerCache(s.Cache), | ||||
| 		HandlerStore(s.Store), | ||||
| 		HandlerRemote(s.Remote), | ||||
| 		HandlerConfig(s.Config), | ||||
| 	) | ||||
| 	e.Use(session.SetUser()) | ||||
| 	e.Use(token.Refresh) | ||||
|  | ||||
| 	e.GET("/", web.ShowIndex) | ||||
| 	e.GET("/repos", web.ShowAllRepos) | ||||
| 	e.GET("/login", web.ShowLogin) | ||||
| 	e.GET("/login/form", web.ShowLoginForm) | ||||
| 	e.GET("/logout", GetLogout) | ||||
|  | ||||
| 	// TODO below will Go away with React UI | ||||
| 	settings := e.Group("/settings") | ||||
| 	{ | ||||
| 		settings.Use(session.MustUser()) | ||||
| 		settings.GET("/profile", web.ShowUser) | ||||
| 	} | ||||
| 	repo := e.Group("/repos/:owner/:name") | ||||
| 	{ | ||||
| 		repo.Use(session.SetRepo()) | ||||
| 		repo.Use(session.SetPerm()) | ||||
| 		repo.Use(session.MustPull) | ||||
|  | ||||
| 		repo.GET("", web.ShowRepo) | ||||
| 		repo.GET("/builds/:number", web.ShowBuild) | ||||
| 		repo.GET("/builds/:number/:job", web.ShowBuild) | ||||
|  | ||||
| 		repo_settings := repo.Group("/settings") | ||||
| 		{ | ||||
| 			repo_settings.GET("", session.MustPush, web.ShowRepoConf) | ||||
| 			repo_settings.GET("/encrypt", session.MustPush, web.ShowRepoEncrypt) | ||||
| 			repo_settings.GET("/badges", web.ShowRepoBadges) | ||||
| 		} | ||||
| 	} | ||||
| 	// TODO above will Go away with React UI | ||||
|  | ||||
| 	user := e.Group("/api/user") | ||||
| 	{ | ||||
| 		user.Use(session.MustUser()) | ||||
| 		user.GET("", api.GetSelf) | ||||
| 		user.GET("/feed", api.GetFeed) | ||||
| 		user.GET("/repos", api.GetRepos) | ||||
| 		user.GET("/repos/remote", api.GetRemoteRepos) | ||||
| 		user.POST("/token", api.PostToken) | ||||
| 		user.DELETE("/token", api.DeleteToken) | ||||
| 	} | ||||
|  | ||||
| 	users := e.Group("/api/users") | ||||
| 	{ | ||||
| 		users.Use(session.MustAdmin()) | ||||
| 		users.GET("", api.GetUsers) | ||||
| 		users.POST("", api.PostUser) | ||||
| 		users.GET("/:login", api.GetUser) | ||||
| 		users.PATCH("/:login", api.PatchUser) | ||||
| 		users.DELETE("/:login", api.DeleteUser) | ||||
| 	} | ||||
|  | ||||
| 	repos := e.Group("/api/repos/:owner/:name") | ||||
| 	{ | ||||
| 		repos.POST("", api.PostRepo) | ||||
|  | ||||
| 		repo := repos.Group("") | ||||
| 		{ | ||||
| 			repo.Use(session.SetRepo()) | ||||
| 			repo.Use(session.SetPerm()) | ||||
| 			repo.Use(session.MustPull) | ||||
|  | ||||
| 			repo.GET("", api.GetRepo) | ||||
| 			repo.GET("/builds", api.GetBuilds) | ||||
| 			repo.GET("/builds/:number", api.GetBuild) | ||||
| 			repo.GET("/logs/:number/:job", api.GetBuildLogs) | ||||
| 			repo.POST("/sign", session.MustPush, api.Sign) | ||||
|  | ||||
| 			repo.POST("/secrets", session.MustPush, api.PostSecret) | ||||
| 			repo.DELETE("/secrets/:secret", session.MustPush, api.DeleteSecret) | ||||
|  | ||||
| 			// requires push permissions | ||||
| 			repo.PATCH("", session.MustPush, api.PatchRepo) | ||||
| 			repo.DELETE("", session.MustPush, api.DeleteRepo) | ||||
|  | ||||
| 			repo.POST("/builds/:number", session.MustPush, api.PostBuild) | ||||
| 			repo.DELETE("/builds/:number/:job", session.MustPush, api.DeleteBuild) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	badges := e.Group("/api/badges/:owner/:name") | ||||
| 	{ | ||||
| 		badges.GET("/status.svg", web.GetBadge) | ||||
| 		badges.GET("/cc.xml", web.GetCC) | ||||
| 	} | ||||
|  | ||||
| 	e.POST("/hook", web.PostHook) | ||||
| 	e.POST("/api/hook", web.PostHook) | ||||
|  | ||||
| 	stream := e.Group("/api/stream") | ||||
| 	{ | ||||
| 		stream.Use(session.SetRepo()) | ||||
| 		stream.Use(session.SetPerm()) | ||||
| 		stream.Use(session.MustPull) | ||||
|  | ||||
| 		stream.GET("/:owner/:name", web.GetRepoEvents) | ||||
| 		stream.GET("/:owner/:name/:build/:number", web.GetStream) | ||||
| 	} | ||||
|  | ||||
| 	auth := e.Group("/authorize") | ||||
| 	{ | ||||
| 		auth.GET("", GetLogin) | ||||
| 		auth.POST("", GetLogin) | ||||
| 		auth.POST("/token", GetLoginToken) | ||||
| 	} | ||||
|  | ||||
| 	queue := e.Group("/api/queue") | ||||
| 	{ | ||||
| 		queue.Use(middleware.AgentMust()) | ||||
| 		queue.POST("/pull", api.Pull) | ||||
| 		queue.POST("/pull/:os/:arch", api.Pull) | ||||
| 		queue.POST("/wait/:id", api.Wait) | ||||
| 		queue.POST("/stream/:id", api.Stream) | ||||
| 		queue.POST("/status/:id", api.Update) | ||||
| 	} | ||||
|  | ||||
| 	// DELETE THESE | ||||
| 	// gitlab := e.Group("/gitlab/:owner/:name") | ||||
| 	// { | ||||
| 	// 	gitlab.Use(session.SetRepo()) | ||||
| 	// 	gitlab.GET("/commits/:sha", web.GetCommit) | ||||
| 	// 	gitlab.GET("/pulls/:number", web.GetPullRequest) | ||||
| 	// | ||||
| 	// 	redirects := gitlab.Group("/redirect") | ||||
| 	// 	{ | ||||
| 	// 		redirects.GET("/commits/:sha", web.RedirectSha) | ||||
| 	// 		redirects.GET("/pulls/:number", web.RedirectPullRequest) | ||||
| 	// 	} | ||||
| 	// } | ||||
|  | ||||
| 	// bots := e.Group("/bots") | ||||
| 	// { | ||||
| 	// 	bots.Use(session.MustUser()) | ||||
| 	// 	bots.POST("/slack", web.Slack) | ||||
| 	// 	bots.POST("/slack/:command", web.Slack) | ||||
| 	// } | ||||
|  | ||||
| 	return normalize(e) | ||||
| } | ||||
|  | ||||
| // THIS HACK JOB IS GOING AWAY SOON. | ||||
| // | ||||
| // normalize is a helper function to work around the following | ||||
| // issue with gin. https://github.com/gin-gonic/gin/issues/388 | ||||
| func normalize(h http.Handler) http.Handler { | ||||
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
|  | ||||
| 		parts := strings.Split(r.URL.Path, "/")[1:] | ||||
| 		switch parts[0] { | ||||
| 		case "settings", "bots", "repos", "api", "login", "logout", "", "authorize", "hook", "static", "gitlab": | ||||
| 			// no-op | ||||
| 		default: | ||||
|  | ||||
| 			if len(parts) > 2 && parts[2] != "settings" { | ||||
| 				parts = append(parts[:2], append([]string{"builds"}, parts[2:]...)...) | ||||
| 			} | ||||
|  | ||||
| 			// prefix the URL with /repo so that it | ||||
| 			// can be effectively routed. | ||||
| 			parts = append([]string{"", "repos"}, parts...) | ||||
|  | ||||
| 			// reconstruct the path | ||||
| 			r.URL.Path = strings.Join(parts, "/") | ||||
| 		} | ||||
|  | ||||
| 		h.ServeHTTP(w, r) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package api | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package web | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"strings" | ||||
| @@ -1,4 +1,4 @@ | ||||
| package web | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| @@ -11,6 +11,7 @@ | ||||
| //     - application/json | ||||
| // | ||||
| // swagger:meta | ||||
| package api | ||||
| package swagger | ||||
| 
 | ||||
| //go:generate swagger generate spec -o swagger/files/swagger.json | ||||
| //go:generate swagger generate spec -o files/swagger.json | ||||
| //go:generate go-bindata -pkg swagger -o swagger_gen.go files/ | ||||
							
								
								
									
										85
									
								
								server/swagger/swagger.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								server/swagger/swagger.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| package swagger | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/drone/drone/model" | ||||
| ) | ||||
|  | ||||
| // swagger:route GET /users/{login} user getUser | ||||
| // | ||||
| // Get the user with the matching login. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func userFind(w http.ResponseWriter, r *http.Request) {} | ||||
|  | ||||
| // swagger:route GET /user user getCurrentUser | ||||
| // | ||||
| // Get the currently authenticated user. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func userCurrent(w http.ResponseWriter, r *http.Request) {} | ||||
|  | ||||
| // swagger:route GET /users user getUserList | ||||
| // | ||||
| // Get the list of all registered users. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func userList(w http.ResponseWriter, r *http.Request) {} | ||||
|  | ||||
| // swagger:route GET /user/feed user getUserFeed | ||||
| // | ||||
| // Get the currently authenticated user's build feed. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: feed | ||||
| // | ||||
| func userFeed(w http.ResponseWriter, r *http.Request) {} | ||||
|  | ||||
| // swagger:route DELETE /users/{login} user deleteUserLogin | ||||
| // | ||||
| // Delete the user with the matching login. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func userDelete(w http.ResponseWriter, r *http.Request) {} | ||||
|  | ||||
| // swagger:route GET /user/repos user getUserRepos | ||||
| // | ||||
| // Get the currently authenticated user's active repository list. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: repos | ||||
| // | ||||
| func repoList(w http.ResponseWriter, r *http.Request) {} | ||||
|  | ||||
| // swagger:response user | ||||
| type userResp struct { | ||||
| 	// in: body | ||||
| 	Body model.User | ||||
| } | ||||
|  | ||||
| // swagger:response users | ||||
| type usersResp struct { | ||||
| 	// in: body | ||||
| 	Body []model.User | ||||
| } | ||||
|  | ||||
| // swagger:response feed | ||||
| type feedResp struct { | ||||
| 	// in: body | ||||
| 	Body []model.Feed | ||||
| } | ||||
|  | ||||
| // swagger:response repos | ||||
| type reposResp struct { | ||||
| 	// in: body | ||||
| 	Body []model.Repo | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package api | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| @@ -6,31 +6,16 @@ import ( | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 
 | ||||
| 	"github.com/drone/drone/cache" | ||||
| 	"github.com/drone/drone/model" | ||||
| 	"github.com/drone/drone/router/middleware/session" | ||||
| 	"github.com/drone/drone/shared/crypto" | ||||
| 	"github.com/drone/drone/shared/token" | ||||
| 	"github.com/drone/drone/store" | ||||
| ) | ||||
| 
 | ||||
| // swagger:route GET /user user getUser | ||||
| // | ||||
| // Get the currently authenticated user. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func GetSelf(c *gin.Context) { | ||||
| 	c.JSON(200, session.User(c)) | ||||
| } | ||||
| 
 | ||||
| // swagger:route GET /user/feed user getUserFeed | ||||
| // | ||||
| // Get the currently authenticated user's build feed. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: feed | ||||
| // | ||||
| func GetFeed(c *gin.Context) { | ||||
| 	repos, err := cache.GetRepos(c, session.User(c)) | ||||
| 	if err != nil { | ||||
| @@ -46,13 +31,6 @@ func GetFeed(c *gin.Context) { | ||||
| 	c.JSON(200, feed) | ||||
| } | ||||
| 
 | ||||
| // swagger:route GET /user/repos user getUserRepos | ||||
| // | ||||
| // Get the currently authenticated user's active repository list. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: repos | ||||
| // | ||||
| func GetRepos(c *gin.Context) { | ||||
| 	repos, err := cache.GetRepos(c, session.User(c)) | ||||
| 	if err != nil { | ||||
| @@ -105,27 +83,3 @@ func DeleteToken(c *gin.Context) { | ||||
| 	} | ||||
| 	c.String(http.StatusOK, tokenstr) | ||||
| } | ||||
| 
 | ||||
| // swagger:response user | ||||
| type userResp struct { | ||||
| 	// in: body | ||||
| 	Body model.User | ||||
| } | ||||
| 
 | ||||
| // swagger:response users | ||||
| type usersResp struct { | ||||
| 	// in: body | ||||
| 	Body []model.User | ||||
| } | ||||
| 
 | ||||
| // swagger:response feed | ||||
| type feedResp struct { | ||||
| 	// in: body | ||||
| 	Body []model.Feed | ||||
| } | ||||
| 
 | ||||
| // swagger:response repos | ||||
| type reposResp struct { | ||||
| 	// in: body | ||||
| 	Body []model.Repo | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package api | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| @@ -10,13 +10,6 @@ import ( | ||||
| 	"github.com/drone/drone/store" | ||||
| ) | ||||
| 
 | ||||
| // swagger:route GET /users user getUserList | ||||
| // | ||||
| // Get the list of all registered users. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func GetUsers(c *gin.Context) { | ||||
| 	users, err := store.GetUserList(c) | ||||
| 	if err != nil { | ||||
| @@ -26,20 +19,13 @@ func GetUsers(c *gin.Context) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // swagger:route GET /users/{login} user getUserLogin | ||||
| // | ||||
| // Get the user with the matching login. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func GetUser(c *gin.Context) { | ||||
| 	user, err := store.GetUserLogin(c, c.Param("login")) | ||||
| 	if err != nil { | ||||
| 		c.String(404, "Cannot find user. %s", err) | ||||
| 	} else { | ||||
| 		c.JSON(200, user) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(200, user) | ||||
| } | ||||
| 
 | ||||
| func PatchUser(c *gin.Context) { | ||||
| @@ -74,31 +60,20 @@ func PostUser(c *gin.Context) { | ||||
| 		c.String(http.StatusBadRequest, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user := &model.User{} | ||||
| 	user.Login = in.Login | ||||
| 	user.Email = in.Email | ||||
| 	user.Admin = in.Admin | ||||
| 	user.Avatar = in.Avatar | ||||
| 	user.Active = true | ||||
| 	user.Hash = crypto.Rand() | ||||
| 
 | ||||
| 	err = store.CreateUser(c, user) | ||||
| 	if err != nil { | ||||
| 	user := &model.User{ | ||||
| 		Active: true, | ||||
| 		Login:  in.Login, | ||||
| 		Email:  in.Email, | ||||
| 		Avatar: in.Avatar, | ||||
| 		Hash:   crypto.Rand(), | ||||
| 	} | ||||
| 	if err = store.CreateUser(c, user); err != nil { | ||||
| 		c.String(http.StatusInternalServerError, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	c.JSON(http.StatusOK, user) | ||||
| } | ||||
| 
 | ||||
| // swagger:route DELETE /users/{login} user deleteUserLogin | ||||
| // | ||||
| // Delete the user with the matching login. | ||||
| // | ||||
| //     Responses: | ||||
| //       200: user | ||||
| // | ||||
| func DeleteUser(c *gin.Context) { | ||||
| 	user, err := store.GetUserLogin(c, c.Param("login")) | ||||
| 	if err != nil { | ||||
| @@ -107,7 +82,7 @@ func DeleteUser(c *gin.Context) { | ||||
| 	} | ||||
| 	if err = store.DeleteUser(c, user); err != nil { | ||||
| 		c.String(500, "Error deleting user. %s", err) | ||||
| 	} else { | ||||
| 		c.String(200, "") | ||||
| 		return | ||||
| 	} | ||||
| 	c.String(200, "") | ||||
| } | ||||
| @@ -1,97 +0,0 @@ | ||||
| package docker | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/samalba/dockerclient" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	LogOpts = &dockerclient.LogOptions{ | ||||
| 		Stdout: true, | ||||
| 		Stderr: true, | ||||
| 	} | ||||
|  | ||||
| 	LogOptsTail = &dockerclient.LogOptions{ | ||||
| 		Follow: true, | ||||
| 		Stdout: true, | ||||
| 		Stderr: true, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| // Run creates the docker container, pulling images if necessary, starts | ||||
| // the container and blocks until the container exits, returning the exit | ||||
| // information. | ||||
| func Run(client dockerclient.Client, conf *dockerclient.ContainerConfig, name string) (*dockerclient.ContainerInfo, error) { | ||||
| 	info, err := RunDaemon(client, conf, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return Wait(client, info.Id) | ||||
| } | ||||
|  | ||||
| // RunDaemon creates the docker container, pulling images if necessary, starts | ||||
| // the container and returns the container information. It does not wait for | ||||
| // the container to exit. | ||||
| func RunDaemon(client dockerclient.Client, conf *dockerclient.ContainerConfig, name string) (*dockerclient.ContainerInfo, error) { | ||||
|  | ||||
| 	// attempts to create the container | ||||
| 	id, err := client.CreateContainer(conf, name, nil) | ||||
| 	if err != nil { | ||||
| 		// and pull the image and re-create if that fails | ||||
| 		err = client.PullImage(conf.Image, nil) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		id, err = client.CreateContainer(conf, name, nil) | ||||
| 		if err != nil { | ||||
| 			client.RemoveContainer(id, true, true) | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// fetches the container information | ||||
| 	info, err := client.InspectContainer(id) | ||||
| 	if err != nil { | ||||
| 		client.RemoveContainer(id, true, true) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// starts the container | ||||
| 	err = client.StartContainer(id, &conf.HostConfig) | ||||
| 	if err != nil { | ||||
| 		client.RemoveContainer(id, true, true) | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return info, err | ||||
| } | ||||
|  | ||||
| // Wait blocks until the named container exits, returning the exit information. | ||||
| func Wait(client dockerclient.Client, name string) (*dockerclient.ContainerInfo, error) { | ||||
|  | ||||
| 	defer func() { | ||||
| 		client.StopContainer(name, 5) | ||||
| 		client.KillContainer(name, "9") | ||||
| 	}() | ||||
|  | ||||
| 	for attempts := 0; attempts < 5; attempts++ { | ||||
| 		done := client.Wait(name) | ||||
| 		<-done | ||||
|  | ||||
| 		info, err := client.InspectContainer(name) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		if !info.State.Running { | ||||
| 			return info, nil | ||||
| 		} | ||||
|  | ||||
| 		log.Debugf("attempting to resume waiting after %d attempts.\n", attempts) | ||||
| 	} | ||||
|  | ||||
| 	return nil, errors.New("reached maximum wait attempts") | ||||
| } | ||||
							
								
								
									
										149
									
								
								web/login.go
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								web/login.go
									
									
									
									
									
								
							| @@ -1,149 +0,0 @@ | ||||
| package web | ||||
|  | ||||
| // | ||||
| // import ( | ||||
| // 	"net/http" | ||||
| // 	"time" | ||||
| // | ||||
| // 	"github.com/drone/drone/model" | ||||
| // 	"github.com/drone/drone/remote" | ||||
| // 	"github.com/drone/drone/shared/crypto" | ||||
| // 	"github.com/drone/drone/shared/httputil" | ||||
| // 	"github.com/drone/drone/shared/token" | ||||
| // 	"github.com/drone/drone/store" | ||||
| // | ||||
| // 	"github.com/Sirupsen/logrus" | ||||
| // 	"github.com/gin-gonic/gin" | ||||
| // ) | ||||
| // | ||||
| // func GetLogin(c *gin.Context) { | ||||
| // 	remote := remote.FromContext(c) | ||||
| // | ||||
| // 	// when dealing with redirects we may need | ||||
| // 	// to adjust the content type. I cannot, however, | ||||
| // 	// remember why, so need to revisit this line. | ||||
| // 	c.Writer.Header().Del("Content-Type") | ||||
| // | ||||
| // 	tmpuser, err := remote.Login(c.Writer, c.Request) | ||||
| // 	if err != nil { | ||||
| // 		logrus.Errorf("cannot authenticate user. %s", err) | ||||
| // 		c.Redirect(303, "/login?error=oauth_error") | ||||
| // 		return | ||||
| // 	} | ||||
| // 	// this will happen when the user is redirected by | ||||
| // 	// the remote provide as part of the oauth dance. | ||||
| // 	if tmpuser == nil { | ||||
| // 		return | ||||
| // 	} | ||||
| // | ||||
| // 	var open = false // TODO get this from context | ||||
| // | ||||
| // 	// get the user from the database | ||||
| // 	u, err := store.GetUserLogin(c, tmpuser.Login) | ||||
| // 	if err != nil { | ||||
| // | ||||
| // 		// if self-registration is disabled we should | ||||
| // 		// return a notAuthorized error. the only exception | ||||
| // 		// is if no users exist yet in the system we'll proceed. | ||||
| // 		if !open { | ||||
| // 			logrus.Errorf("cannot register %s. registration closed", tmpuser.Login) | ||||
| // 			c.Redirect(303, "/login?error=access_denied") | ||||
| // 			return | ||||
| // 		} | ||||
| // | ||||
| // 		// create the user account | ||||
| // 		u = &model.User{} | ||||
| // 		u.Login = tmpuser.Login | ||||
| // 		u.Token = tmpuser.Token | ||||
| // 		u.Secret = tmpuser.Secret | ||||
| // 		u.Email = tmpuser.Email | ||||
| // 		u.Avatar = tmpuser.Avatar | ||||
| // 		u.Hash = crypto.Rand() | ||||
| // | ||||
| // 		// insert the user into the database | ||||
| // 		if err := store.CreateUser(c, u); err != nil { | ||||
| // 			logrus.Errorf("cannot insert %s. %s", u.Login, err) | ||||
| // 			c.Redirect(303, "/login?error=internal_error") | ||||
| // 			return | ||||
| // 		} | ||||
| // 	} | ||||
| // | ||||
| // 	// update the user meta data and authorization | ||||
| // 	// data and cache in the datastore. | ||||
| // 	u.Token = tmpuser.Token | ||||
| // 	u.Secret = tmpuser.Secret | ||||
| // 	u.Email = tmpuser.Email | ||||
| // 	u.Avatar = tmpuser.Avatar | ||||
| // | ||||
| // 	if err := store.UpdateUser(c, u); err != nil { | ||||
| // 		logrus.Errorf("cannot update %s. %s", u.Login, err) | ||||
| // 		c.Redirect(303, "/login?error=internal_error") | ||||
| // 		return | ||||
| // 	} | ||||
| // | ||||
| // 	exp := time.Now().Add(time.Hour * 72).Unix() | ||||
| // 	token := token.New(token.SessToken, u.Login) | ||||
| // 	tokenstr, err := token.SignExpires(u.Hash, exp) | ||||
| // 	if err != nil { | ||||
| // 		logrus.Errorf("cannot create token for %s. %s", u.Login, err) | ||||
| // 		c.Redirect(303, "/login?error=internal_error") | ||||
| // 		return | ||||
| // 	} | ||||
| // | ||||
| // 	httputil.SetCookie(c.Writer, c.Request, "user_sess", tokenstr) | ||||
| // 	redirect := httputil.GetCookie(c.Request, "user_last") | ||||
| // 	if len(redirect) == 0 { | ||||
| // 		redirect = "/" | ||||
| // 	} | ||||
| // 	c.Redirect(303, redirect) | ||||
| // | ||||
| // } | ||||
| // | ||||
| // func GetLogout(c *gin.Context) { | ||||
| // | ||||
| // 	httputil.DelCookie(c.Writer, c.Request, "user_sess") | ||||
| // 	httputil.DelCookie(c.Writer, c.Request, "user_last") | ||||
| // 	c.Redirect(303, "/login") | ||||
| // } | ||||
| // | ||||
| // func GetLoginToken(c *gin.Context) { | ||||
| // 	remote := remote.FromContext(c) | ||||
| // | ||||
| // 	in := &tokenPayload{} | ||||
| // 	err := c.Bind(in) | ||||
| // 	if err != nil { | ||||
| // 		c.AbortWithError(http.StatusBadRequest, err) | ||||
| // 		return | ||||
| // 	} | ||||
| // | ||||
| // 	login, err := remote.Auth(in.Access, in.Refresh) | ||||
| // 	if err != nil { | ||||
| // 		c.AbortWithError(http.StatusUnauthorized, err) | ||||
| // 		return | ||||
| // 	} | ||||
| // | ||||
| // 	user, err := store.GetUserLogin(c, login) | ||||
| // 	if err != nil { | ||||
| // 		c.AbortWithError(http.StatusNotFound, err) | ||||
| // 		return | ||||
| // 	} | ||||
| // | ||||
| // 	exp := time.Now().Add(time.Hour * 72).Unix() | ||||
| // 	token := token.New(token.SessToken, user.Login) | ||||
| // 	tokenstr, err := token.SignExpires(user.Hash, exp) | ||||
| // 	if err != nil { | ||||
| // 		c.AbortWithError(http.StatusInternalServerError, err) | ||||
| // 		return | ||||
| // 	} | ||||
| // | ||||
| // 	c.IndentedJSON(http.StatusOK, &tokenPayload{ | ||||
| // 		Access:  tokenstr, | ||||
| // 		Expires: exp - time.Now().Unix(), | ||||
| // 	}) | ||||
| // } | ||||
| // | ||||
| // type tokenPayload struct { | ||||
| // 	Access  string `json:"access_token,omitempty"` | ||||
| // 	Refresh string `json:"refresh_token,omitempty"` | ||||
| // 	Expires int64  `json:"expires_in,omitempty"` | ||||
| // } | ||||
| @@ -1,70 +0,0 @@ | ||||
| package checksum | ||||
|  | ||||
| import ( | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/sha512" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // Check is a calculates and verifies a file checksum. This supports the sha1, | ||||
| // sha256 and sha512 values. | ||||
| func Check(in, checksum string) bool { | ||||
| 	hash, size, _ := split(checksum) | ||||
|  | ||||
| 	// if a byte size is provided for the | ||||
| 	// Yaml file it must match. | ||||
| 	if size > 0 && int64(len(in)) != size { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	switch len(hash) { | ||||
| 	case 64: | ||||
| 		return sha256sum(in) == hash | ||||
| 	case 128: | ||||
| 		return sha512sum(in) == hash | ||||
| 	case 40: | ||||
| 		return sha1sum(in) == hash | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func sha1sum(in string) string { | ||||
| 	h := sha1.New() | ||||
| 	io.WriteString(h, in) | ||||
| 	return fmt.Sprintf("%x", h.Sum(nil)) | ||||
| } | ||||
|  | ||||
| func sha256sum(in string) string { | ||||
| 	h := sha256.New() | ||||
| 	io.WriteString(h, in) | ||||
| 	return fmt.Sprintf("%x", h.Sum(nil)) | ||||
| } | ||||
|  | ||||
| func sha512sum(in string) string { | ||||
| 	h := sha512.New() | ||||
| 	io.WriteString(h, in) | ||||
| 	return fmt.Sprintf("%x", h.Sum(nil)) | ||||
| } | ||||
|  | ||||
| func split(in string) (string, int64, string) { | ||||
| 	var hash string | ||||
| 	var name string | ||||
| 	var size int64 | ||||
|  | ||||
| 	// the checksum might be split into multiple | ||||
| 	// sections including the file size and name. | ||||
| 	switch strings.Count(in, " ") { | ||||
| 	case 1: | ||||
| 		fmt.Sscanf(in, "%s %s", &hash, &name) | ||||
| 	case 2: | ||||
| 		fmt.Sscanf(in, "%s %d %s", &hash, &size, &name) | ||||
| 	default: | ||||
| 		hash = in | ||||
| 	} | ||||
|  | ||||
| 	return hash, size, name | ||||
| } | ||||
| @@ -1,97 +0,0 @@ | ||||
| package checksum | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/franela/goblin" | ||||
| ) | ||||
|  | ||||
| func TestParse(t *testing.T) { | ||||
|  | ||||
| 	g := goblin.Goblin(t) | ||||
| 	g.Describe("Shasum", func() { | ||||
|  | ||||
| 		g.It("Should parse the shasum string", func() { | ||||
| 			hash, _, _ := split("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") | ||||
| 			g.Assert(hash).Equal("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should parse a two-part shasum string", func() { | ||||
| 			hash, _, name := split("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 .drone.yml") | ||||
| 			g.Assert(hash).Equal("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") | ||||
| 			g.Assert(name).Equal(".drone.yml") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should parse a three-part shasum string", func() { | ||||
| 			hash, size, name := split("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 42 .drone.yml") | ||||
| 			g.Assert(hash).Equal("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") | ||||
| 			g.Assert(name).Equal(".drone.yml") | ||||
| 			g.Assert(size).Equal(int64(42)) | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should calc a sha1 sum", func() { | ||||
| 			hash := sha1sum("foo\n") | ||||
| 			g.Assert(hash).Equal("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should calc a sha256 sum", func() { | ||||
| 			hash := sha256sum("foo\n") | ||||
| 			g.Assert(hash).Equal("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should calc a sha512 sum", func() { | ||||
| 			hash := sha512sum("foo\n") | ||||
| 			g.Assert(hash).Equal("0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should calc a sha1 sum", func() { | ||||
| 			hash := sha1sum("foo\n") | ||||
| 			g.Assert(hash).Equal("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should validate sha1 sum with file size", func() { | ||||
| 			ok := Check("foo\n", "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 4 -") | ||||
| 			g.Assert(ok).IsTrue() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should validate sha256 sum with file size", func() { | ||||
| 			ok := Check("foo\n", "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c 4 -") | ||||
| 			g.Assert(ok).IsTrue() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should validate sha512 sum with file size", func() { | ||||
| 			ok := Check("foo\n", "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6 4 -") | ||||
| 			g.Assert(ok).IsTrue() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should fail validation if incorrect sha1", func() { | ||||
| 			ok := Check("bar\n", "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 4 -") | ||||
| 			g.Assert(ok).IsFalse() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should fail validation if incorrect sha256", func() { | ||||
| 			ok := Check("bar\n", "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c 4 -") | ||||
| 			g.Assert(ok).IsFalse() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should fail validation if incorrect sha512", func() { | ||||
| 			ok := Check("bar\n", "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6 4 -") | ||||
| 			g.Assert(ok).IsFalse() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return false if file size mismatch", func() { | ||||
| 			ok := Check("foo\n", "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 12 -") | ||||
| 			g.Assert(ok).IsFalse() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return false if invalid checksum string", func() { | ||||
| 			ok := Check("foo\n", "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15234") | ||||
| 			g.Assert(ok).IsFalse() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return false if empty checksum", func() { | ||||
| 			ok := Check("foo\n", "") | ||||
| 			g.Assert(ok).IsFalse() | ||||
| 		}) | ||||
| 	}) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user