Skip to content
This repository was archived by the owner on Oct 31, 2021. It is now read-only.

Commit 2ab8ce3

Browse files
committed
General improvements to sentry traces and testing.
1 parent cac48d4 commit 2ab8ce3

24 files changed

+404
-99
lines changed

.deepsource.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "go"
77
enabled = true
88

99
[analyzers.meta]
10-
import_paths = ["github.com/monetrapp/rest-api"]
10+
import_paths = ["github.com/monetr/rest-api"]
1111

1212
[[analyzers]]
1313
name = "test-coverage"

Makefile

-9
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,6 @@ docker:
5858
docker-work-web-ui:
5959
docker build -t workwebui -f Dockerfile.work .
6060

61-
clean-development:
62-
docker-compose -f ./docker-compose.development.yaml rm --stop --force || true
63-
64-
compose-development: docker docker-work-web-ui
65-
docker-compose -f ./docker-compose.development.yaml up
66-
67-
compose-development-lite:
68-
docker-compose -f ./docker-compose.development.yaml up
69-
7061
ifdef GITLAB_CI
7162
include Makefile.gitlab-ci
7263
endif

docker-compose.development.yaml

-17
This file was deleted.

pkg/config/configuration.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,15 @@ type JWT struct {
5656
}
5757

5858
type PostgreSQL struct {
59-
Address string
60-
Port int
61-
Username string
62-
Password string
63-
Database string
64-
CACertificatePath string
65-
KeyPath string
66-
CertificatePath string
59+
Address string
60+
Port int
61+
Username string
62+
Password string
63+
Database string
64+
InsecureSkipVerify bool
65+
CACertificatePath string
66+
KeyPath string
67+
CertificatePath string
6768
}
6869

6970
type SMTPClient struct {
@@ -266,6 +267,7 @@ func setupEnv(v *viper.Viper) {
266267
v.BindEnv("PostgreSQL.Username", "MONETR_PG_USERNAME")
267268
v.BindEnv("PostgreSQL.Password", "MONETR_PG_PASSWORD")
268269
v.BindEnv("PostgreSQL.Database", "MONETR_PG_DATABASE")
270+
v.BindEnv("PostgreSQL.InsecureSkipVerify", "MONETR_PG_INSECURE_SKIP_VERIFY")
269271
v.BindEnv("PostgreSQL.CACertificatePath", "MONETR_PG_CA_PATH")
270272
v.BindEnv("PostgreSQL.CertificatePath", "MONETR_PG_CERT_PATH")
271273
v.BindEnv("PostgreSQL.KeyPath", "MONETR_PG_KEY_PATH")

pkg/controller/controller.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ func (c *Controller) RegisterRoutes(app *iris.Application) {
203203
span.Status = sentry.SpanStatusOK
204204
}
205205
}
206+
span.Finish()
206207
}()
207-
defer span.Finish()
208208

209209
ctx.Values().Set(spanKey, span)
210210
ctx.Values().Set(spanContextKey, span.Context())
@@ -251,7 +251,7 @@ func (c *Controller) RegisterRoutes(app *iris.Application) {
251251
repoParty.PartyFunc("/authentication", func(repoParty router.Party) {
252252
repoParty.Post("/login", c.loginEndpoint)
253253
repoParty.Post("/register", c.registerEndpoint)
254-
repoParty.Post("/verify", c.verifyEndpoint)
254+
//repoParty.Post("/verify", c.verifyEndpoint)
255255
})
256256

257257
repoParty.Use(c.authenticationMiddleware)

pkg/controller/login.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (c *Controller) loginEndpoint(ctx iris.Context) {
101101
}
102102

103103
if !c.configuration.Stripe.IsBillingEnabled() {
104-
token, err := c.generateToken(login.LoginId, user.UserId, user.AccountId, true)
104+
token, err := c.generateToken(login.LoginId, user.UserId, user.AccountId)
105105
if err != nil {
106106
c.wrapAndReturnError(ctx, err, http.StatusInternalServerError, "could not generate JWT")
107107
return
@@ -120,7 +120,7 @@ func (c *Controller) loginEndpoint(ctx iris.Context) {
120120
return
121121
}
122122

123-
token, err := c.generateToken(login.LoginId, user.UserId, user.AccountId, subscriptionIsActive)
123+
token, err := c.generateToken(login.LoginId, user.UserId, user.AccountId)
124124
if err != nil {
125125
c.wrapAndReturnError(ctx, err, http.StatusInternalServerError, "could not generate JWT")
126126
return
@@ -139,7 +139,7 @@ func (c *Controller) loginEndpoint(ctx iris.Context) {
139139
// If the login has more than one user then we want to generate a temp
140140
// JWT that will only grant them access to API endpoints not specific to
141141
// an account.
142-
token, err := c.generateToken(login.LoginId, 0, 0, true)
142+
token, err := c.generateToken(login.LoginId, 0, 0)
143143
if err != nil {
144144
c.wrapAndReturnError(ctx, err, http.StatusInternalServerError, "could not generate JWT")
145145
return
@@ -161,7 +161,7 @@ func (c *Controller) validateLogin(email, password string) error {
161161
return nil
162162
}
163163

164-
func (c *Controller) generateToken(loginId, userId, accountId uint64, subscriptionActive bool) (string, error) {
164+
func (c *Controller) generateToken(loginId, userId, accountId uint64) (string, error) {
165165
now := time.Now()
166166
claims := &HarderClaims{
167167
LoginId: loginId,

pkg/controller/register.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func (c *Controller) registerEndpoint(ctx iris.Context) {
240240

241241
// If we are not requiring email verification to activate an account we can
242242
// simply return a token here for the user to be signed in.
243-
token, err := c.generateToken(login.LoginId, user.UserId, account.AccountId, !c.configuration.Stripe.IsBillingEnabled())
243+
token, err := c.generateToken(login.LoginId, user.UserId, account.AccountId)
244244
if err != nil {
245245
c.wrapAndReturnError(ctx, err, http.StatusInternalServerError,
246246
"failed to create JWT",
@@ -310,7 +310,7 @@ func (c *Controller) verifyEndpoint(ctx iris.Context) {
310310
return
311311
}
312312

313-
token, err := c.generateToken(user.LoginId, user.UserId, user.AccountId, true)
313+
token, err := c.generateToken(user.LoginId, user.UserId, user.AccountId)
314314
if err != nil {
315315
c.wrapAndReturnError(ctx, err, http.StatusInternalServerError,
316316
"failed to create JWT",

pkg/controller/transactions.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ func (c *Controller) handleTransactions(p iris.Party) {
2323
// @Summary List Transactions
2424
// @ID list-transactions
2525
// @tags Transactions
26-
// @description Lists the transactions for the specified bank account Id. Transactions are returned sorted by the date they were authorized (descending) and then by their numeric Id (descending). This means that transactions that were first seen later will be higher in the list than they may have actually occurred.
26+
// @description Lists the transactions for the specified bank account Id. Transactions are returned sorted by the date
27+
// @description they were authorized (descending) and then by their numeric Id (descending). This means that
28+
// @description transactions that were first seen later will be higher in the list than they may have actually occurred.
2729
// @Security ApiKeyAuth
2830
// @Produce json
2931
// @Param bankAccountId path int true "Bank Account ID"
3032
// @Param limit query int false "Specifies the number of transactions to return in the result, default is 25. Max is 100."
3133
// @Param offset query int false "The number of transactions to skip before returning any."
3234
// @Router /bank_accounts/{bankAccountId}/transactions [get]
33-
// @Success 200 {array} models.Transaction
35+
// @Success 200 {array} swag.TransactionResponse
3436
// @Failure 400 {object} InvalidBankAccountIdError Invalid Bank Account ID.
3537
// @Failure 500 {object} ApiError Something went wrong on our end.
3638
func (c *Controller) getTransactions(ctx *context.Context) {
@@ -149,6 +151,21 @@ func (c *Controller) postTransactions(ctx *context.Context) {
149151
ctx.JSON(returnedObject)
150152
}
151153

154+
// Update Transaction
155+
// @Summary Update Transaction
156+
// @ID update-transactions
157+
// @tags Transactions
158+
// @description Updates the provided transaction.
159+
// @Security ApiKeyAuth
160+
// @Accept json
161+
// @Produce json
162+
// @Param bankAccountId path int true "Bank Account ID"
163+
// @Param transactionId path int true "TransactionId "
164+
// @Param Transaction body swag.UpdateTransactionRequest true "Updated transaction"
165+
// @Router /bank_accounts/{bankAccountId}/transactions/{transactionId} [post]
166+
// @Success 200 {array} swag.TransactionResponse
167+
// @Failure 400 {object} InvalidBankAccountIdError Invalid Bank Account ID.
168+
// @Failure 500 {object} ApiError Something went wrong on our end.
152169
func (c *Controller) putTransactions(ctx *context.Context) {
153170
bankAccountId := ctx.Params().GetUint64Default("bankAccountId", 0)
154171
if bankAccountId == 0 {

pkg/internal/cmd/serve.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func RunServer() error {
174174

175175
tlsConfiguration = &tls.Config{
176176
Rand: rand.Reader,
177-
InsecureSkipVerify: true,
177+
InsecureSkipVerify: configuration.PostgreSQL.InsecureSkipVerify,
178178
RootCAs: caCertPool,
179179
ServerName: configuration.PostgreSQL.Address,
180180
Renegotiation: tls.RenegotiateFreelyAsClient,
@@ -228,7 +228,7 @@ func RunServer() error {
228228

229229
tlsConfig := &tls.Config{
230230
Rand: rand.Reader,
231-
InsecureSkipVerify: true,
231+
InsecureSkipVerify: configuration.PostgreSQL.InsecureSkipVerify,
232232
RootCAs: nil,
233233
ServerName: configuration.PostgreSQL.Address,
234234
Renegotiation: tls.RenegotiateFreelyAsClient,

pkg/jobs/process_funding_schedules.go

+5
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ func (j *jobManagerBase) processFundingSchedules(job *work.Job) (err error) {
138138
return err
139139
}
140140

141+
if !fundingSchedule.CalculateNextOccurrence(span.Context(), timezone) {
142+
fundingLog.Warn("skipping processing funding schedule, it does not occur yet")
143+
continue
144+
}
145+
141146
if time.Now().Before(fundingSchedule.NextOccurrence) {
142147
crumbs.Debug(span.Context(), "Skipping processing funding schedule, it does not occur yet", map[string]interface{}{
143148
"fundingScheduleId": fundingScheduleId,

pkg/models/funding_schedule.go

+32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package models
22

33
import (
4+
"context"
5+
"github.com/getsentry/sentry-go"
6+
"github.com/monetr/rest-api/pkg/crumbs"
7+
"github.com/monetr/rest-api/pkg/util"
48
"time"
59
)
610

@@ -18,3 +22,31 @@ type FundingSchedule struct {
1822
LastOccurrence *time.Time `json:"lastOccurrence" pg:"last_occurrence"`
1923
NextOccurrence time.Time `json:"nextOccurrence" pg:"next_occurrence,notnull"`
2024
}
25+
26+
func (f *FundingSchedule) CalculateNextOccurrence(ctx context.Context, timezone *time.Location) bool {
27+
span := sentry.StartSpan(ctx, "CalculateNextOccurrence")
28+
defer span.Finish()
29+
30+
span.Data = map[string]interface{}{
31+
"fundingScheduleId": f.FundingScheduleId,
32+
"timezone": timezone.String(),
33+
}
34+
35+
now := time.Now()
36+
37+
if now.Before(f.NextOccurrence) {
38+
crumbs.Debug(span.Context(), "Skipping processing funding schedule, it does not occur yet", map[string]interface{}{
39+
"fundingScheduleId": f.FundingScheduleId,
40+
"nextOccurrence": f.NextOccurrence,
41+
})
42+
return false
43+
}
44+
45+
nextFundingOccurrence := util.MidnightInLocal(f.Rule.After(now, false), timezone)
46+
47+
current := f.NextOccurrence
48+
f.LastOccurrence = &current
49+
f.NextOccurrence = nextFundingOccurrence
50+
51+
return true
52+
}

pkg/models/funding_schedule_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package models
2+
3+
import (
4+
"context"
5+
"github.com/stretchr/testify/assert"
6+
"github.com/stretchr/testify/require"
7+
"testing"
8+
"time"
9+
)
10+
11+
func TestFundingSchedule_CalculateNextOccurrence(t *testing.T) {
12+
t.Run("simple", func(t *testing.T) {
13+
rule, err := NewRule("FREQ=DAILY")
14+
require.NoError(t, err, "must be able to create a rule")
15+
16+
originalOccurrence := time.Now().Add(-1 * time.Minute)
17+
18+
fundingSchedule := FundingSchedule{
19+
AccountId: 1234,
20+
BankAccountId: 1234,
21+
Name: "Testing #123",
22+
Description: t.Name(),
23+
Rule: rule,
24+
LastOccurrence: nil,
25+
NextOccurrence: originalOccurrence,
26+
}
27+
28+
assert.Nil(t, fundingSchedule.LastOccurrence, "last occurrence should still be nil")
29+
30+
ok := fundingSchedule.CalculateNextOccurrence(context.Background(), time.Local)
31+
assert.True(t, ok, "should calculate next occurrence")
32+
assert.NotNil(t, fundingSchedule.LastOccurrence, "last occurrence should no longer be nil")
33+
assert.Equal(t, originalOccurrence.Unix(), fundingSchedule.LastOccurrence.Unix(), "last occurrence should match original")
34+
assert.Greater(t, fundingSchedule.NextOccurrence.Unix(), originalOccurrence.Unix(), "next occurrence should be in the future relative to the last occurrence")
35+
})
36+
37+
t.Run("would skip", func(t *testing.T) {
38+
rule, err := NewRule("FREQ=DAILY")
39+
require.NoError(t, err, "must be able to create a rule")
40+
41+
originalOccurrence := time.Now().Add(1 * time.Minute)
42+
43+
fundingSchedule := FundingSchedule{
44+
AccountId: 1234,
45+
BankAccountId: 1234,
46+
Name: "Testing #123",
47+
Description: t.Name(),
48+
Rule: rule,
49+
LastOccurrence: nil,
50+
NextOccurrence: originalOccurrence,
51+
}
52+
53+
assert.Nil(t, fundingSchedule.LastOccurrence, "last occurrence should still be nil")
54+
55+
ok := fundingSchedule.CalculateNextOccurrence(context.Background(), time.Local)
56+
assert.False(t, ok, "next occurrence should not be calculated")
57+
assert.Equal(t, originalOccurrence.Unix(), fundingSchedule.NextOccurrence.Unix(), "next occurrence should not have changed")
58+
})
59+
}

pkg/models/invoice.go

-9
This file was deleted.

pkg/models/payment_method.go

-19
This file was deleted.

pkg/models/rule.go

+11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ type Rule struct {
2222
rrule.RRule
2323
}
2424

25+
func NewRule(input string) (*Rule, error) {
26+
rule, err := rrule.StrToRRule(input)
27+
if err != nil {
28+
return nil, errors.Wrap(err, "failed to parse rule")
29+
}
30+
31+
return &Rule{
32+
RRule: *rule,
33+
}, nil
34+
}
35+
2536
func (r *Rule) UnmarshalJSON(input []byte) error {
2637
rule, err := rrule.StrToRRule(strings.Trim(string(input), `"`))
2738
if err != nil {

pkg/repository/funding_schedules.go

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func (r *repositoryBase) UpdateNextFundingScheduleDate(ctx context.Context, fund
8989
}
9090

9191
_, err := r.txn.ModelContext(span.Context(), &models.FundingSchedule{}).
92+
Set(`"last_occurrence" = "next_occurrence"`).
9293
Set(`"next_occurrence" = ?`, nextOccurrence).
9394
Where(`"funding_schedule"."account_id" = ?`, r.AccountId()).
9495
Where(`"funding_schedule"."funding_schedule_id" = ?`, fundingScheduleId).

0 commit comments

Comments
 (0)