diff --git a/client_store.go b/client_store.go new file mode 100644 index 0000000..b651c6f --- /dev/null +++ b/client_store.go @@ -0,0 +1,126 @@ +package mongo + +import ( + "github.com/globalsign/mgo" + "gopkg.in/oauth2.v3" + "gopkg.in/oauth2.v3/models" +) + +// ClientConfig client configuration parameters +type ClientConfig struct { + // store clients data collection name(The default is oauth2_clients) + ClientsCName string +} + +// NewDefaultClientConfig create a default client configuration +func NewDefaultClientConfig() *ClientConfig { + return &ClientConfig{ + ClientsCName: "oauth2_clients", + } +} + +// NewClientStore create a client store instance based on mongodb +func NewClientStore(cfg *Config, ccfgs ...*ClientConfig) *ClientStore { + session, err := mgo.Dial(cfg.URL) + if err != nil { + panic(err) + } + + return NewClientStoreWithSession(session, cfg.DB, ccfgs...) +} + +// NewClientStoreWithSession create a client store instance based on mongodb +func NewClientStoreWithSession(session *mgo.Session, dbName string, ccfgs ...*ClientConfig) *ClientStore { + cs := &ClientStore{ + dbName: dbName, + session: session, + ccfg: NewDefaultClientConfig(), + } + if len(ccfgs) > 0 { + cs.ccfg = ccfgs[0] + } + + return cs +} + +// ClientStore MongoDB storage for OAuth 2.0 +type ClientStore struct { + ccfg *ClientConfig + dbName string + session *mgo.Session +} + +// Close close the mongo session +func (cs *ClientStore) Close() { + cs.session.Close() +} + +func (cs *ClientStore) c(name string) *mgo.Collection { + return cs.session.DB(cs.dbName).C(name) +} + +func (cs *ClientStore) cHandler(name string, handler func(c *mgo.Collection)) { + session := cs.session.Clone() + defer session.Close() + handler(session.DB(cs.dbName).C(name)) + return +} + +// Set set client information +func (cs *ClientStore) Set(info oauth2.ClientInfo) (err error) { + cs.cHandler(cs.ccfg.ClientsCName, func(c *mgo.Collection) { + entity := &client{ + ID: info.GetID(), + Secret: info.GetSecret(), + Domain: info.GetDomain(), + UserID: info.GetUserID(), + } + + if cerr := c.Insert(entity); cerr != nil { + err = cerr + return + } + }) + + return +} + +// GetByID according to the ID for the client information +func (cs *ClientStore) GetByID(id string) (info oauth2.ClientInfo, err error) { + cs.cHandler(cs.ccfg.ClientsCName, func(c *mgo.Collection) { + entity := new(client) + + if cerr := c.FindId(id).One(entity); cerr != nil { + err = cerr + return + } + + info = &models.Client{ + ID: entity.ID, + Secret: entity.Secret, + Domain: entity.Domain, + UserID: entity.UserID, + } + }) + + return +} + +// RemoveByID use the client id to delete the client information +func (cs *ClientStore) RemoveByID(id string) (err error) { + cs.cHandler(cs.ccfg.ClientsCName, func(c *mgo.Collection) { + if cerr := c.RemoveId(id); cerr != nil { + err = cerr + return + } + }) + + return +} + +type client struct { + ID string `bson:"_id"` + Secret string `bson:"secret"` + Domain string `bson:"domain"` + UserID string `bson:"userid"` +} diff --git a/client_store_test.go b/client_store_test.go new file mode 100644 index 0000000..5cc6afa --- /dev/null +++ b/client_store_test.go @@ -0,0 +1,64 @@ +package mongo + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" + "gopkg.in/oauth2.v3/models" +) + +func TestClientStore(t *testing.T) { + store := NewClientStore(NewConfig(url, dbName)) + + client := &models.Client{ + ID: "id", + Secret: "secret", + Domain: "domain", + UserID: "user_id", + } + + Convey("Set", t, func() { + Convey("HappyPath", func() { + _ = store.RemoveByID(client.ID) + + err := store.Set(client) + + So(err, ShouldBeNil) + }) + + Convey("AlreadyExistingClient", func() { + _ = store.RemoveByID(client.ID) + + _ = store.Set(client) + err := store.Set(client) + + So(err, ShouldNotBeNil) + }) + }) + + Convey("GetByID", t, func() { + Convey("HappyPath", func() { + _ = store.RemoveByID(client.ID) + _ = store.Set(client) + + got, err := store.GetByID(client.ID) + + So(err, ShouldBeNil) + So(got, ShouldResemble, client) + }) + + Convey("UnknownClient", func() { + _, err := store.GetByID("unknown_client") + + So(err, ShouldNotBeNil) + }) + }) + + Convey("RemoveByID", t, func() { + Convey("UnknownClient", func() { + err := store.RemoveByID("unknown_client") + + So(err, ShouldNotBeNil) + }) + }) +} diff --git a/config.go b/config.go new file mode 100644 index 0000000..96d5ea2 --- /dev/null +++ b/config.go @@ -0,0 +1,15 @@ +package mongo + +// Config mongodb configuration parameters +type Config struct { + URL string + DB string +} + +// NewConfig create mongodb configuration +func NewConfig(url, db string) *Config { + return &Config{ + URL: url, + DB: db, + } +} diff --git a/config_test.go b/config_test.go new file mode 100644 index 0000000..ae17bcb --- /dev/null +++ b/config_test.go @@ -0,0 +1,6 @@ +package mongo + +const ( + url = "127.0.0.1:27017" + dbName = "mydb_test" +) diff --git a/mongo.go b/token_store.go similarity index 94% rename from mongo.go rename to token_store.go index d13be90..b1e3883 100644 --- a/mongo.go +++ b/token_store.go @@ -11,20 +11,6 @@ import ( "gopkg.in/oauth2.v3/models" ) -// Config mongodb configuration parameters -type Config struct { - URL string - DB string -} - -// NewConfig create mongodb configuration -func NewConfig(url, db string) *Config { - return &Config{ - URL: url, - DB: db, - } -} - // TokenConfig token configuration parameters type TokenConfig struct { // store txn collection name(The default is oauth2) @@ -68,17 +54,17 @@ func NewTokenStoreWithSession(session *mgo.Session, dbName string, tcfgs ...*Tok ts.tcfg = tcfgs[0] } - ts.c(ts.tcfg.BasicCName).EnsureIndex(mgo.Index{ + _ = ts.c(ts.tcfg.BasicCName).EnsureIndex(mgo.Index{ Key: []string{"ExpiredAt"}, ExpireAfter: time.Second * 1, }) - ts.c(ts.tcfg.AccessCName).EnsureIndex(mgo.Index{ + _ = ts.c(ts.tcfg.AccessCName).EnsureIndex(mgo.Index{ Key: []string{"ExpiredAt"}, ExpireAfter: time.Second * 1, }) - ts.c(ts.tcfg.RefreshCName).EnsureIndex(mgo.Index{ + _ = ts.c(ts.tcfg.RefreshCName).EnsureIndex(mgo.Index{ Key: []string{"ExpiredAt"}, ExpireAfter: time.Second * 1, }) diff --git a/mongo_test.go b/token_store_test.go similarity index 97% rename from mongo_test.go rename to token_store_test.go index d433610..7f2a71a 100644 --- a/mongo_test.go +++ b/token_store_test.go @@ -9,11 +9,6 @@ import ( . "github.com/smartystreets/goconvey/convey" ) -const ( - url = "127.0.0.1:27017" - dbName = "mydb_test" -) - func TestTokenStore(t *testing.T) { Convey("Test mongodb token store", t, func() { store := NewTokenStore(NewConfig(url, dbName))