Skip to content

Commit

Permalink
[BACK-3375] Set confirmations userId if userId empty and email matches
Browse files Browse the repository at this point in the history
user before retrieving clinician or personal invites. Allows to
associate/retrieve confirmations by userId instead of email.
  • Loading branch information
lostlevels committed Jan 24, 2025
1 parent 6115318 commit 5c21cb5
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 3 deletions.
10 changes: 9 additions & 1 deletion api/clinicianInvites.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,15 @@ func (a *Api) GetClinicianInvitations(res http.ResponseWriter, req *http.Request
return
}

found, err := a.Store.FindConfirmations(ctx, &models.Confirmation{Email: invitedUsr.Emails[0], Type: models.TypeClinicianInvite}, models.StatusPending)
// Populate userId of the confirmations for this user's userId if is not set. This will allow us to query by userId.
inviteType := models.TypeClinicianInvite
inviteStatus := models.StatusPending
if err := a.addUserIdsToEmptyPendingInvites(ctx, invitedUsr, inviteType, inviteStatus); err != nil {
a.sendError(ctx, res, http.StatusInternalServerError, STATUS_ERR_UPDATING_CONFIRMATION, err)
return
}

found, err := a.Store.FindConfirmations(ctx, &models.Confirmation{UserId: invitedUsr.UserID, Type: inviteType}, inviteStatus)
if err != nil {
a.sendError(ctx, res, http.StatusInternalServerError, STATUS_ERR_FINDING_CONFIRMATION, err)
return
Expand Down
12 changes: 12 additions & 0 deletions api/hydrophoneApi.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const (
STATUS_ERR_SAVING_CONFIRMATION = "Error saving the confirmation"
STATUS_ERR_SENDING_EMAIL = "Error sending email"
STATUS_ERR_SETTING_PERMISSIONS = "Error setting permissions"
STATUS_ERR_UPDATING_CONFIRMATION = "Error updating confirmation"
STATUS_ERR_UPDATING_USER = "Error updating user"
STATUS_ERR_VALIDATING_CONTEXT = "Error validating the confirmation context"

Expand Down Expand Up @@ -511,6 +512,17 @@ func (a *Api) ensureIdSet(ctx context.Context, userId string, confirmations []*m
}
}

func (a *Api) addUserIdsToEmptyPendingInvites(ctx context.Context, user *shoreline.UserData, inviteType models.Type, inviteStatus models.Status) error {
opts := clients.FilterOpts{AllowEmptyUserID: true}
filter := &models.Confirmation{Email: user.Emails[0], UserId: "", Type: inviteType}
userlessConfirms, err := a.Store.FindConfirmationsWithOpts(ctx, filter, opts, inviteStatus)
if err != nil {
return err
}
a.ensureIdSet(ctx, user.UserID, userlessConfirms)
return nil
}

// Populate restrictions
func (a *Api) populateRestrictions(ctx context.Context, user shoreline.UserData, td shoreline.TokenData, confirmations []*models.Confirmation) error {
for _, conf := range confirmations {
Expand Down
10 changes: 9 additions & 1 deletion api/invite.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,16 @@ func (a *Api) GetReceivedInvitations(res http.ResponseWriter, req *http.Request,

invitedUsr := a.findExistingUser(ctx, inviteeID, req.Header.Get(TP_SESSION_TOKEN))

// Populate userId of the confirmations for this user's userId if is not set. This will allow us to query by userId.
inviteType := models.TypeCareteamInvite
inviteStatus := models.StatusPending
if err := a.addUserIdsToEmptyPendingInvites(ctx, invitedUsr, inviteType, inviteStatus); err != nil {
a.sendError(ctx, res, http.StatusInternalServerError, STATUS_ERR_UPDATING_CONFIRMATION, err)
return
}

//find all oustanding invites were this user is the invite//
found, err := a.Store.FindConfirmations(ctx, &models.Confirmation{Email: invitedUsr.Emails[0], Type: models.TypeCareteamInvite}, models.StatusPending)
found, err := a.Store.FindConfirmations(ctx, &models.Confirmation{UserId: invitedUsr.UserID, Type: inviteType}, inviteStatus)
if err != nil {
a.sendError(ctx, res, http.StatusInternalServerError, STATUS_ERR_FINDING_CONFIRMATION, err,
"while finding pending invites")
Expand Down
15 changes: 15 additions & 0 deletions clients/mockStoreClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,21 @@ func (d *MockStoreClient) FindConfirmation(ctx context.Context, notification *mo
return notification, nil
}

func (d *MockStoreClient) FindConfirmationsWithOpts(ctx context.Context, confirmation *models.Confirmation, filter FilterOpts, statuses ...models.Status) (results []*models.Confirmation, err error) {
if d.doBad {
return nil, errors.New("FindConfirmationsWithOpts failure")
}
if d.returnNone {
return nil, nil
}

confirmation.Created = time.Now().AddDate(0, 0, -3) // created three days ago
confirmation.Context = []byte(`{"view":{}, "note":{}}`)
confirmation.UpdateStatus(statuses[0])

return []*models.Confirmation{confirmation}, nil
}

func (d *MockStoreClient) FindConfirmations(ctx context.Context, confirmation *models.Confirmation, statuses ...models.Status) (results []*models.Confirmation, err error) {
if d.doBad {
return nil, errors.New("FindConfirmation failure")
Expand Down
6 changes: 5 additions & 1 deletion clients/mongoStoreClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ func (c *MongoStoreClient) FindConfirmation(ctx context.Context, confirmation *m

// FindConfirmations - find and return existing confirmations
func (c *MongoStoreClient) FindConfirmations(ctx context.Context, confirmation *models.Confirmation, statuses ...models.Status) (results []*models.Confirmation, err error) {
return c.FindConfirmationsWithOpts(ctx, confirmation, FilterOpts{}, statuses...)
}

func (c *MongoStoreClient) FindConfirmationsWithOpts(ctx context.Context, confirmation *models.Confirmation, extraFilters FilterOpts, statuses ...models.Status) (results []*models.Confirmation, err error) {
var query bson.M = bson.M{}

if confirmation.Email != "" {
Expand All @@ -171,7 +175,7 @@ func (c *MongoStoreClient) FindConfirmations(ctx context.Context, confirmation *
if confirmation.CreatorId != "" {
query["creatorId"] = confirmation.CreatorId
}
if confirmation.UserId != "" {
if confirmation.UserId != "" || extraFilters.AllowEmptyUserID {
query["userId"] = confirmation.UserId
}
if confirmation.ClinicId != "" {
Expand Down
7 changes: 7 additions & 0 deletions clients/storeClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ import (
"github.com/tidepool-org/hydrophone/models"
)

// FilterOpts allows further filtering options of Confirmation retrieval for more specific use cases.
// The zero value is fine for the "default" case of filtering on the logical AND of non empty fields.
type FilterOpts struct {
AllowEmptyUserID bool // If true, then specifically query for an empty string userId instead of not including in the query.
}

type StoreClient interface {
Ping(ctx context.Context) error
UpsertConfirmation(ctx context.Context, confirmation *models.Confirmation) error
FindConfirmations(ctx context.Context, confirmation *models.Confirmation, statuses ...models.Status) (results []*models.Confirmation, err error)
FindConfirmationsWithOpts(ctx context.Context, confirmation *models.Confirmation, opts FilterOpts, statuses ...models.Status) (results []*models.Confirmation, err error)
FindConfirmation(ctx context.Context, confirmation *models.Confirmation) (result *models.Confirmation, err error)
RemoveConfirmation(ctx context.Context, confirmation *models.Confirmation) error
RemoveConfirmationsForUser(ctx context.Context, userId string) error
Expand Down

0 comments on commit 5c21cb5

Please sign in to comment.