Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
73ef5b7
[BACK-2416] Add optional TIDEPOOL_AUTH_CLIENT_EXTERNAL_PATH_PREFIX
lostlevels Jan 3, 2024
d075b04
Add ability to disable index creation on startup with an env variable
toddkazakov Mar 15, 2023
aed9c70
Create new deviceData indexes, hint, and remove "type" field from ind…
lostlevels Sep 13, 2024
0b173d9
Match indexes to production in shadowed cluster.
lostlevels Jan 15, 2025
017b966
Merge remote-tracking branch 'origin/master' into jimmy/back-2416-sha…
lostlevels Jan 15, 2025
0b6b2b5
Re-add superfluous "type: {$ne: 'upload'}" query selector to match prod.
lostlevels Jan 15, 2025
8a97e25
Modify summary indexes to allow for sorted migratiuon queries
Roukoswarf Apr 16, 2025
7a499c7
change egrep to grep -E
ewollesen Jan 16, 2025
c6fb178
Add Twiist provider
toddkazakov May 28, 2024
73f9487
Dump request and response for token exchange
toddkazakov Jun 6, 2024
49b61a3
Remove debug statements
toddkazakov Jun 11, 2024
1d27a87
[BACK-1913] Add sample interval and backfilled to cbg data type
darinkrauss Feb 3, 2025
271837e
upgrade golang.org/x/net package to fix CVE-2024-45338
ewollesen Jan 29, 2025
542c860
Prevent panics if ehr sync tasks don't have a cadence set
toddkazakov Feb 21, 2025
8d3ca97
[BACK-3461] Add trend rate units to cbg data type
darinkrauss Mar 5, 2025
9f86058
[BACK-3392] Add OpenID sector for Abbott OAuth
darinkrauss Feb 7, 2025
34522a0
Make trend rate units optional
toddkazakov Mar 12, 2025
b6cdf7e
[BACK-2773/3474/3475] Updates to data model for twiist integration
darinkrauss Mar 18, 2025
c2a3788
[BACK-3514] Handle out-of-order food and bolus data for twiist
darinkrauss Apr 2, 2025
f3d1833
Minor updates to fix bugs
darinkrauss Apr 2, 2025
ebc8cf6
Updates based upon PR review
darinkrauss Apr 3, 2025
b7a1aed
Merge remote-tracking branch 'origin/alex-fix-mongo8-null-check' into…
lostlevels Apr 23, 2025
cffbd7a
Put back upload type on deviceDataSets.
lostlevels Apr 23, 2025
aecd54e
Merge remote-tracking branch 'origin/master' into jimmy/back-2416-sha…
lostlevels Apr 23, 2025
e4ed169
Merge remote-tracking branch 'origin/master' into jimmy/back-2416-sha…
lostlevels May 13, 2025
20a1a08
Fix index after merge.
lostlevels May 13, 2025
975865b
Fix tests.
lostlevels May 13, 2025
2fa84f3
Don't log provenance error.
lostlevels May 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions auth/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var _ = Describe("Client", func() {
config.Config.UserAgent = testHttp.NewUserAgent()
config.Config.ServiceSecret = authTest.NewServiceSecret()
config.ExternalConfig.Address = testHttp.NewAddress()
config.ExternalConfig.PathPrefix = "auth"
config.ExternalConfig.UserAgent = testHttp.NewUserAgent()
config.ExternalConfig.ServerSessionTokenSecret = serverTokenSecret
config.ExternalConfig.ServerSessionTokenTimeout = time.Duration(serverTokenTimeout) * time.Second
Expand Down Expand Up @@ -126,6 +127,7 @@ var _ = Describe("Client", func() {
config.Config.UserAgent = testHttp.NewUserAgent()
config.Config.ServiceSecret = authTest.NewServiceSecret()
config.ExternalConfig.Address = server.URL()
config.ExternalConfig.PathPrefix = "auth"
config.ExternalConfig.UserAgent = testHttp.NewUserAgent()
config.ExternalConfig.ServerSessionTokenSecret = serverTokenSecret
authorizeAs = platform.AuthorizeAsService
Expand Down
8 changes: 6 additions & 2 deletions auth/client/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ type ExternalConfig struct {
*platform.Config
ServerSessionTokenSecret string `envconfig:"TIDEPOOL_AUTH_CLIENT_EXTERNAL_SERVER_SESSION_TOKEN_SECRET"`
ServerSessionTokenTimeout time.Duration `envconfig:"TIDEPOOL_AUTH_CLIENT_EXTERNAL_SERVER_SESSION_TOKEN_TIMEOUT" default:"1h"`
// PathPrefix to prepend to the path of any service calls (if any).
PathPrefix string `envconfig:"TIDEPOOL_AUTH_CLIENT_EXTERNAL_PATH_PREFIX" default:"auth"`
}

func NewExternalConfig() *ExternalConfig {
Expand Down Expand Up @@ -107,6 +109,7 @@ type External struct {
serverSessionTokenMutex sync.Mutex
serverSessionTokenSafe string
closingChannel chan chan bool
PathPrefix string // PathPrefix is the prefix to prepend to all external URL path calls to the auth service (if any)
}

func NewExternal(cfg *ExternalConfig, authorizeAs platform.AuthorizeAs, name string, lgr log.Logger) (*External, error) {
Expand Down Expand Up @@ -135,6 +138,7 @@ func NewExternal(cfg *ExternalConfig, authorizeAs platform.AuthorizeAs, name str
name: name,
serverSessionTokenSecret: cfg.ServerSessionTokenSecret,
serverSessionTokenTimeout: cfg.ServerSessionTokenTimeout,
PathPrefix: cfg.PathPrefix,
}, nil
}

Expand Down Expand Up @@ -200,7 +204,7 @@ func (e *External) ValidateSessionToken(ctx context.Context, token string) (requ
IsServer bool
UserID string
}
if err := e.client.RequestData(ctx, "GET", e.client.ConstructURL("auth", "token", token), nil, nil, &result); err != nil {
if err := e.client.RequestData(ctx, "GET", e.client.ConstructURL(e.PathPrefix, "token", token), nil, nil, &result); err != nil {
return nil, err
}

Expand Down Expand Up @@ -329,7 +333,7 @@ func (e *External) refreshServerSessionToken() error {
e.logger.Debug("Refreshing server session token")

requestMethod := "POST"
requestURL := e.client.ConstructURL("auth", "serverlogin")
requestURL := e.client.ConstructURL(e.PathPrefix, "serverlogin")
request, err := http.NewRequest(requestMethod, requestURL, nil)
if err != nil {
return errors.Wrapf(err, "unable to create new request for %s %s", requestMethod, requestURL)
Expand Down
19 changes: 13 additions & 6 deletions auth/service/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (s *Service) Initialize(provider application.Provider) error {
if err := s.initializeTwiistServiceAccountAuthorizer(); err != nil {
return err
}
return s.initializeUserEventsHandler()
return s.initializeUserEventsHandler(provider)
}

func (s *Service) Terminate() {
Expand Down Expand Up @@ -468,13 +468,20 @@ func (s *Service) terminateAuthClient() {
}
}

func (s *Service) initializeUserEventsHandler() error {
func (s *Service) initializeUserEventsHandler(provider application.Provider) error {
s.Logger().Debug("Initializing user events handler")

ctx := logInternal.NewContextWithLogger(context.Background(), s.Logger())
handler := authEvents.NewUserDataDeletionHandler(ctx, s.authClient)
handlers := []eventsCommon.EventHandler{handler}
runner := events.NewRunner(handlers)
var runner events.Runner

configReporter := provider.ConfigReporter().WithScopes("user", "events", "handler")
if configReporter.GetWithDefault("disable", "") != "true" {
ctx := logInternal.NewContextWithLogger(context.Background(), s.Logger())
handler := authEvents.NewUserDataDeletionHandler(ctx, s.authClient)
handlers := []eventsCommon.EventHandler{handler}
runner = events.NewRunner(handlers)
} else {
runner = events.NewNoopRunner()
}

if err := runner.Initialize(); err != nil {
return errors.Wrap(err, "unable to initialize events runner")
Expand Down
2 changes: 1 addition & 1 deletion auth/service/service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var _ = Describe("Service", func() {
server = NewServer()
server.AppendHandlers(
CombineHandlers(
VerifyRequest("POST", "/auth/serverlogin"),
VerifyRequest("POST", "/serverlogin"), // by default the path prefix is empty to the auth service unless set in the env var TIDEPOOL_AUTH_CLIENT_EXTERNAL_PATH_PREFIX
VerifyHeaderKV("X-Tidepool-Server-Name", *provider.NameOutput),
VerifyHeaderKV("X-Tidepool-Server-Secret", serverSecret),
VerifyBody(nil),
Expand Down
19 changes: 13 additions & 6 deletions blob/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (s *Service) Initialize(provider application.Provider) error {
if err := s.initializeBlobClient(); err != nil {
return err
}
if err := s.initializeUserEventsHandler(); err != nil {
if err := s.initializeUserEventsHandler(provider); err != nil {
return err
}
return s.initializeRouter()
Expand Down Expand Up @@ -211,13 +211,20 @@ func (s *Service) terminateDeviceLogsUnstructuredStore() {
}
}

func (s *Service) initializeUserEventsHandler() error {
func (s *Service) initializeUserEventsHandler(provider application.Provider) error {
s.Logger().Debug("Initializing user events handler")

ctx := logInternal.NewContextWithLogger(context.Background(), s.Logger())
handler := blobEvents.NewUserDataDeletionHandler(ctx, s.blobClient)
handlers := []eventsCommon.EventHandler{handler}
runner := events.NewRunner(handlers)
var runner events.Runner

configReporter := provider.ConfigReporter().WithScopes("user", "events", "handler")
if configReporter.GetWithDefault("disable", "") != "true" {
ctx := logInternal.NewContextWithLogger(context.Background(), s.Logger())
handler := blobEvents.NewUserDataDeletionHandler(ctx, s.blobClient)
handlers := []eventsCommon.EventHandler{handler}
runner = events.NewRunner(handlers)
} else {
runner = events.NewNoopRunner()
}

if err := runner.Initialize(); err != nil {
return errors.Wrap(err, "unable to initialize events runner")
Expand Down
2 changes: 1 addition & 1 deletion blob/service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var _ = Describe("Service", func() {
server = NewServer()
server.AppendHandlers(
CombineHandlers(
VerifyRequest(http.MethodPost, "/auth/serverlogin"),
VerifyRequest(http.MethodPost, "/serverlogin"),
VerifyHeaderKV("X-Tidepool-Server-Name", *provider.NameOutput),
VerifyHeaderKV("X-Tidepool-Server-Secret", serverSecret),
VerifyBody(nil),
Expand Down
6 changes: 5 additions & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ func NewWithErrorParser(cfg *Config, errorResponseParser ErrorResponseParser) (*
func (c *Client) ConstructURL(paths ...string) string {
segments := []string{}
for _, path := range paths {
segments = append(segments, url.PathEscape(strings.Trim(path, "/")))
escapedPath := url.PathEscape(strings.Trim(path, "/"))
if escapedPath == "" {
continue
}
segments = append(segments, escapedPath)
}
return fmt.Sprintf("%s/%s", strings.TrimRight(c.address, "/"), strings.Join(segments, "/"))
}
Expand Down
3 changes: 2 additions & 1 deletion client/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
"fmt"
"net/url"

"github.com/kelseyhightower/envconfig"
Expand Down Expand Up @@ -37,7 +38,7 @@ func (c *Config) Validate() error {
if c.Address == "" {
return errors.New("address is missing")
} else if _, err := url.Parse(c.Address); err != nil {
return errors.New("address is invalid")
return fmt.Errorf("address is invalid: %w", err)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion client/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ var _ = Describe("Config", func() {

It("returns an error if the address is not a parseable URL", func() {
cfg.Address = "Not%Parseable"
Expect(cfg.Validate()).To(MatchError("address is invalid"))
Expect(cfg.Validate()).To(MatchError("address is invalid: parse \"Not%Parseable\": invalid URL escape \"%Pa\""))
})

It("returns success", func() {
Expand Down
3 changes: 2 additions & 1 deletion data/service/api/v1/datasets_data_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ func CollectProvenanceInfo(ctx context.Context, req *rest.Request, authDetails r
if token != "" && shouldHaveJWT(authDetails) {
claims := &TokenClaims{}
if _, _, err := jwt.NewParser().ParseUnverified(token, claims); err != nil {
lgr.WithError(err).Warn("Unable to parse access token for provenance")
// temp comment out because makes realtime viewing rough
// lgr.WithError(err).Warn("Unable to parse access token for provenance")
} else {
provenance.ClientID = claims.ClientID
}
Expand Down
20 changes: 14 additions & 6 deletions data/service/service/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (s *Standard) Initialize(provider application.Provider) error {
if err := s.initializeDataSourceClient(); err != nil {
return err
}
if err := s.initializeUserEventsHandler(); err != nil {
if err := s.initializeUserEventsHandler(provider); err != nil {
return err
}
if err := s.initializeTwiistServiceAccountAuthorizer(); err != nil {
Expand Down Expand Up @@ -430,14 +430,22 @@ func (s *Standard) initializeServer() error {
return nil
}

func (s *Standard) initializeUserEventsHandler() error {
func (s *Standard) initializeUserEventsHandler(provider application.Provider) error {
s.Logger().Debug("Initializing user events handler")
sarama.Logger = log.New(os.Stdout, "SARAMA ", log.LstdFlags|log.Lshortfile)

ctx := logInternal.NewContextWithLogger(context.Background(), s.Logger())
handler := dataEvents.NewUserDataDeletionHandler(ctx, s.dataStore, s.dataSourceStructuredStore)
handlers := []eventsCommon.EventHandler{handler}
runner := events.NewRunner(handlers)
var runner events.Runner

configReporter := provider.ConfigReporter().WithScopes("user", "events", "handler")
if configReporter.GetWithDefault("disable", "") != "true" {
ctx := logInternal.NewContextWithLogger(context.Background(), s.Logger())
handler := dataEvents.NewUserDataDeletionHandler(ctx, s.dataStore, s.dataSourceStructuredStore)
handlers := []eventsCommon.EventHandler{handler}
runner = events.NewRunner(handlers)
} else {
runner = events.NewNoopRunner()
}

if err := runner.Initialize(); err != nil {
return errors.Wrap(err, "unable to initialize user events handler runner")
}
Expand Down
18 changes: 4 additions & 14 deletions data/store/mongo/mongo_data_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,6 @@ func (d *DataSetRepository) EnsureIndexes() error {
Options: options.Index().
SetName("UserIdTypeWeighted_v2"),
},
{
Keys: bson.D{
{Key: "origin.id", Value: 1},
{Key: "type", Value: 1},
{Key: "deletedTime", Value: -1},
{Key: "_active", Value: 1},
},
Options: options.Index().
SetName("OriginId"),
},
{
Keys: bson.D{
{Key: "uploadId", Value: 1},
Expand Down Expand Up @@ -330,14 +320,14 @@ func (d *DataSetRepository) GetDataSetsForUserByID(ctx context.Context, userID s
SetSort(bson.M{"createdTime": -1})
cursor, err := d.Find(ctx, selector, opts)

loggerFields := log.Fields{"userId": userID, "dataSetsCount": len(dataSets), "duration": time.Since(now) / time.Microsecond}
log.LoggerFromContext(ctx).WithFields(loggerFields).WithError(err).Debug("GetDataSetsForUserByID")

if err != nil {
return nil, errors.Wrap(err, "unable to get data sets for user by id")
}

if err = cursor.All(ctx, &dataSets); err != nil {
err = cursor.All(ctx, &dataSets)
loggerFields := log.Fields{"userId": userID, "dataSetsCount": len(dataSets), "duration": time.Since(now) / time.Microsecond}
log.LoggerFromContext(ctx).WithFields(loggerFields).WithError(err).Debug("GetDataSetsForUserByID")
if err != nil {
return nil, errors.Wrap(err, "unable to decode data sets for user by id")
}

Expand Down
3 changes: 2 additions & 1 deletion data/store/mongo/mongo_datum.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,8 @@ func (d *DatumRepository) ArchiveDeviceDataUsingHashesFromDataSet(ctx context.Co
"modifiedTime": timestamp,
}
unset := bson.M{}
updateInfo, err = d.UpdateMany(ctx, selector, d.ConstructUpdate(set, unset))
opts := options.Update()
updateInfo, err = d.UpdateMany(ctx, selector, d.ConstructUpdate(set, unset), opts)
}

loggerFields := log.Fields{"userId": dataSet.UserID, "deviceId": *dataSet.DeviceID, "updateInfo": updateInfo, "duration": time.Since(now) / time.Microsecond}
Expand Down
4 changes: 0 additions & 4 deletions data/store/mongo/mongo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,10 +371,6 @@ var _ = Describe("Mongo", Label("mongodb", "slow", "integration"), func() {
"Key": Equal(storeStructuredMongoTest.MakeKeySlice("_userId", "_active", "type", "-time")),
"Name": Equal("UserIdTypeWeighted_v2"),
}),
MatchFields(IgnoreExtras, Fields{
"Key": Equal(storeStructuredMongoTest.MakeKeySlice("origin.id", "type", "-deletedTime", "_active")),
"Name": Equal("OriginId"),
}),
MatchFields(IgnoreExtras, Fields{
"Key": Equal(storeStructuredMongoTest.MakeKeySlice("uploadId", "type", "-deletedTime", "_active")),
"Name": Equal("UploadId"),
Expand Down
1 change: 1 addition & 0 deletions env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export TIDEPOOL_USER_CLIENT_ADDRESS="http://localhost:8009"

export TIDEPOOL_AUTH_CLIENT_EXTERNAL_ADDRESS="http://localhost:8009"
export TIDEPOOL_AUTH_CLIENT_EXTERNAL_SERVER_SESSION_TOKEN_SECRET="This needs to be the same secret everywhere. YaHut75NsK1f9UKUXuWqxNN0RUwHFBCy"
export TIDEPOOL_AUTH_CLIENT_EXTERNAL_PATH_PREFIX="auth"

export TIDEPOOL_AUTH_SERVICE_SERVER_ADDRESS=":9222"
export TIDEPOOL_BLOB_SERVICE_SERVER_ADDRESS=":9225"
Expand Down
25 changes: 25 additions & 0 deletions events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,28 @@ func (r *runner) Terminate() error {
}
return nil
}

type noopRunner struct {
terminate chan struct{}
}

func (n *noopRunner) Initialize() error {
n.terminate = make(chan struct{}, 0)
return nil
}

func (n *noopRunner) Run() error {
<-n.terminate
return nil
}

func (n *noopRunner) Terminate() error {
n.terminate <- struct{}{}
return nil
}

var _ Runner = &noopRunner{}

func NewNoopRunner() Runner {
return &noopRunner{}
}
2 changes: 1 addition & 1 deletion platform/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ var _ = Describe("Config", func() {

It("returns an error if the address is not a parseable URL", func() {
cfg.Address = "Not%Parseable"
Expect(cfg.Validate()).To(MatchError("address is invalid"))
Expect(cfg.Validate()).To(MatchError("address is invalid: parse \"Not%Parseable\": invalid URL escape \"%Pa\""))
})

It("returns success", func() {
Expand Down
2 changes: 1 addition & 1 deletion prescription/application/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var _ = Describe("Application", func() {
server = NewServer()
server.AppendHandlers(
CombineHandlers(
VerifyRequest(http.MethodPost, "/auth/serverlogin"),
VerifyRequest(http.MethodPost, "/serverlogin"),
VerifyHeaderKV("X-Tidepool-Server-Name", *prvdr.NameOutput),
VerifyHeaderKV("X-Tidepool-Server-Secret", serverSecret),
VerifyBody(nil),
Expand Down
2 changes: 1 addition & 1 deletion service/service/DEPRECATED_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var _ = Describe("DEPRECATEDService", func() {
Expect(server).ToNot(BeNil())
server.AppendHandlers(
CombineHandlers(
VerifyRequest("POST", "/auth/serverlogin"),
VerifyRequest("POST", "/serverlogin"),
VerifyHeaderKV("X-Tidepool-Server-Name", *provider.NameOutput),
VerifyHeaderKV("X-Tidepool-Server-Secret", serverSecret),
VerifyBody(nil),
Expand Down
19 changes: 10 additions & 9 deletions store/structured/mongo/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ func LoadConfig() (*Config, error) {

// Config describe parameters need to make a connection to a Mongo database
type Config struct {
Scheme string `json:"scheme" envconfig:"TIDEPOOL_STORE_SCHEME"`
Addresses []string `json:"addresses" envconfig:"TIDEPOOL_STORE_ADDRESSES" required:"true"`
TLS bool `json:"tls" envconfig:"TIDEPOOL_STORE_TLS" default:"true"`
Database string `json:"database" envconfig:"TIDEPOOL_STORE_DATABASE" required:"true"`
CollectionPrefix string `json:"collectionPrefix" envconfig:"TIDEPOOL_STORE_COLLECTION_PREFIX"`
Username *string `json:"-" envconfig:"TIDEPOOL_STORE_USERNAME"`
Password *string `json:"-" envconfig:"TIDEPOOL_STORE_PASSWORD"`
Timeout time.Duration `json:"timeout" envconfig:"TIDEPOOL_STORE_TIMEOUT" default:"60s"`
OptParams *string `json:"optParams" envconfig:"TIDEPOOL_STORE_OPT_PARAMS"`
Scheme string `json:"scheme" envconfig:"TIDEPOOL_STORE_SCHEME"`
Addresses []string `json:"addresses" envconfig:"TIDEPOOL_STORE_ADDRESSES" required:"true"`
TLS bool `json:"tls" envconfig:"TIDEPOOL_STORE_TLS" default:"true"`
Database string `json:"database" envconfig:"TIDEPOOL_STORE_DATABASE" required:"true"`
CollectionPrefix string `json:"collectionPrefix" envconfig:"TIDEPOOL_STORE_COLLECTION_PREFIX"`
Username *string `json:"-" envconfig:"TIDEPOOL_STORE_USERNAME"`
Password *string `json:"-" envconfig:"TIDEPOOL_STORE_PASSWORD"`
Timeout time.Duration `json:"timeout" envconfig:"TIDEPOOL_STORE_TIMEOUT" default:"60s"`
OptParams *string `json:"optParams" envconfig:"TIDEPOOL_STORE_OPT_PARAMS"`
DisableIndexCreation bool `json:"disableIndexCreation" envconfig:"TIDEPOOL_DISABLE_INDEX_CREATION"`
}

// AsConnectionString constructs a MongoDB connection string from a Config
Expand Down
Loading