diff --git a/common/repo.go b/common/repo.go index a54faa5e..cc7d96a1 100644 --- a/common/repo.go +++ b/common/repo.go @@ -20,7 +20,7 @@ type Repo struct { Created int64 `json:"created_at"` Updated int64 `json:"updated_at"` - User *User `json:"user,omitempty"` + User *Owner `json:"user,omitempty"` Last *Build `json:"last_build,omitempty"` } @@ -32,6 +32,11 @@ type Keypair struct { Private string `json:"-"` } +// Owner represents the owner of a repository. +type Owner struct { + Login string `json:"login"` +} + // Subscriber represents a user's subscription // to a repository. This determines if the repository // is displayed on the user dashboard and in the user diff --git a/common/user.go b/common/user.go index 107c8562..c1af49c9 100644 --- a/common/user.go +++ b/common/user.go @@ -14,4 +14,8 @@ type User struct { // Repos contains a list of subscriptions // to repositories the user is watching. Repos map[string]struct{} `json:"-"` + + // Tokens contains a list of tokens for + // the user account. + Tokens map[string]struct{} `json:"-"` } diff --git a/datastore/bolt/build.go b/datastore/bolt/build.go index a2bce5f9..3339b7a6 100644 --- a/datastore/bolt/build.go +++ b/datastore/bolt/build.go @@ -35,9 +35,15 @@ func (db *DB) GetBuildList(repo string) ([]*common.Build, error) { // GetBuildLast gets the last executed build for the // named repository. func (db *DB) GetBuildLast(repo string) (*common.Build, error) { - // get the last build sequence number (stored in key in `bucketBuildSeq`) - // return that build - return nil, nil + key := []byte(repo) + build := &common.Build{} + err := db.View(func(t *bolt.Tx) error { + raw := t.Bucket(bucketBuildSeq).Get(key) + num := binary.LittleEndian.Uint32(raw) + key = []byte(repo + "/" + strconv.FormatUint(uint64(num), 10)) + return get(t, bucketBuild, key, build) + }) + return build, err } // GetBuildStatus gets the named build status for the @@ -78,17 +84,17 @@ func (db *DB) GetBuildStatusList(repo string, build int) ([]*common.Status, erro func (db *DB) InsertBuild(repo string, build *common.Build) error { key := []byte(repo) - return db.Update(func (t *bolt.Tx) error { + return db.Update(func(t *bolt.Tx) error { raw, err := raw(t, bucketBuildSeq, key) var next_seq uint32 switch err { - case ErrKeyNotFound: - next_seq = 1 - case nil: - next_seq = 1 + binary.LittleEndian.Uint32(raw) - default: - return err + case ErrKeyNotFound: + next_seq = 1 + case nil: + next_seq = 1 + binary.LittleEndian.Uint32(raw) + default: + return err } // covert our seqno to raw value diff --git a/datastore/bolt/build_test.go b/datastore/bolt/build_test.go index a0f3927b..2c53d693 100644 --- a/datastore/bolt/build_test.go +++ b/datastore/bolt/build_test.go @@ -42,5 +42,15 @@ func TestBuild(t *testing.T) { g.Assert(build.State).Equal("success") }) + g.It("Should get the latest builds", func() { + db.InsertBuild(repo, &common.Build{State: "success"}) + db.InsertBuild(repo, &common.Build{State: "success"}) + db.InsertBuild(repo, &common.Build{State: "pending"}) + + build, err := db.GetBuildLast(repo) + g.Assert(err).Equal(nil) + g.Assert(build.State).Equal("pending") + g.Assert(build.Number).Equal(3) + }) }) } diff --git a/datastore/bolt/user_test.go b/datastore/bolt/user_test.go index 6064a09a..f1ca8afa 100644 --- a/datastore/bolt/user_test.go +++ b/datastore/bolt/user_test.go @@ -73,7 +73,13 @@ func TestUser(t *testing.T) { g.Assert(err).Equal(ErrKeyNotFound) }) - g.It("Should list") + g.It("Should list", func() { + db.InsertUser(&common.User{Login: "bert"}) + db.InsertUser(&common.User{Login: "ernie"}) + users, err := db.GetUserList() + g.Assert(err).Equal(nil) + g.Assert(len(users)).Equal(2) + }) g.It("Should count", func() { db.InsertUser(&common.User{Login: "bert"}) diff --git a/datastore/bolt/util.go b/datastore/bolt/util.go index 1b3c8ae3..d373bbfa 100644 --- a/datastore/bolt/util.go +++ b/datastore/bolt/util.go @@ -1,8 +1,8 @@ package bolt import ( - "github.com/youtube/vitess/go/bson" "github.com/boltdb/bolt" + "github.com/youtube/vitess/go/bson" ) func encode(v interface{}) ([]byte, error) { @@ -35,11 +35,7 @@ func update(t *bolt.Tx, bucket, key []byte, v interface{}) error { t.Rollback() return err } - err = t.Bucket(bucket).Put(key, raw) - if err != nil { - return err - } - return nil + return t.Bucket(bucket).Put(key, raw) } func insert(t *bolt.Tx, bucket, key []byte, v interface{}) error { @@ -53,17 +49,9 @@ func insert(t *bolt.Tx, bucket, key []byte, v interface{}) error { if t.Bucket(bucket).Get(key) != nil { return ErrKeyExists } - err = t.Bucket(bucket).Put(key, raw) - if err != nil { - return err - } - return nil + return t.Bucket(bucket).Put(key, raw) } func delete(t *bolt.Tx, bucket, key []byte) error { - err := t.Bucket(bucket).Delete(key) - if err != nil { - return err - } - return nil + return t.Bucket(bucket).Delete(key) } diff --git a/drone.go b/drone.go index 063d2232..442289d6 100644 --- a/drone.go +++ b/drone.go @@ -114,7 +114,7 @@ func main() { logs.Use(server.CheckPull()) logs.Use(server.CheckPush()) - logs.GET("", server.GetLogs) + logs.GET("", server.GetTaskLogs) } status := api.Group("/status/:owner/:name/:number") diff --git a/server/login.go b/server/login.go index f572c9d7..ec73b782 100644 --- a/server/login.go +++ b/server/login.go @@ -166,7 +166,7 @@ func getLoginBasic(c *gin.Context) { var ( remote = ToRemote(c) username = c.Request.FormValue("username") - password = c.Request.FormValue("username") + password = c.Request.FormValue("password") ) // get user account diff --git a/server/logs.go b/server/logs.go deleted file mode 100644 index 459182d7..00000000 --- a/server/logs.go +++ /dev/null @@ -1,27 +0,0 @@ -package server - -import ( - "strconv" - - "github.com/gin-gonic/gin" -) - -// GetLogs accepts a request to retrieve logs from the -// datastore for the given repository, build and task -// number. -// -// GET /api/logs/:owner/:name/:number/:task -// -func GetLogs(c *gin.Context) { - ds := ToDatastore(c) - repo := ToRepo(c) - build, _ := strconv.Atoi(c.Params.ByName("number")) - task, _ := strconv.Atoi(c.Params.ByName("task")) - - logs, err := ds.GetTaskLogs(repo.FullName, build, task) - if err != nil { - c.Fail(404, err) - } else { - c.Writer.Write(logs) - } -} diff --git a/server/repos.go b/server/repos.go index 61032fbd..7af11af4 100644 --- a/server/repos.go +++ b/server/repos.go @@ -193,7 +193,7 @@ func PostRepo(c *gin.Context) { // set the repository owner to the // currently authenticated user. - r.User = user + r.User = &common.Owner{Login: user.Login} // generate an RSA key and add to the repo key, err := sshutil.GeneratePrivateKey() diff --git a/server/tasks.go b/server/tasks.go index 3491ec0e..789904ad 100644 --- a/server/tasks.go +++ b/server/tasks.go @@ -44,3 +44,23 @@ func GetTasks(c *gin.Context) { c.JSON(200, tasks) } } + +// GetTaskLogs accepts a request to retrieve logs from the +// datastore for the given repository, build and task +// number. +// +// GET /api/logs/:owner/:name/:number/:task +// +func GetTaskLogs(c *gin.Context) { + ds := ToDatastore(c) + repo := ToRepo(c) + build, _ := strconv.Atoi(c.Params.ByName("number")) + task, _ := strconv.Atoi(c.Params.ByName("task")) + + logs, err := ds.GetTaskLogs(repo.FullName, build, task) + if err != nil { + c.Fail(404, err) + } else { + c.Writer.Write(logs) + } +} diff --git a/server/token.go b/server/token.go new file mode 100644 index 00000000..60672b86 --- /dev/null +++ b/server/token.go @@ -0,0 +1,40 @@ +package server + +import ( + "github.com/gin-gonic/gin" + + // "github.com/drone/drone/common" +) + +// POST /api/user/tokens +func PostToken(c *gin.Context) { + // 1. generate a unique, random password + // 2. take a hash of the password, and store in the database + // 3. return the random password to the UI and instruct the user to copy it +} + +// DELETE /api/user/tokens/:sha +func DelToken(c *gin.Context) { + store := ToDatastore(c) + user := ToUser(c) + hash := c.Params.ByName("hash") + token, err := store.GetToken(hash) + if err != nil { + c.Fail(404, err) + } + err = store.DeleteToken(token) + if err != nil { + c.Fail(400, err) + } + + // TODO(bradrydzewski) this should be encapsulated + // in our database code, since this feels like a + // database-specific implementation. + delete(user.Tokens, token.Sha) + err = store.UpdateUser(user) + if err != nil { + c.Fail(400, err) + } else { + c.Writer.WriteHeader(200) + } +} diff --git a/server/user.go b/server/user.go index 5a0fbda5..1888b481 100644 --- a/server/user.go +++ b/server/user.go @@ -57,3 +57,20 @@ func GetUserRepos(c *gin.Context) { c.JSON(200, &repos) } } + +// GetUserTokens accepts a request to get the currently +// authenticated user's token list from the datastore, +// encoded and returned in JSON format. +// +// GET /api/user/tokens +// +func GetUserTokens(c *gin.Context) { + // ds := ToDatastore(c) + // me := ToUser(c) + // tokens, err := ds.GetUserTokens(me.Login) + // if err != nil { + // c.Fail(400, err) + // } else { + // c.JSON(200, &repos) + // } +}