diff --git a/datastore/bolt/token.go b/datastore/bolt/token.go index 1b28728f..a060b53e 100644 --- a/datastore/bolt/token.go +++ b/datastore/bolt/token.go @@ -1,6 +1,8 @@ package bolt import ( + "bytes" + "github.com/boltdb/bolt" "github.com/drone/drone/common" ) @@ -22,16 +24,44 @@ func (db *DB) GetToken(user, label string) (*common.Token, error) { func (db *DB) InsertToken(token *common.Token) error { key := []byte(token.Login + "/" + token.Label) return db.Update(func(t *bolt.Tx) error { + // gets an index + var idx [][]byte + err := get(t, bucketUserTokens, []byte(token.Login), &idx) + if err != nil && err != ErrKeyNotFound { + return err + } + // pushes to the index + idx = append(idx, key) + err = update(t, bucketUserTokens, []byte(token.Login), &idx) + if err != nil { + return err + } + return insert(t, bucketTokens, key, token) }) - // TODO(bradrydzewski) add token to users_token index } // DeleteUser deletes the token. func (db *DB) DeleteToken(token *common.Token) error { key := []byte(token.Login + "/" + token.Label) return db.Update(func(t *bolt.Tx) error { + // gets an index + var idx [][]byte + err := get(t, bucketUserTokens, []byte(token.Login), &idx) + if err != nil && err != ErrKeyNotFound { + return err + } + // pushes to the index + for i, val := range idx { + if bytes.Equal(val, key) { + idx = idx[:i+copy(idx[i:], idx[i+1:])] + break + } + } + err = update(t, bucketUserTokens, []byte(token.Login), &idx) + if err != nil { + return err + } return delete(t, bucketUser, key) }) - // TODO(bradrydzewski) remove token from users_token index } diff --git a/datastore/bolt/token_test.go b/datastore/bolt/token_test.go index 8fd4c8be..8afb4ee5 100644 --- a/datastore/bolt/token_test.go +++ b/datastore/bolt/token_test.go @@ -1,17 +1,39 @@ package bolt import ( + "os" "testing" + "github.com/drone/drone/common" . "github.com/franela/goblin" ) func TestToken(t *testing.T) { g := Goblin(t) g.Describe("Tokens", func() { + var db *DB // temporary database - g.It("Should find by sha") - g.It("Should list for user") + // create a new database before each unit + // test and destroy afterwards. + g.BeforeEach(func() { + db = Must("/tmp/drone.test.db") + }) + g.AfterEach(func() { + os.Remove(db.Path()) + }) + + g.It("Should find by label") + g.It("Should list for user", func() { + db.InsertUser(&common.User{Login: "octocat"}) + err1 := db.InsertToken(&common.Token{Login: "octocat", Label: "gist"}) + err2 := db.InsertToken(&common.Token{Login: "octocat", Label: "github"}) + g.Assert(err1).Equal(nil) + g.Assert(err2).Equal(nil) + + list, err := db.GetUserTokens("octocat") + g.Assert(err).Equal(nil) + g.Assert(len(list)).Equal(2) + }) g.It("Should delete") g.It("Should insert") g.It("Should not insert if exists") diff --git a/datastore/bolt/user.go b/datastore/bolt/user.go index 89c08b65..aebe113d 100644 --- a/datastore/bolt/user.go +++ b/datastore/bolt/user.go @@ -3,8 +3,8 @@ package bolt import ( "time" - "github.com/drone/drone/common" "github.com/boltdb/bolt" + "github.com/drone/drone/common" ) // GetUser gets a user by user login. @@ -12,7 +12,7 @@ func (db *DB) GetUser(login string) (*common.User, error) { user := &common.User{} key := []byte(login) - err := db.View(func (t *bolt.Tx) error { + err := db.View(func(t *bolt.Tx) error { return get(t, bucketUser, key, user) }) @@ -31,26 +31,24 @@ func (db *DB) GetUserTokens(login string) ([]*common.Token, error) { // get the index of user tokens and unmarshal // to a string array. - key := []byte(login) - raw := t.Bucket(bucketUserTokens).Get(key) - keys := [][]byte{} - err = decode(raw, &keys) - if err != nil { - return tokens, err + var keys [][]byte + err = get(t, bucketUserTokens, []byte(login), &keys) + if err != nil && err != ErrKeyNotFound { + return nil, err } // for each item in the index, get the repository // and append to the array for _, key := range keys { token := &common.Token{} - raw = t.Bucket(bucketTokens).Get(key) + raw := t.Bucket(bucketTokens).Get(key) err = decode(raw, token) if err != nil { - break + return nil, err } tokens = append(tokens, token) } - return tokens, err + return tokens, nil } // GetUserRepos gets a list of repositories for the @@ -126,7 +124,7 @@ func (db *DB) UpdateUser(user *common.User) error { key := []byte(user.Login) user.Updated = time.Now().UTC().Unix() - return db.Update(func (t *bolt.Tx) error { + return db.Update(func(t *bolt.Tx) error { return update(t, bucketUser, key, user) }) } @@ -138,7 +136,7 @@ func (db *DB) InsertUser(user *common.User) error { user.Created = time.Now().UTC().Unix() user.Updated = time.Now().UTC().Unix() - return db.Update(func (t *bolt.Tx) error { + return db.Update(func(t *bolt.Tx) error { return insert(t, bucketUser, key, user) }) } @@ -149,7 +147,7 @@ func (db *DB) DeleteUser(user *common.User) error { // TODO(bradrydzewski) delete user subscriptions // TODO(bradrydzewski) delete user tokens - return db.Update(func (t *bolt.Tx) error { + return db.Update(func(t *bolt.Tx) error { return delete(t, bucketUser, key) }) } diff --git a/drone.go b/drone.go index 442289d6..a97fd653 100644 --- a/drone.go +++ b/drone.go @@ -43,6 +43,9 @@ func main() { user.GET("", server.GetUserCurr) user.PUT("", server.PutUserCurr) user.GET("/repos", server.GetUserRepos) + user.GET("/tokens", server.GetUserTokens) + user.POST("/tokens", server.PostToken) + user.DELETE("/tokens", server.DelToken) } users := api.Group("/users") diff --git a/server/token.go b/server/token.go index 23bfe2c7..33cfae5e 100644 --- a/server/token.go +++ b/server/token.go @@ -2,19 +2,26 @@ package server import ( "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" "github.com/drone/drone/common" ) -// POST /api/user/tokens/:label +// POST /api/user/tokens func PostToken(c *gin.Context) { store := ToDatastore(c) sess := ToSession(c) user := ToUser(c) - label := c.Params.ByName("label") + + in := &common.Token{} + if !c.BindWith(in, binding.JSON) { + return + } token := &common.Token{} - token.Label = label + token.Label = in.Label + token.Repos = in.Repos + token.Scopes = in.Scopes token.Login = user.Login token.Kind = common.TokenUser @@ -30,11 +37,12 @@ func PostToken(c *gin.Context) { c.String(200, jwt) } -// DELETE /api/user/tokens/:label +// DELETE /api/user/tokens func DelToken(c *gin.Context) { store := ToDatastore(c) user := ToUser(c) label := c.Params.ByName("label") + token, err := store.GetToken(user.Login, label) if err != nil { c.Fail(404, err) @@ -43,4 +51,6 @@ func DelToken(c *gin.Context) { if err != nil { c.Fail(400, err) } + + c.Writer.WriteHeader(200) }