Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ dist: jammy
language: go

go:
- 1.24.3
- 1.24.5

services:
- docker
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG GOLANG_VERSION=1.24.3-alpine
ARG GOLANG_VERSION=1.24.5-alpine
ARG MONGO_VERSION=6.0.23
ARG PLUGIN_VISIBILITY=public

Expand Down
51 changes: 24 additions & 27 deletions auth/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,33 +72,6 @@ func NewClient(cfg *Config, authorizeAs platform.AuthorizeAs, name string, lgr l
}, nil
}

func (c *Client) ListUserProviderSessions(ctx context.Context, userID string, filter *auth.ProviderSessionFilter, pagination *page.Pagination) (auth.ProviderSessions, error) {
if ctx == nil {
return nil, errors.New("context is missing")
}
if userID == "" {
return nil, errors.New("user id is missing")
}
if filter == nil {
filter = auth.NewProviderSessionFilter()
} else if err := structureValidator.New(log.LoggerFromContext(ctx)).Validate(filter); err != nil {
return nil, errors.Wrap(err, "filter is invalid")
}
if pagination == nil {
pagination = page.NewPagination()
} else if err := structureValidator.New(log.LoggerFromContext(ctx)).Validate(pagination); err != nil {
return nil, errors.Wrap(err, "pagination is invalid")
}

url := c.client.ConstructURL("v1", "users", userID, "provider_sessions")
providerSessions := auth.ProviderSessions{}
if err := c.client.RequestData(ctx, http.MethodGet, url, []request.RequestMutator{filter, pagination}, nil, &providerSessions); err != nil {
return nil, err
}

return providerSessions, nil
}

func (c *Client) CreateUserProviderSession(ctx context.Context, userID string, create *auth.ProviderSessionCreate) (*auth.ProviderSession, error) {
if ctx == nil {
return nil, errors.New("context is missing")
Expand Down Expand Up @@ -133,6 +106,30 @@ func (c *Client) DeleteUserProviderSessions(ctx context.Context, userID string)
return c.client.RequestData(ctx, http.MethodDelete, url, nil, nil, nil)
}

func (c *Client) ListProviderSessions(ctx context.Context, filter *auth.ProviderSessionFilter, pagination *page.Pagination) (auth.ProviderSessions, error) {
if ctx == nil {
return nil, errors.New("context is missing")
}
if filter == nil {
filter = auth.NewProviderSessionFilter()
} else if err := structureValidator.New(log.LoggerFromContext(ctx)).Validate(filter); err != nil {
return nil, errors.Wrap(err, "filter is invalid")
}
if pagination == nil {
pagination = page.NewPagination()
} else if err := structureValidator.New(log.LoggerFromContext(ctx)).Validate(pagination); err != nil {
return nil, errors.Wrap(err, "pagination is invalid")
}

url := c.client.ConstructURL("v1", "provider_sessions")
providerSessions := auth.ProviderSessions{}
if err := c.client.RequestData(ctx, http.MethodGet, url, []request.RequestMutator{filter, pagination}, nil, &providerSessions); err != nil {
return nil, err
}

return providerSessions, nil
}

func (c *Client) GetProviderSession(ctx context.Context, id string) (*auth.ProviderSession, error) {
if ctx == nil {
return nil, errors.New("context is missing")
Expand Down
9 changes: 8 additions & 1 deletion auth/provider_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/tidepool-org/platform/request"
"github.com/tidepool-org/platform/structure"
structureValidator "github.com/tidepool-org/platform/structure/validator"
"github.com/tidepool-org/platform/user"
)

const (
Expand All @@ -26,16 +27,17 @@ func ProviderTypes() []string {
}

type ProviderSessionAccessor interface {
ListUserProviderSessions(ctx context.Context, userID string, filter *ProviderSessionFilter, pagination *page.Pagination) (ProviderSessions, error)
CreateUserProviderSession(ctx context.Context, userID string, create *ProviderSessionCreate) (*ProviderSession, error)
DeleteUserProviderSessions(ctx context.Context, userID string) error

ListProviderSessions(ctx context.Context, filter *ProviderSessionFilter, pagination *page.Pagination) (ProviderSessions, error)
GetProviderSession(ctx context.Context, id string) (*ProviderSession, error)
UpdateProviderSession(ctx context.Context, id string, update *ProviderSessionUpdate) (*ProviderSession, error)
DeleteProviderSession(ctx context.Context, id string) error
}

type ProviderSessionFilter struct {
UserID *string `json:"userId,omitempty"`
Type *string `json:"type,omitempty"`
Name *string `json:"name,omitempty"`
ExternalID *string `json:"externalId,omitempty"`
Expand All @@ -46,19 +48,24 @@ func NewProviderSessionFilter() *ProviderSessionFilter {
}

func (p *ProviderSessionFilter) Parse(parser structure.ObjectParser) {
p.UserID = parser.String("userId")
p.Type = parser.String("type")
p.Name = parser.String("name")
p.ExternalID = parser.String("externalId")
}

func (p *ProviderSessionFilter) Validate(validator structure.Validator) {
validator.String("userId", p.UserID).Using(user.IDValidator)
validator.String("type", p.Type).OneOf(ProviderTypes()...)
validator.String("name", p.Name).Using(ProviderNameValidator)
validator.String("externalId", p.ExternalID).Using(ProviderExternalIDValidator)
}

func (p *ProviderSessionFilter) MutateRequest(req *http.Request) error {
parameters := map[string]string{}
if p.UserID != nil {
parameters["userId"] = *p.UserID
}
if p.Type != nil {
parameters["type"] = *p.Type
}
Expand Down
6 changes: 4 additions & 2 deletions auth/service/api/v1/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,10 @@ func (r *Router) UserOAuthProviderAuthorizeDelete(res rest.ResponseWriter, req *
}

providerSessionFilter := auth.NewProviderSessionFilter()
providerSessionFilter.UserID = pointer.FromString(userID)
providerSessionFilter.Type = pointer.FromString(prvdr.Type())
providerSessionFilter.Name = pointer.FromString(prvdr.Name())
providerSessions, err := r.AuthClient().ListUserProviderSessions(ctx, userID, providerSessionFilter, page.NewPagination())
providerSessions, err := r.AuthClient().ListProviderSessions(ctx, providerSessionFilter, page.NewPagination())
if err != nil {
responder.Error(http.StatusInternalServerError, err)
return
Expand Down Expand Up @@ -179,9 +180,10 @@ func (r *Router) OAuthProviderRedirectGet(res rest.ResponseWriter, req *rest.Req
}

filter := auth.NewProviderSessionFilter()
filter.UserID = pointer.FromString(restrictedToken.UserID)
filter.Type = pointer.FromString(prvdr.Type())
filter.Name = pointer.FromString(prvdr.Name())
providerSessions, err := r.AuthClient().ListUserProviderSessions(ctx, restrictedToken.UserID, filter, nil)
providerSessions, err := r.AuthClient().ListProviderSessions(ctx, filter, nil)
if err != nil {
r.htmlOnError(res, req, err)
return
Expand Down
40 changes: 17 additions & 23 deletions auth/service/api/v1/provider_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (

func (r *Router) ProviderSessionsRoutes() []*rest.Route {
return []*rest.Route{
rest.Get("/v1/users/:userId/provider_sessions", serviceApi.RequireServer(r.ListUserProviderSessions)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep this for backward compatibility or is it only used by other platform services?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this endpoint required a server token (i.e. serviceApi.RequireServer) I did a search through all of the backend code for provider_sessions (and downstream usages, specifically ListUserProviderSessions) and it was not used anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new endpoint ListProviderSessions is used now by the twiist data ingestion code in the data service to communicate with the auth service.

rest.Post("/v1/users/:userId/provider_sessions", serviceApi.RequireServer(r.CreateUserProviderSession)),
rest.Delete("/v1/users/:userId/provider_sessions", serviceApi.RequireServer(r.DeleteUserProviderSessions)),
rest.Get("/v1/provider_sessions", serviceApi.RequireServer(r.ListProviderSessions)),
rest.Get("/v1/provider_sessions/:id", serviceApi.RequireServer(r.GetProviderSession)),
rest.Put("/v1/provider_sessions/:id", serviceApi.RequireServer(r.UpdateProviderSession)),
rest.Delete("/v1/provider_sessions/:id", serviceApi.RequireServer(r.DeleteProviderSession)),
Expand All @@ -28,7 +28,7 @@ func (r *Router) ProviderSessionsRoutes() []*rest.Route {
}
}

func (r *Router) ListUserProviderSessions(res rest.ResponseWriter, req *rest.Request) {
func (r *Router) CreateUserProviderSession(res rest.ResponseWriter, req *rest.Request) {
responder := request.MustNewResponder(res, req)

userID := req.PathParam("userId")
Expand All @@ -37,23 +37,22 @@ func (r *Router) ListUserProviderSessions(res rest.ResponseWriter, req *rest.Req
return
}

filter := auth.NewProviderSessionFilter()
pagination := page.NewPagination()
if err := request.DecodeRequestQuery(req.Request, filter, pagination); err != nil {
create := auth.NewProviderSessionCreate()
if err := request.DecodeRequestBody(req.Request, create); err != nil {
responder.Error(http.StatusBadRequest, err)
return
}

providerSessions, err := r.AuthClient().ListUserProviderSessions(req.Context(), userID, filter, pagination)
providerSession, err := r.AuthClient().CreateUserProviderSession(req.Context(), userID, create)
if err != nil {
responder.Error(http.StatusInternalServerError, err)
return
}

responder.Data(http.StatusOK, providerSessions)
responder.Data(http.StatusCreated, providerSession)
}

func (r *Router) CreateUserProviderSession(res rest.ResponseWriter, req *rest.Request) {
func (r *Router) DeleteUserProviderSessions(res rest.ResponseWriter, req *rest.Request) {
responder := request.MustNewResponder(res, req)

userID := req.PathParam("userId")
Expand All @@ -62,36 +61,31 @@ func (r *Router) CreateUserProviderSession(res rest.ResponseWriter, req *rest.Re
return
}

create := auth.NewProviderSessionCreate()
if err := request.DecodeRequestBody(req.Request, create); err != nil {
responder.Error(http.StatusBadRequest, err)
return
}

providerSession, err := r.AuthClient().CreateUserProviderSession(req.Context(), userID, create)
if err != nil {
if err := r.AuthClient().DeleteUserProviderSessions(req.Context(), userID); err != nil {
responder.Error(http.StatusInternalServerError, err)
return
}

responder.Data(http.StatusCreated, providerSession)
responder.Empty(http.StatusNoContent)
}

func (r *Router) DeleteUserProviderSessions(res rest.ResponseWriter, req *rest.Request) {
func (r *Router) ListProviderSessions(res rest.ResponseWriter, req *rest.Request) {
responder := request.MustNewResponder(res, req)

userID := req.PathParam("userId")
if userID == "" {
responder.Error(http.StatusBadRequest, request.ErrorParameterMissing("userId"))
filter := auth.NewProviderSessionFilter()
pagination := page.NewPagination()
if err := request.DecodeRequestQuery(req.Request, filter, pagination); err != nil {
responder.Error(http.StatusBadRequest, err)
return
}

if err := r.AuthClient().DeleteUserProviderSessions(req.Context(), userID); err != nil {
providerSessions, err := r.AuthClient().ListProviderSessions(req.Context(), filter, pagination)
if err != nil {
responder.Error(http.StatusInternalServerError, err)
return
}

responder.Empty(http.StatusNoContent)
responder.Data(http.StatusOK, providerSessions)
}

func (r *Router) GetProviderSession(res rest.ResponseWriter, req *rest.Request) {
Expand Down
16 changes: 10 additions & 6 deletions auth/service/service/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/tidepool-org/platform/log"
"github.com/tidepool-org/platform/page"
"github.com/tidepool-org/platform/platform"
"github.com/tidepool-org/platform/pointer"
"github.com/tidepool-org/platform/provider"
structureValidator "github.com/tidepool-org/platform/structure/validator"
)
Expand Down Expand Up @@ -53,11 +54,6 @@ func NewClient(cfg *authClient.ExternalConfig, authorizeAs platform.AuthorizeAs,
}, nil
}

func (c *Client) ListUserProviderSessions(ctx context.Context, userID string, filter *auth.ProviderSessionFilter, pagination *page.Pagination) (auth.ProviderSessions, error) {
repository := c.authStore.NewProviderSessionRepository()
return repository.ListUserProviderSessions(ctx, userID, filter, pagination)
}

func (c *Client) CreateUserProviderSession(ctx context.Context, userID string, create *auth.ProviderSessionCreate) (*auth.ProviderSession, error) {
prvdr, err := c.providerFactory.Get(create.Type, create.Name)
if err != nil {
Expand Down Expand Up @@ -97,7 +93,10 @@ func (c *Client) DeleteUserProviderSessions(ctx context.Context, userID string)
repository := c.authStore.NewProviderSessionRepository()

// TODO: Add pagination if/when we ever get over one page of provider sessions
if providerSessions, err := repository.ListUserProviderSessions(ctx, userID, nil, nil); err != nil {
filter := &auth.ProviderSessionFilter{
UserID: pointer.FromString(userID),
}
if providerSessions, err := repository.ListProviderSessions(ctx, filter, nil); err != nil {
logger.WithError(err).Warn("Unable to list user provider sessions")
} else {
for _, providerSession := range providerSessions {
Expand Down Expand Up @@ -153,6 +152,11 @@ func (c *Client) DeleteAllProviderSessions(ctx context.Context, filter auth.Prov
return nil
}

func (c *Client) ListProviderSessions(ctx context.Context, filter *auth.ProviderSessionFilter, pagination *page.Pagination) (auth.ProviderSessions, error) {
repository := c.authStore.NewProviderSessionRepository()
return repository.ListProviderSessions(ctx, filter, pagination)
}

func (c *Client) GetProviderSession(ctx context.Context, id string) (*auth.ProviderSession, error) {
repository := c.authStore.NewProviderSessionRepository()
return repository.GetProviderSession(ctx, id)
Expand Down
Loading