Merge pull request #604 from bradrydzewski/master

added token to post-commit hooks
This commit is contained in:
Brad Rydzewski 2014-10-22 00:31:03 -07:00
commit 5fe126ec83
12 changed files with 62 additions and 13 deletions

View file

@ -88,5 +88,5 @@ rpm:
# DRONE_STAGING_USER -- the username used to login
# DRONE_STAGING_KEY -- the identity file path (~/.ssh/id_rsa)
deploy:
scp -i $$DRONE_STAGING_KEY debian/drone.deb $$DRONE_STAGING_USER@$$DRONE_STAGING_HOST:/tmp
scp -i $$DRONE_STAGING_KEY packaging/output/drone.deb $$DRONE_STAGING_USER@$$DRONE_STAGING_HOST:/tmp
ssh -i $$DRONE_STAGING_KEY $$DRONE_STAGING_USER@$$DRONE_STAGING_HOST -- dpkg -i /tmp/drone.deb

View file

@ -201,3 +201,11 @@ Authorization callback URL:
```
http://localhost:8000/api/auth/github.com
```
## Build Configuration
You will need to include a `.drone.yml` file in the root of your repository in order to
configure a build. I'm still working on updated documentation, so in the meantime please refer
to the `0.2` README to learn more about the `.drone.yml` format:
https://github.com/drone/drone/blob/v0.2.1/README.md#builds

View file

@ -135,7 +135,7 @@ func (r *Gitlab) Activate(user *model.User, repo *model.Repo, link string) error
// append the repo owner / name to the hook url since gitlab
// doesn't send this detail in the post-commit hook
link += "?owner=" + repo.Owner + "&name=" + repo.Name
link += "&owner=" + repo.Owner + "&name=" + repo.Name
// add the hook
return client.AddProjectHook(path, link, true, false, true)

View file

@ -37,6 +37,7 @@ func Connect(driver, datasource string) (*sql.DB, error) {
migration.DefaultSetVersion = migrate.SetVersion
var migrations = []migration.Migrator{
migrate.Setup,
migrate.Migrate_20142110,
}
return migration.Open(driver, datasource, migrations)
}

View file

@ -23,6 +23,22 @@ func Setup(tx migration.LimitedTx) error {
return nil
}
// Migrate_20142110 is a database migration on Oct-10 2014.
func Migrate_20142110(tx migration.LimitedTx) error {
var stmts = []string{
commitRepoIndex, // index the commit table repo_id column
repoTokenColumn, // add the repo token column
repoTokenUpdate, // update the repo token column to empty string
}
for _, stmt := range stmts {
_, err := tx.Exec(transform(stmt))
if err != nil {
return err
}
}
return nil
}
var userTable = `
CREATE TABLE IF NOT EXISTS users (
user_id INTEGER PRIMARY KEY AUTOINCREMENT
@ -86,6 +102,14 @@ CREATE TABLE IF NOT EXISTS repos (
);
`
var repoTokenColumn = `
ALTER TABLE repos ADD COLUMN repo_token VARCHAR(40)
`
var repoTokenUpdate = `
UPDATE repos SET repo_token = '';
`
var commitTable = `
CREATE TABLE IF NOT EXISTS commits (
commit_id INTEGER PRIMARY KEY AUTOINCREMENT
@ -108,6 +132,10 @@ CREATE TABLE IF NOT EXISTS commits (
);
`
var commitRepoIndex = `
CREATE INDEX commit_repo_id_idx ON commits (repo_id);
`
var blobTable = `
CREATE TABLE IF NOT EXISTS blobs (
blob_id INTEGER PRIMARY KEY AUTOINCREMENT

View file

@ -1,6 +1,7 @@
package handler
import (
"log"
"net/http"
"strings"
@ -24,6 +25,7 @@ import (
func PostHook(c web.C, w http.ResponseWriter, r *http.Request) {
var ctx = context.FromC(c)
var host = c.URLParams["host"]
var token = r.FormValue("token")
var remote = remote.Lookup(host)
if remote == nil {
w.WriteHeader(http.StatusNotFound)
@ -52,6 +54,14 @@ func PostHook(c web.C, w http.ResponseWriter, r *http.Request) {
return
}
// each hook contains a token to verify the sender. If the token
// is not provided or does not match, exit
if len(repo.Token) == 0 || repo.Token != token {
log.Printf("Rejected post commit hook for %s. Token mismatch\n", repo.Name)
w.WriteHeader(http.StatusUnauthorized)
return
}
if repo.Active == false ||
(repo.PostCommit == false && len(hook.PullRequest) == 0) ||
(repo.PullRequest == false && len(hook.PullRequest) != 0) {

View file

@ -80,6 +80,7 @@ func PostRepo(c web.C, w http.ResponseWriter, r *http.Request) {
repo.PostCommit = true
repo.UserID = user.ID
repo.Timeout = 3600 // default to 1 hour
repo.Token = model.GenerateToken()
// generates the rsa key
key, err := sshutil.GeneratePrivateKey()
@ -98,7 +99,7 @@ func PostRepo(c web.C, w http.ResponseWriter, r *http.Request) {
// setup the post-commit hook with the remote system and
// if necessary, register the public key
var hook = fmt.Sprintf("%s/api/hook/%s", httputil.GetURL(r), repo.Remote)
var hook = fmt.Sprintf("%s/api/hook/%s?token=%s", httputil.GetURL(r), repo.Remote, repo.Token)
if err := remote.Activate(user, repo, hook); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return

View file

@ -26,7 +26,7 @@ type Commit struct {
// SetAuthor sets the author's email address and calculate the Gravatar hash.
func (c *Commit) SetAuthor(email string) {
c.Author = email
c.Gravatar = createGravatar(email)
c.Gravatar = CreateGravatar(email)
}
// Returns the Short (--short) Commit Hash.

View file

@ -18,6 +18,7 @@ type RepoParams map[string]string
type Repo struct {
ID int64 `meddler:"repo_id,pk" json:"-"`
UserID int64 `meddler:"user_id" json:"-"`
Token string `meddler:"repo_token" json:"-"`
Remote string `meddler:"repo_remote" json:"remote"`
Host string `meddler:"repo_host" json:"host"`
Owner string `meddler:"repo_owner" json:"owner"`

View file

@ -24,7 +24,7 @@ type User struct {
func NewUser(remote, login, email string) *User {
user := User{}
user.Token = generateToken()
user.Token = GenerateToken()
user.Login = login
user.Remote = remote
user.Active = true
@ -35,7 +35,7 @@ func NewUser(remote, login, email string) *User {
// SetEmail sets the email address and calculate the Gravatar hash.
func (u *User) SetEmail(email string) {
u.Email = email
u.Gravatar = createGravatar(email)
u.Gravatar = CreateGravatar(email)
}
func (u *User) IsStale() bool {

View file

@ -14,9 +14,9 @@ var chars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567
// default token length
var length = 40
// generateToken generates random strings good for use in URIs to
// GenerateToken generates random strings good for use in URIs to
// identify unique objects.
func generateToken() string {
func GenerateToken() string {
b := make([]byte, length)
r := make([]byte, length+(length/4)) // storage for random bytes.
clen := byte(len(chars))
@ -40,7 +40,7 @@ func generateToken() string {
// helper function to create a Gravatar Hash
// for the given Email address.
func createGravatar(email string) string {
func CreateGravatar(email string) string {
email = strings.ToLower(strings.TrimSpace(email))
hash := md5.New()
hash.Write([]byte(email))

View file

@ -4,15 +4,15 @@ import (
"testing"
)
func Test_createGravatar(t *testing.T) {
var got, want = createGravatar("dr_cooper@caltech.edu"), "2b77ba83e2216ddcd11fe8c24b70c2a3"
func Test_CreateGravatar(t *testing.T) {
var got, want = CreateGravatar("dr_cooper@caltech.edu"), "2b77ba83e2216ddcd11fe8c24b70c2a3"
if got != want {
t.Errorf("Got gravatar hash %s, want %s", got, want)
}
}
func Test_generateToken(t *testing.T) {
token := generateToken()
func Test_GenerateToken(t *testing.T) {
token := GenerateToken()
if len(token) != length {
t.Errorf("Want token length %d, got %d", length, len(token))
}