Skip to content

Commit f1b7d17

Browse files
author
jeffyanta
authored
Merge pull request #17 from code-payments/remove-prisma-accounts
account: remove prisma from postgres store
2 parents 2da7f7e + 224cb28 commit f1b7d17

31 files changed

+372
-422
lines changed

account/postgres/authorizer_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@
33
package postgres
44

55
import (
6+
"context"
67
"testing"
78

8-
prismatest "github.com/code-payments/flipchat-server/database/prisma/test"
9+
"github.com/stretchr/testify/require"
910

1011
"github.com/code-payments/flipchat-server/account/tests"
1112

12-
_ "github.com/jackc/pgx/v4/stdlib"
13+
"github.com/jackc/pgx/v5/pgxpool"
14+
_ "github.com/jackc/pgx/v5/stdlib"
1315
)
1416

1517
func TestAccount_PostgresAuthorizer(t *testing.T) {
16-
client, disconnect := prismatest.NewTestClient(testEnv.DatabaseUrl, t)
17-
defer disconnect()
18+
pool, err := pgxpool.New(context.Background(), testEnv.DatabaseUrl)
19+
require.NoError(t, err)
20+
defer pool.Close()
1821

19-
testStore := NewInPostgres(client)
22+
testStore := NewInPostgres(pool)
2023
teardown := func() {
2124
testStore.(*store).reset()
2225
}

account/postgres/common_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
prismatest "github.com/code-payments/flipchat-server/database/prisma/test"
1212

13-
_ "github.com/jackc/pgx/v4/stdlib"
13+
_ "github.com/jackc/pgx/v5/stdlib"
1414
)
1515

1616
var testEnv *prismatest.TestEnv

account/postgres/model.go

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
package postgres
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"github.com/georgysavva/scany/v2/pgxscan"
9+
"github.com/jackc/pgx/v5/pgxpool"
10+
11+
commonpb "github.com/code-payments/flipchat-protobuf-api/generated/go/common/v1"
12+
"github.com/code-payments/flipchat-server/account"
13+
pg "github.com/code-payments/flipchat-server/database/postgres"
14+
)
15+
16+
const (
17+
publicKeysTableName = "flipchat_publickeys"
18+
allPublicKeyFields = `"key", "userId", "createdAt", "updatedAt"`
19+
20+
usersTableName = "flipchat_users"
21+
allUserFields = `"id", "displayName", "isStaff", "isRegistered", "nextAirdropAt", "elibigibleForAirdropsUntil", "createdAt", "updatedAt"`
22+
)
23+
24+
func dbBind(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId, pubKey *commonpb.PublicKey) error {
25+
tx, err := pool.Begin(ctx)
26+
if err != nil {
27+
return err
28+
}
29+
30+
upsertUserQuery := `INSERT INTO ` + usersTableName + ` (` + allUserFields + `) VALUES ($1, NULL, false, false, NOW(), NOW(), NOW(), NOW()) ON CONFLICT ("id") DO NOTHING`
31+
_, err = tx.Exec(ctx, upsertUserQuery, pg.Encode(userID.Value))
32+
if err != nil {
33+
return err
34+
}
35+
36+
putPubkeyQuery := `INSERT INTO ` + publicKeysTableName + ` (` + allPublicKeyFields + `) VALUES ($1, $2, NOW(), NOW()) ON CONFLICT ("key") DO UPDATE SET "userId" = $2 WHERE ` + publicKeysTableName + `."key" = $1`
37+
_, err = tx.Exec(ctx, putPubkeyQuery, pg.Encode(pubKey.Value, pg.Base58), pg.Encode(userID.Value))
38+
if err != nil {
39+
return err
40+
}
41+
42+
return tx.Commit(ctx)
43+
}
44+
45+
func dbGetUserId(ctx context.Context, pool *pgxpool.Pool, pubKey *commonpb.PublicKey) (*commonpb.UserId, error) {
46+
var encoded string
47+
query := `SELECT "userId" FROM ` + publicKeysTableName + ` WHERE "key" = $1`
48+
err := pgxscan.Get(
49+
ctx,
50+
pool,
51+
&encoded,
52+
query,
53+
pg.Encode(pubKey.Value, pg.Base58),
54+
)
55+
if pgxscan.NotFound(err) {
56+
return nil, account.ErrNotFound
57+
} else if err != nil {
58+
return nil, err
59+
}
60+
decoded, err := pg.Decode(encoded)
61+
if err != nil {
62+
return nil, err
63+
}
64+
return &commonpb.UserId{Value: decoded}, err
65+
}
66+
67+
func dbGetPubKeys(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId) ([]*commonpb.PublicKey, error) {
68+
var encodedValues []string
69+
query := `SELECT "key" FROM ` + publicKeysTableName + ` WHERE "userId" = $1`
70+
err := pgxscan.Select(
71+
ctx,
72+
pool,
73+
&encodedValues,
74+
query,
75+
pg.Encode(userID.Value),
76+
)
77+
if pgxscan.NotFound(err) {
78+
return nil, nil
79+
} else if err != nil {
80+
return nil, err
81+
}
82+
if len(encodedValues) == 0 {
83+
return nil, nil
84+
}
85+
res := make([]*commonpb.PublicKey, len(encodedValues))
86+
for i, encodedValue := range encodedValues {
87+
decodedValue, err := pg.Decode(encodedValue)
88+
if err != nil {
89+
return nil, err
90+
}
91+
res[i] = &commonpb.PublicKey{Value: decodedValue}
92+
}
93+
return res, nil
94+
}
95+
96+
func dbRemoveKey(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId, pubKey *commonpb.PublicKey) error {
97+
query := `DELETE FROM ` + publicKeysTableName + ` WHERE "key" = $1 AND "userId" = $2`
98+
_, err := pool.Exec(ctx, query, pg.Encode(pubKey.Value, pg.Base58), pg.Encode(userID.Value))
99+
return err
100+
}
101+
102+
func dbIsStaff(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId) (bool, error) {
103+
var res bool
104+
query := `SELECT "isStaff" FROM ` + usersTableName + ` WHERE "id" = $1`
105+
err := pgxscan.Get(
106+
ctx,
107+
pool,
108+
&res,
109+
query,
110+
pg.Encode(userID.Value),
111+
)
112+
if pgxscan.NotFound(err) {
113+
return false, nil
114+
}
115+
return res, err
116+
}
117+
118+
func dbIsRegistered(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId) (bool, error) {
119+
var res bool
120+
query := `SELECT "isRegistered" FROM ` + usersTableName + ` WHERE "id" = $1`
121+
err := pgxscan.Get(
122+
ctx,
123+
pool,
124+
&res,
125+
query,
126+
pg.Encode(userID.Value),
127+
)
128+
if pgxscan.NotFound(err) {
129+
return false, nil
130+
}
131+
return res, err
132+
}
133+
134+
func dbSetRegistrationFlag(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId, isRegistered bool) error {
135+
query := `UPDATE ` + usersTableName + ` SET "isRegistered" = $1 WHERE "id" = $2`
136+
res, err := pool.Exec(ctx, query, isRegistered, pg.Encode(userID.Value))
137+
if err != nil {
138+
return err
139+
}
140+
if res.RowsAffected() == 0 {
141+
return account.ErrNotFound
142+
}
143+
return nil
144+
}
145+
146+
func dbBatchSetNextAirdropTimestamp(ctx context.Context, pool *pgxpool.Pool, ts time.Time, userIDs ...*commonpb.UserId) error {
147+
queryParameters := make([]any, len(userIDs)+1)
148+
queryParameters[0] = ts.UTC()
149+
query := `UPDATE ` + usersTableName + ` SET "nextAirdropAt" = $1 WHERE "id" IN (`
150+
for i, userID := range userIDs {
151+
queryParameters[i+1] = pg.Encode(userID.Value)
152+
if i > 0 {
153+
query += fmt.Sprintf(",$%d", i+2)
154+
} else {
155+
query += fmt.Sprintf("$%d", i+2)
156+
}
157+
}
158+
query += `)`
159+
_, err := pool.Exec(ctx, query, queryParameters...)
160+
if err != nil {
161+
return err
162+
}
163+
return err
164+
}
165+
166+
func dbGetNextAirdropTimestamp(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId) (time.Time, error) {
167+
res := struct {
168+
NextAirdropAt time.Time `db:"nextAirdropAt"`
169+
}{}
170+
query := `SELECT "nextAirdropAt" FROM ` + usersTableName + ` WHERE "id" = $1`
171+
err := pgxscan.Get(
172+
ctx,
173+
pool,
174+
&res,
175+
query,
176+
pg.Encode(userID.Value),
177+
)
178+
if pgxscan.NotFound(err) {
179+
return time.Time{}, account.ErrNotFound
180+
} else if err != nil {
181+
return time.Time{}, err
182+
}
183+
return res.NextAirdropAt, err
184+
}
185+
186+
func dbExtendAirdropEligibility(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId, until time.Time) error {
187+
query := `UPDATE ` + usersTableName + ` SET "elibigibleForAirdropsUntil" = $1 WHERE "id" = $2`
188+
res, err := pool.Exec(ctx, query, until.UTC(), pg.Encode(userID.Value))
189+
if err != nil {
190+
return err
191+
}
192+
if res.RowsAffected() == 0 {
193+
return account.ErrNotFound
194+
}
195+
return nil
196+
}
197+
198+
func dbGetAirdropEligibilityTimestamp(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId) (time.Time, error) {
199+
res := struct {
200+
ElibigibleForAirdropsUntil time.Time `db:"elibigibleForAirdropsUntil"`
201+
}{}
202+
query := `SELECT "elibigibleForAirdropsUntil" FROM ` + usersTableName + ` WHERE "id" = $1`
203+
err := pgxscan.Get(
204+
ctx,
205+
pool,
206+
&res,
207+
query,
208+
pg.Encode(userID.Value),
209+
)
210+
if pgxscan.NotFound(err) {
211+
return time.Time{}, account.ErrNotFound
212+
} else if err != nil {
213+
return time.Time{}, err
214+
}
215+
return res.ElibigibleForAirdropsUntil, err
216+
}
217+
218+
func dbGetUsersToAirdrop(ctx context.Context, pool *pgxpool.Pool, at time.Time) ([]*commonpb.UserId, error) {
219+
var encodedValues []string
220+
query := `SELECT "id" FROM ` + usersTableName + ` WHERE "isRegistered" = true AND "nextAirdropAt" < $1 AND "elibigibleForAirdropsUntil" > $1`
221+
err := pgxscan.Select(
222+
ctx,
223+
pool,
224+
&encodedValues,
225+
query,
226+
at.UTC(),
227+
)
228+
if pgxscan.NotFound(err) {
229+
return nil, account.ErrNotFound
230+
} else if err != nil {
231+
return nil, err
232+
}
233+
if len(encodedValues) == 0 {
234+
return nil, account.ErrNotFound
235+
}
236+
res := make([]*commonpb.UserId, len(encodedValues))
237+
for i, encodedValue := range encodedValues {
238+
decodedValue, err := pg.Decode(encodedValue)
239+
if err != nil {
240+
return nil, err
241+
}
242+
res[i] = &commonpb.UserId{Value: decodedValue}
243+
}
244+
return res, nil
245+
}

account/postgres/server_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@
33
package postgres
44

55
import (
6+
"context"
67
"testing"
78

8-
prismatest "github.com/code-payments/flipchat-server/database/prisma/test"
9+
"github.com/stretchr/testify/require"
910

1011
"github.com/code-payments/flipchat-server/account/tests"
1112

12-
_ "github.com/jackc/pgx/v4/stdlib"
13+
"github.com/jackc/pgx/v5/pgxpool"
14+
_ "github.com/jackc/pgx/v5/stdlib"
1315
)
1416

1517
func TestAccount_PostgresServer(t *testing.T) {
16-
client, disconnect := prismatest.NewTestClient(testEnv.DatabaseUrl, t)
17-
defer disconnect()
18+
pool, err := pgxpool.New(context.Background(), testEnv.DatabaseUrl)
19+
require.NoError(t, err)
20+
defer pool.Close()
1821

19-
testStore := NewInPostgres(client)
22+
testStore := NewInPostgres(pool)
2023
teardown := func() {
2124
testStore.(*store).reset()
2225
}

0 commit comments

Comments
 (0)