-
Notifications
You must be signed in to change notification settings - Fork 0
/
pgdb.go
118 lines (104 loc) · 3.52 KB
/
pgdb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package fitbit_pgdb
// package fitbit_pgdb contains an implementation of the [fitbit.Storage][1] interface
// for the [Fitbit Web API - Go client][2]
//
// [1]: https://github.com/galeone/fitbit/blob/main/storage.go
// [2]: https://github.com/galeone/fitbit
import (
"database/sql"
"github.com/galeone/fitbit/v2/types"
"github.com/galeone/igor"
_ "github.com/joho/godotenv/autoload"
)
// PGDB implements the fitbit.Storage interface
type PGDB struct {
*igor.Database
}
// NewPGDB creates a new connection to a PostgreSQL server.
// You must provide the connection string to use for connecting to a
// running PostgreSQL instance.
//
// *PGDB implements the `fitbit.Storage` interface.
func NewPGDB(connectionString string) *PGDB {
var err error
var db *igor.Database
if db, err = igor.Connect(connectionString); err != nil {
panic(err.Error())
}
return &PGDB{
db,
}
}
// NewPGDBFromConnection creates a new instance of PGDB without creating
// a new connection. It re-uses the database connection provided as input.
//
// *PGDB implements the `fitbit.Storage` interface.
func NewPGDBFromConnection(connection *sql.DB) *PGDB {
var err error
var db *igor.Database
if db, err = igor.Wrap(connection); err != nil {
panic(err.Error())
}
return &PGDB{
db,
}
}
// InsertAuthorizingUser executes a CREATE query on the PostgreSQL database
// inserting the authorizing user in the associated table.
func (s *PGDB) InsertAuthorizingUser(authorizing *types.AuthorizingUser) error {
authorizingUser := &AuthorizingUser{
AuthorizingUser: *authorizing,
}
return s.Create(authorizingUser)
}
// UpsertAuthorizedUser executes INSERT or UPDATE the user on the PostgreSQL database.
// It inserts the user if the SELECT by user UserID fields returns the empty set.
// If it finds the user insteads it updates all the other NON PRIMARY KEY (or equivalent like UserID) fields.
func (s *PGDB) UpsertAuthorizedUser(authorized *types.AuthorizedUser) error {
user := &AuthorizedUser{
AuthorizedUser: *authorized,
}
var exists AuthorizedUser
var err error
var condition AuthorizedUser
condition.UserID = authorized.UserID
if err = s.Model(AuthorizedUser{}).Where(condition).Scan(&exists); err != nil {
// First time we see this user
err = s.Create(user)
} else {
user.ID = exists.ID
err = s.Updates(user)
}
return err
}
// AuthorizedUser executes a SELECT for the types.AuthorizedUser using the
// `accessToken` as only query parameter.
// NOTE: the `accessToken` is unique on the underlying table.
func (s *PGDB) AuthorizedUser(accessToken string) (*types.AuthorizedUser, error) {
var dbToken AuthorizedUser
var err error
var condition AuthorizedUser
condition.AccessToken = accessToken
if err = s.Model(AuthorizedUser{}).Where(&condition).Scan(&dbToken); err != nil {
return nil, err
}
return &dbToken.AuthorizedUser, nil
}
// AuthorizingUser executes a SELECT for the types.AuthorizingUser using the `id`
// provided as PRIMARY KEY for creating the query.
func (s *PGDB) AuthorizingUser(id string) (*types.AuthorizingUser, error) {
var authorizing AuthorizingUser
var err error
var condition AuthorizingUser
condition.CSRFToken = id
if err = s.Model(AuthorizingUser{}).Where(&condition).Scan(&authorizing); err != nil {
return nil, err
}
return &types.AuthorizingUser{
Code: authorizing.Code,
CSRFToken: authorizing.CSRFToken,
}, nil
}