-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from FeNoMeNa/client_store
clients: implement ClientStore interface
- Loading branch information
Showing
6 changed files
with
214 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package mongo | ||
|
||
const ( | ||
url = "127.0.0.1:27017" | ||
dbName = "mydb_test" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters