Skip to content

Commit e3051c6

Browse files
authored
Merge pull request #4 from vgarvardt/feature/client-store
Renamed Store to TokenStore as ClientStore is coming next
2 parents f85a5e1 + fe759fe commit e3051c6

13 files changed

+599
-302
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,14 @@ func main() {
3939
manager := manage.NewDefaultManager()
4040

4141
// use PostgreSQL token store with pgx.Connection adapter
42-
store, _ := pg.NewStore(pgxAdapter.NewConn(pgxConn), pg.WithGCInterval(time.Minute))
42+
adapter := pgxAdapter.NewConn(pgxConn)
43+
tokenStore, _ := pg.NewTokenStore(adapter, pg.WithTokenStoreGCInterval(time.Minute))
4344
defer store.Close()
45+
46+
clientStore, _ := pg.NewClientStore(adapter)
4447

45-
manager.MapTokenStorage(store)
48+
manager.MapTokenStorage(tokenStore)
49+
manager.MapClientStorage(clientStore)
4650
// ...
4751
}
4852
```

client_store.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package pg
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
8+
"github.com/json-iterator/go"
9+
"gopkg.in/oauth2.v3"
10+
"gopkg.in/oauth2.v3/models"
11+
)
12+
13+
// ClientStore PostgreSQL client store
14+
type ClientStore struct {
15+
adapter Adapter
16+
tableName string
17+
logger Logger
18+
19+
initTableDisabled bool
20+
}
21+
22+
// ClientStoreItem data item
23+
type ClientStoreItem struct {
24+
ID string `db:"id"`
25+
Secret string `db:"secret"`
26+
Domain string `db:"domain"`
27+
Data []byte `db:"data"`
28+
}
29+
30+
// NewClientStore creates PostgreSQL store instance
31+
func NewClientStore(adapter Adapter, options ...ClientStoreOption) (*ClientStore, error) {
32+
store := &ClientStore{
33+
adapter: adapter,
34+
tableName: "oauth2_clients",
35+
logger: log.New(os.Stderr, "[OAUTH2-PG-ERROR]", log.LstdFlags),
36+
}
37+
38+
for _, o := range options {
39+
o(store)
40+
}
41+
42+
var err error
43+
if !store.initTableDisabled {
44+
err = store.initTable()
45+
}
46+
47+
if err != nil {
48+
return store, err
49+
}
50+
51+
return store, err
52+
}
53+
54+
func (s *ClientStore) initTable() error {
55+
return s.adapter.Exec(fmt.Sprintf(`
56+
CREATE TABLE IF NOT EXISTS %[1]s (
57+
id TEXT NOT NULL,
58+
secret TEXT NOT NULL,
59+
domain TEXT NOT NULL,
60+
data JSONB NOT NULL,
61+
CONSTRAINT %[1]s_pkey PRIMARY KEY (id)
62+
);
63+
`, s.tableName))
64+
}
65+
66+
func (s *ClientStore) toClientInfo(data []byte) (oauth2.ClientInfo, error) {
67+
var cm models.Client
68+
err := jsoniter.Unmarshal(data, &cm)
69+
return &cm, err
70+
}
71+
72+
// GetByID retrieves and returns client information by id
73+
func (s *ClientStore) GetByID(id string) (oauth2.ClientInfo, error) {
74+
if id == "" {
75+
return nil, nil
76+
}
77+
78+
var item ClientStoreItem
79+
if err := s.adapter.SelectOne(&item, fmt.Sprintf("SELECT * FROM %s WHERE id = $1", s.tableName), id); err != nil {
80+
return nil, err
81+
}
82+
83+
return s.toClientInfo(item.Data)
84+
}
85+
86+
// Create creates and stores the new client information
87+
func (s *ClientStore) Create(info oauth2.ClientInfo) error {
88+
data, err := jsoniter.Marshal(info)
89+
if err != nil {
90+
return err
91+
}
92+
93+
return s.adapter.Exec(
94+
fmt.Sprintf("INSERT INTO %s (id, secret, domain, data) VALUES ($1, $2, $3, $4)", s.tableName),
95+
info.GetID(),
96+
info.GetSecret(),
97+
info.GetDomain(),
98+
data,
99+
)
100+
}

client_store_options.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package pg
2+
3+
// ClientStoreOption is the configuration options type for client store
4+
type ClientStoreOption func(s *ClientStore)
5+
6+
// WithClientStoreTableName returns option that sets client store table name
7+
func WithClientStoreTableName(tableName string) ClientStoreOption {
8+
return func(s *ClientStore) {
9+
s.tableName = tableName
10+
}
11+
}
12+
13+
// WithClientStoreLogger returns option that sets client store logger implementation
14+
func WithClientStoreLogger(logger Logger) ClientStoreOption {
15+
return func(s *ClientStore) {
16+
s.logger = logger
17+
}
18+
}
19+
20+
// WithClientStoreInitTableDisabled returns option that disables table creation on client store instantiation
21+
func WithClientStoreInitTableDisabled() ClientStoreOption {
22+
return func(s *ClientStore) {
23+
s.initTableDisabled = true
24+
}
25+
}

client_store_options_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package pg
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestWithClientStoreInitTableDisabled(t *testing.T) {
12+
store, err := NewClientStore(nil, WithClientStoreInitTableDisabled())
13+
require.NoError(t, err)
14+
assert.True(t, store.initTableDisabled)
15+
}
16+
17+
func TestWithClientStoreTableName(t *testing.T) {
18+
randomName := time.Now().String()
19+
20+
store, err := NewClientStore(nil, WithClientStoreTableName(randomName), WithClientStoreInitTableDisabled())
21+
require.NoError(t, err)
22+
assert.Equal(t, randomName, store.tableName)
23+
}
24+
25+
func TestWithClientStoreLogger(t *testing.T) {
26+
l := new(memoryLogger)
27+
28+
store, err := NewClientStore(nil, WithClientStoreLogger(l), WithClientStoreInitTableDisabled())
29+
require.NoError(t, err)
30+
31+
store.logger.Printf("log1", 1, "2", "333")
32+
store.logger.Printf("log2", 12, "22")
33+
34+
require.Equal(t, 2, len(l.formats))
35+
require.Equal(t, 2, len(l.args))
36+
37+
assert.Equal(t, "log1", l.formats[0])
38+
assert.Equal(t, "log2", l.formats[1])
39+
40+
require.Equal(t, 3, len(l.args[0]))
41+
require.Equal(t, 2, len(l.args[1]))
42+
43+
assert.Equal(t, 1, l.args[0][0])
44+
assert.Equal(t, "2", l.args[0][1])
45+
assert.Equal(t, "333", l.args[0][2])
46+
47+
assert.Equal(t, 12, l.args[1][0])
48+
assert.Equal(t, "22", l.args[1][1])
49+
}

client_store_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package pg
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestClientStore_initTable(t *testing.T) {
12+
adapter := new(mockAdapter)
13+
14+
_, err := NewClientStore(adapter)
15+
require.NoError(t, err)
16+
17+
assert.Equal(t, 1, len(adapter.execCalls))
18+
assert.Equal(t, 0, len(adapter.selectOneCalls))
19+
20+
// new line character is the character at position 0
21+
assert.Equal(t, 1, strings.Index(adapter.execCalls[0].query, "CREATE TABLE IF NOT EXISTS"))
22+
}

options.go

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)