storing user repos index inside users object, for now

This commit is contained in:
Brad Rydzewski 2015-04-08 22:18:25 -07:00
parent fac0582b57
commit 950e4f4090
10 changed files with 106 additions and 119 deletions

View file

@ -37,8 +37,6 @@ type Keypair struct {
// is displayed on the user dashboard and in the user // is displayed on the user dashboard and in the user
// event feed. // event feed.
type Subscriber struct { type Subscriber struct {
Login string `json:"login,omitempty"`
// Determines if notifications should be // Determines if notifications should be
// received from this repository. // received from this repository.
Subscribed bool `json:"subscribed"` Subscribed bool `json:"subscribed"`

View file

@ -10,4 +10,8 @@ type User struct {
Admin bool `json:"admin,omitempty"` Admin bool `json:"admin,omitempty"`
Created int64 `json:"created_at,omitempty"` Created int64 `json:"created_at,omitempty"`
Updated int64 `json:"updated_at,omitempty"` Updated int64 `json:"updated_at,omitempty"`
// Repos contains a list of subscriptions
// to repositories the user is watching.
Repos map[string]struct{} `json:"-"`
} }

View file

@ -84,25 +84,25 @@ func (db *DB) DeleteRepo(repo *common.Repo) error {
return t.Commit() return t.Commit()
} }
// GetSubscriber gets the subscriber by login for the // // GetSubscriber gets the subscriber by login for the
// named repository. // // named repository.
func (db *DB) GetSubscriber(repo string, login string) (*common.Subscriber, error) { // func (db *DB) GetSubscriber(repo string, login string) (*common.Subscriber, error) {
sub := &common.Subscriber{} // sub := &common.Subscriber{}
key := []byte(login + "/" + repo) // key := []byte(login + "/" + repo)
err := get(db, bucketUserRepos, key, sub) // err := get(db, bucketUserRepos, key, sub)
return sub, err // return sub, err
} // }
// InsertSubscriber inserts a subscriber for the named // // InsertSubscriber inserts a subscriber for the named
// repository. // // repository.
func (db *DB) InsertSubscriber(repo string, sub *common.Subscriber) error { // func (db *DB) InsertSubscriber(repo string, sub *common.Subscriber) error {
key := []byte(sub.Login + "/" + repo) // key := []byte(sub.Login + "/" + repo)
return insert(db, bucketUserRepos, key, sub) // return insert(db, bucketUserRepos, key, sub)
} // }
// DeleteSubscriber removes the subscriber by login for the // // DeleteSubscriber removes the subscriber by login for the
// named repository. // // named repository.
func (db *DB) DeleteSubscriber(repo string, sub *common.Subscriber) error { // func (db *DB) DeleteSubscriber(repo string, sub *common.Subscriber) error {
key := []byte(sub.Login + "/" + repo) // key := []byte(sub.Login + "/" + repo)
return delete(db, bucketUserRepos, key) // return delete(db, bucketUserRepos, key)
} // }

View file

@ -57,22 +57,27 @@ func (db *DB) GetUserRepos(login string) ([]*common.Repo, error) {
} }
defer t.Rollback() defer t.Rollback()
repos := []*common.Repo{} repos := []*common.Repo{}
user := &common.User{}
// get the index of user repos and unmarshal // get the user struct from the database
// to a string array.
key := []byte(login) key := []byte(login)
raw := t.Bucket(bucketUserRepos).Get(key) raw := t.Bucket(bucketUser).Get(key)
keys := [][]byte{} err = decode(raw, user)
err = decode(raw, &keys)
if err != nil { if err != nil {
return repos, err return nil, err
} }
// for each item in the index, get the repository // for each item in the index, get the repository
// and append to the array // and append to the array
for _, key := range keys { for repoName, _ := range user.Repos {
repo := &common.Repo{} repo := &common.Repo{}
key = []byte(repoName)
raw = t.Bucket(bucketRepo).Get(key) raw = t.Bucket(bucketRepo).Get(key)
if raw == nil {
// this will happen when the repository has been deleted
// TODO we should probably upate the index in this case.
continue
}
err = decode(raw, repo) err = decode(raw, repo)
if err != nil { if err != nil {
break break

View file

@ -42,17 +42,17 @@ type Datastore interface {
// DeleteUser deletes the token. // DeleteUser deletes the token.
DeleteToken(*common.Token) error DeleteToken(*common.Token) error
// GetSubscriber gets the subscriber by login for the // // GetSubscriber gets the subscriber by login for the
// named repository. // // named repository.
GetSubscriber(string, string) (*common.Subscriber, error) // GetSubscriber(string, string) (*common.Subscriber, error)
// InsertSubscriber inserts a subscriber for the named // // InsertSubscriber inserts a subscriber for the named
// repository. // // repository.
InsertSubscriber(string, *common.Subscriber) error // InsertSubscriber(string, *common.Subscriber) error
// DeleteSubscriber removes the subscriber by login for the // // DeleteSubscriber removes the subscriber by login for the
// named repository. // // named repository.
DeleteSubscriber(string, *common.Subscriber) error // DeleteSubscriber(string, *common.Subscriber) error
// GetRepo gets the repository by name. // GetRepo gets the repository by name.
GetRepo(string) (*common.Repo, error) GetRepo(string) (*common.Repo, error)

View file

@ -79,7 +79,6 @@ func main() {
subscribers.Use(server.SetPerm()) subscribers.Use(server.SetPerm())
subscribers.Use(server.CheckPull()) subscribers.Use(server.CheckPull())
subscribers.GET("", server.GetSubscribers)
subscribers.POST("", server.Subscribe) subscribers.POST("", server.Subscribe)
subscribers.DELETE("", server.Unsubscribe) subscribers.DELETE("", server.Unsubscribe)
} }

View file

@ -60,9 +60,15 @@ func GetRepo(c *gin.Context) {
} }
// if the user is authenticated, we should display // if the user is authenticated, we should display
// if she is watching the current repository. // if she is watching the current repository.
if user != nil { if user == nil {
data.Watch, _ = store.GetSubscriber(repo.FullName, user.Login) c.JSON(200, data)
return
} }
// check to see if the user is subscribing to the repo
_, ok := user.Repos[repo.FullName]
data.Watch = &common.Subscriber{Subscribed: ok}
c.JSON(200, data) c.JSON(200, data)
} }
@ -75,8 +81,8 @@ func GetRepo(c *gin.Context) {
func PutRepo(c *gin.Context) { func PutRepo(c *gin.Context) {
store := ToDatastore(c) store := ToDatastore(c)
perm := ToPerm(c) perm := ToPerm(c)
u := ToUser(c) user := ToUser(c)
r := ToRepo(c) repo := ToRepo(c)
in := &repoReq{} in := &repoReq{}
if !c.BindWith(in, binding.JSON) { if !c.BindWith(in, binding.JSON) {
@ -84,37 +90,41 @@ func PutRepo(c *gin.Context) {
} }
if in.Params != nil { if in.Params != nil {
err := store.UpsertRepoParams(r.FullName, *in.Params) err := store.UpsertRepoParams(repo.FullName, *in.Params)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
return return
} }
} }
if in.Disabled != nil { if in.Disabled != nil {
r.Disabled = *in.Disabled repo.Disabled = *in.Disabled
} }
if in.DisablePR != nil { if in.DisablePR != nil {
r.DisablePR = *in.DisablePR repo.DisablePR = *in.DisablePR
} }
if in.DisableTag != nil { if in.DisableTag != nil {
r.DisableTag = *in.DisableTag repo.DisableTag = *in.DisableTag
} }
if in.Trusted != nil && u.Admin { if in.Trusted != nil && user.Admin {
r.Trusted = *in.Trusted repo.Trusted = *in.Trusted
} }
if in.Timeout != nil && u.Admin { if in.Timeout != nil && user.Admin {
r.Timeout = *in.Timeout repo.Timeout = *in.Timeout
} }
err := store.UpdateRepo(r) err := store.UpdateRepo(repo)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
return return
} }
data := repoResp{r, perm, nil, nil} data := repoResp{repo, perm, nil, nil}
data.Params, _ = store.GetRepoParams(r.FullName) data.Params, _ = store.GetRepoParams(repo.FullName)
data.Watch, _ = store.GetSubscriber(r.FullName, u.Login)
// check to see if the user is subscribing to the repo
_, ok := user.Repos[repo.FullName]
data.Watch = &common.Subscriber{Subscribed: ok}
c.JSON(200, data) c.JSON(200, data)
} }
@ -194,30 +204,38 @@ func PostRepo(c *gin.Context) {
keypair := &common.Keypair{} keypair := &common.Keypair{}
keypair.Public = sshutil.MarshalPublicKey(&key.PublicKey) keypair.Public = sshutil.MarshalPublicKey(&key.PublicKey)
keypair.Private = sshutil.MarshalPrivateKey(key) keypair.Private = sshutil.MarshalPrivateKey(key)
// activate the repository before we make any
// local changes to the database.
err = remote.Activate(user, r, keypair, link)
if err != nil {
c.Fail(500, err)
return
}
// persist the repository
err = store.InsertRepo(user, r)
if err != nil {
c.Fail(500, err)
return
}
// persisty the repository key pair
err = store.UpsertRepoKeys(r.FullName, keypair) err = store.UpsertRepoKeys(r.FullName, keypair)
if err != nil { if err != nil {
c.Fail(500, err) c.Fail(500, err)
return return
} }
// store the repository and the users' permissions // subscribe the user to the repository
// in the datastore. // if this fails we'll ignore, since the user
err = store.InsertRepo(user, r) // can just go click the "watch" button in the
if err != nil { // user interface.
c.Fail(500, err) if user.Repos == nil {
return user.Repos = map[string]struct{}{}
}
err = store.InsertSubscriber(r.FullName, &common.Subscriber{Subscribed: true})
if err != nil {
c.Fail(500, err)
return
}
err = remote.Activate(user, r, keypair, link)
if err != nil {
c.Fail(500, err)
return
} }
user.Repos[r.FullName] = struct{}{}
store.UpdateUser(user)
c.JSON(200, r) c.JSON(200, r)
} }

View file

@ -24,7 +24,7 @@ type session struct {
func New(s *settings.Session) Session { func New(s *settings.Session) Session {
// TODO (bradrydzewski) hook up the Session.Expires // TODO (bradrydzewski) hook up the Session.Expires
secret := s.Secret secret := []byte(s.Secret)
expire := time.Hour * 72 expire := time.Hour * 72
if len(secret) == 0 { if len(secret) == 0 {
securecookie.GenerateRandomKey(32) securecookie.GenerateRandomKey(32)

View file

@ -6,41 +6,6 @@ import (
"github.com/drone/drone/common" "github.com/drone/drone/common"
) )
// GetSubscriber accepts a request to retrieve a repository
// subscriber from the datastore for the given repository by
// user Login.
//
// GET /api/subscribers/:owner/:name/:login
//
func GetSubscriber(c *gin.Context) {
store := ToDatastore(c)
repo := ToRepo(c)
login := c.Params.ByName("login")
subsc, err := store.GetSubscriber(repo.FullName, login)
if err != nil {
c.Fail(404, err)
} else {
c.JSON(200, subsc)
}
}
// GetSubscribers accepts a request to retrieve a repository
// watchers from the datastore for the given repository.
//
// GET /api/subscribers/:owner/:name
//
func GetSubscribers(c *gin.Context) {
// store := ToDatastore(c)
// repo := ToRepo(c)
// subs, err := store.GetSubscribers(repo.FullName)
// if err != nil {
// c.Fail(404, err)
// } else {
// c.JSON(200, subs)
// }
c.Writer.WriteHeader(501)
}
// Unubscribe accapets a request to unsubscribe the // Unubscribe accapets a request to unsubscribe the
// currently authenticated user to the repository. // currently authenticated user to the repository.
// //
@ -50,11 +15,9 @@ func Unsubscribe(c *gin.Context) {
store := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
user := ToUser(c) user := ToUser(c)
sub, err := store.GetSubscriber(repo.FullName, user.Login)
if err != nil { delete(user.Repos, repo.FullName)
c.Fail(404, err) err := store.UpdateUser(user)
}
err = store.DeleteSubscriber(repo.FullName, sub)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
@ -71,14 +34,14 @@ func Subscribe(c *gin.Context) {
store := ToDatastore(c) store := ToDatastore(c)
repo := ToRepo(c) repo := ToRepo(c)
user := ToUser(c) user := ToUser(c)
subscriber := &common.Subscriber{ if user.Repos == nil {
Login: user.Login, user.Repos = map[string]struct{}{}
Subscribed: true,
} }
err := store.InsertSubscriber(repo.FullName, subscriber) user.Repos[repo.FullName] = struct{}{}
err := store.UpdateUser(user)
if err != nil { if err != nil {
c.Fail(400, err) c.Fail(400, err)
} else { } else {
c.JSON(200, subscriber) c.JSON(200, &common.Subscriber{Subscribed: true})
} }
} }

View file

@ -73,7 +73,7 @@ type Server struct {
// used to generate, validate and expire authentication // used to generate, validate and expire authentication
// sessions. // sessions.
type Session struct { type Session struct {
Secret []byte `toml:"secret"` Secret string `toml:"secret"`
Expires int64 `toml:"expires"` Expires int64 `toml:"expires"`
} }