From 7efb9d2897679f90d2705a5ae32b0387c58211f2 Mon Sep 17 00:00:00 2001 From: Jeroen Rinzema Date: Tue, 23 Jun 2026 00:08:46 +0200 Subject: [PATCH 1/4] feat(client)!: move the client API under /projects/{projectID} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The client API derived the project from the authenticating credential, so a trusted-issuer JWT was resolved by its self-asserted `iss` with no project scope — a cross-tenant resolution gap. The project is now an explicit path segment on every authenticated client endpoint: /api/client/... -> /api/client/projects/{projectID}/... - spec + regenerated chi-server bindings; every handler takes projectID. - auth: every credential type fails closed unless its project matches the URL (enforceURLProject); trusted-issuer resolution is now (project_id, issuer). - store: GetTrustedIssuer is project-scoped; the issuer cache key is project-namespaced; UNIQUE(project_id, issuer) among active methods (denormalized project column + hard-delete child on soft-delete). - docs updated. BREAKING CHANGE: all client API paths require the project UUID; no legacy routes. --- docs/content/docs/api/client.mdx | 22 +- docs/content/docs/events.mdx | 12 +- docs/content/docs/organizations.mdx | 34 +- docs/content/docs/schedules.mdx | 8 +- docs/content/docs/sdks/android.mdx | 2 +- docs/content/docs/sdks/ios.mdx | 2 +- docs/content/docs/users.mdx | 2 +- internal/http/auth/auth.go | 65 + internal/http/auth/project_test.go | 83 + internal/http/auth/session.go | 6 + internal/http/auth/trusted_issuer.go | 19 +- .../http/controllers/v1/client/client_test.go | 84 +- .../http/controllers/v1/client/devices.go | 4 +- internal/http/controllers/v1/client/events.go | 4 +- internal/http/controllers/v1/client/inbox.go | 20 +- .../http/controllers/v1/client/inbox_test.go | 65 +- .../controllers/v1/client/oapi/resources.yml | 107 +- .../v1/client/oapi/resources_gen.go | 1485 +++++++++++------ .../controllers/v1/client/organizations.go | 8 +- .../http/controllers/v1/client/scheduled.go | 8 +- .../http/controllers/v1/client/sessions.go | 14 +- internal/http/controllers/v1/client/users.go | 4 +- internal/store/management/auth.go | 24 +- internal/store/management/auth_methods.go | 70 +- .../store/management/auth_methods_test.go | 84 +- ...6043_trusted_issuer_project_scope.down.sql | 8 + ...116043_trusted_issuer_project_scope.up.sql | 32 + 27 files changed, 1559 insertions(+), 717 deletions(-) create mode 100644 internal/http/auth/project_test.go create mode 100644 internal/store/management/migrations/1764116043_trusted_issuer_project_scope.down.sql create mode 100644 internal/store/management/migrations/1764116043_trusted_issuer_project_scope.up.sql diff --git a/docs/content/docs/api/client.mdx b/docs/content/docs/api/client.mdx index a698c5fd..732e116f 100644 --- a/docs/content/docs/api/client.mdx +++ b/docs/content/docs/api/client.mdx @@ -17,6 +17,8 @@ Authorization: Bearer YOUR_API_KEY You can [create and manage API keys](/settings/access) in your project settings. +Every client endpoint is namespaced under `/api/client/projects/{projectID}/...`, where `{projectID}` is your project's UUID. The project is now an explicit part of the URL rather than being derived from the API key, and the API key you use must be authorized for that project. + Client keys can ingest data but cannot read or modify existing resources. See [Access](/settings/access) for a full breakdown of roles and permissions. @@ -26,16 +28,16 @@ You can [create and manage API keys](/settings/access) in your project settings. | Method | Endpoint | Description | | ------ | -------- | ----------- | -| `POST` | `/api/client/users` | Create or update a user | -| `POST` | `/api/client/users/events` | Track user events | -| `DELETE` | `/api/client/users` | Delete a user | -| `POST` | `/api/client/organizations` | Create or update an organization | -| `POST` | `/api/client/organizations/events` | Track organization events | -| `POST` | `/api/client/users/scheduled` | Create or update a user schedule | -| `DELETE` | `/api/client/users/scheduled` | Delete a user schedule | -| `POST` | `/api/client/organizations/scheduled` | Create or update an org schedule | -| `DELETE` | `/api/client/organizations/scheduled` | Delete an org schedule | -| `POST` | `/api/client/users/devices` | Register a device for push notifications | +| `POST` | `/api/client/projects/{projectID}/users` | Create or update a user | +| `POST` | `/api/client/projects/{projectID}/users/events` | Track user events | +| `DELETE` | `/api/client/projects/{projectID}/users` | Delete a user | +| `POST` | `/api/client/projects/{projectID}/organizations` | Create or update an organization | +| `POST` | `/api/client/projects/{projectID}/organizations/events` | Track organization events | +| `POST` | `/api/client/projects/{projectID}/users/scheduled` | Create or update a user schedule | +| `DELETE` | `/api/client/projects/{projectID}/users/scheduled` | Delete a user schedule | +| `POST` | `/api/client/projects/{projectID}/organizations/scheduled` | Create or update an org schedule | +| `DELETE` | `/api/client/projects/{projectID}/organizations/scheduled` | Delete an org schedule | +| `POST` | `/api/client/projects/{projectID}/users/devices` | Register a device for push notifications | ## SDKs diff --git a/docs/content/docs/events.mdx b/docs/content/docs/events.mdx index 7d29e9cf..a87a3de4 100644 --- a/docs/content/docs/events.mdx +++ b/docs/content/docs/events.mdx @@ -22,7 +22,7 @@ Send events through the [JavaScript SDK](/sdks/javascript) or the client API. Ev ### User Events -`POST /api/client/users/events` +`POST /api/client/projects/{projectID}/users/events` @@ -70,7 +70,7 @@ Send events through the [JavaScript SDK](/sdks/javascript) or the client API. Ev ```bash # Target a specific user by identifier - curl -X POST https://your-instance.com/api/client/users/events \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/users/events \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '[ @@ -87,7 +87,7 @@ Send events through the [JavaScript SDK](/sdks/javascript) or the client API. Ev ]' # Target all users whose data matches a filter - curl -X POST https://your-instance.com/api/client/users/events \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/users/events \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '[ @@ -144,7 +144,7 @@ The example above sends the `feature.announcement` event to every user whose dat ### Organization Events -`POST /api/client/organizations/events` +`POST /api/client/projects/{projectID}/organizations/events` @@ -174,7 +174,7 @@ The example above sends the `feature.announcement` event to every user whose dat ```bash # Target a specific organization by identifier - curl -X POST https://your-instance.com/api/client/organizations/events \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/organizations/events \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '[ @@ -190,7 +190,7 @@ The example above sends the `feature.announcement` event to every user whose dat ]' # Target all organizations whose data matches a filter - curl -X POST https://your-instance.com/api/client/organizations/events \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/organizations/events \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '[ diff --git a/docs/content/docs/organizations.mdx b/docs/content/docs/organizations.mdx index 39631ebd..a500dbc6 100644 --- a/docs/content/docs/organizations.mdx +++ b/docs/content/docs/organizations.mdx @@ -55,7 +55,7 @@ Create organizations through the client API. If an organization with a matching ```bash - curl -X POST https://your-instance.com/api/client/organizations \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/organizations \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '{ @@ -111,7 +111,7 @@ Pass custom data as a JSON object when creating or updating an organization: ```bash - curl -X POST https://your-instance.com/api/client/organizations \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/organizations \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '{ @@ -216,7 +216,7 @@ Delete an organization by its identifier. This also removes all memberships. ```bash - curl -X DELETE https://your-instance.com/api/client/organizations \ + curl -X DELETE https://your-instance.com/api/client/projects/{projectID}/organizations \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '{ @@ -256,7 +256,7 @@ Add a user to an organization using their identifiers: ```bash - curl -X POST https://your-instance.com/api/client/organizations/users \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/organizations/users \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '{ @@ -315,7 +315,7 @@ Remove a user from an organization: ```bash - curl -X DELETE https://your-instance.com/api/client/organizations/users \ + curl -X DELETE https://your-instance.com/api/client/projects/{projectID}/organizations/users \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '{ @@ -358,7 +358,7 @@ Organizations have their own event timeline, separate from user events. Organiza ```bash - curl -X POST https://your-instance.com/api/client/organizations/events \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/organizations/events \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '[ @@ -450,14 +450,14 @@ Organization member has role = "admin" ## API Reference -All organization endpoints use the client API and authenticate with your project API key: - -| Method | Endpoint | Description | -| -------- | ------------------------------------- | ----------------------------- | -| `POST` | `/api/client/organizations` | Create or update organization | -| `DELETE` | `/api/client/organizations` | Delete organization | -| `POST` | `/api/client/organizations/users` | Add member | -| `DELETE` | `/api/client/organizations/users` | Remove member | -| `POST` | `/api/client/organizations/events` | Send organization events | -| `POST` | `/api/client/organizations/scheduled` | Create or update schedule | -| `DELETE` | `/api/client/organizations/scheduled` | Delete schedule | +All organization endpoints use the client API and authenticate with an API key authorized for your project. The project is now part of the URL path — every endpoint lives under `/api/client/projects/{projectID}/...`, where `{projectID}` is your project's UUID: + +| Method | Endpoint | Description | +| -------- | -------------------------------------------------------- | ----------------------------- | +| `POST` | `/api/client/projects/{projectID}/organizations` | Create or update organization | +| `DELETE` | `/api/client/projects/{projectID}/organizations` | Delete organization | +| `POST` | `/api/client/projects/{projectID}/organizations/users` | Add member | +| `DELETE` | `/api/client/projects/{projectID}/organizations/users` | Remove member | +| `POST` | `/api/client/projects/{projectID}/organizations/events` | Send organization events | +| `POST` | `/api/client/projects/{projectID}/organizations/scheduled` | Create or update schedule | +| `DELETE` | `/api/client/projects/{projectID}/organizations/scheduled` | Delete schedule | diff --git a/docs/content/docs/schedules.mdx b/docs/content/docs/schedules.mdx index d4870caf..a8914677 100644 --- a/docs/content/docs/schedules.mdx +++ b/docs/content/docs/schedules.mdx @@ -114,7 +114,7 @@ Schedules are assigned through the client API. The endpoints use an upsert model ### User Schedules ``` -POST /api/client/users/scheduled +POST /api/client/projects/{projectID}/users/scheduled ``` | Field | Type | Required | Description | @@ -131,7 +131,7 @@ POST /api/client/users/scheduled ### Organization Schedules ``` -POST /api/client/organizations/scheduled +POST /api/client/projects/{projectID}/organizations/scheduled ``` | Field | Type | Required | Description | @@ -148,7 +148,7 @@ POST /api/client/organizations/scheduled To remove a schedule assignment: ``` -DELETE /api/client/users/scheduled +DELETE /api/client/projects/{projectID}/users/scheduled ``` ```json @@ -159,7 +159,7 @@ DELETE /api/client/users/scheduled ``` ``` -DELETE /api/client/organizations/scheduled +DELETE /api/client/projects/{projectID}/organizations/scheduled ``` ```json diff --git a/docs/content/docs/sdks/android.mdx b/docs/content/docs/sdks/android.mdx index 4aa416d0..bd3667f8 100644 --- a/docs/content/docs/sdks/android.mdx +++ b/docs/content/docs/sdks/android.mdx @@ -20,4 +20,4 @@ The Lunogram Android SDK will provide native support for user identification, ev ## In the meantime -You can integrate directly with the [Client API](/api/client) using any HTTP library. All you need is a public API key and standard JSON requests. +You can integrate directly with the [Client API](/api/client) using any HTTP library. All you need is a public API key and standard JSON requests. Client requests go to `/api/client/projects/{projectID}/...`, where `{projectID}` is your project's UUID. diff --git a/docs/content/docs/sdks/ios.mdx b/docs/content/docs/sdks/ios.mdx index 8ebf8535..b4fa3e78 100644 --- a/docs/content/docs/sdks/ios.mdx +++ b/docs/content/docs/sdks/ios.mdx @@ -20,4 +20,4 @@ The Lunogram iOS SDK will provide native support for user identification, event ## In the meantime -You can integrate directly with the [Client API](/api/client) using any HTTP library. All you need is a public API key and standard JSON requests. +You can integrate directly with the [Client API](/api/client) using any HTTP library. All you need is a public API key and standard JSON requests. Client requests go to `/api/client/projects/{projectID}/...`, where `{projectID}` is your project's UUID. diff --git a/docs/content/docs/users.mdx b/docs/content/docs/users.mdx index f5bc6048..b2f726df 100644 --- a/docs/content/docs/users.mdx +++ b/docs/content/docs/users.mdx @@ -107,7 +107,7 @@ Store any data you need on user profiles. Custom properties let you personalize ```bash - curl -X POST https://your-instance.com/api/client/users \ + curl -X POST https://your-instance.com/api/client/projects/{projectID}/users \ -H "Authorization: Bearer sk_..." \ -H "Content-Type: application/json" \ -d '{ diff --git a/internal/http/auth/auth.go b/internal/http/auth/auth.go index 3edc6af8..2ea6e1b4 100644 --- a/internal/http/auth/auth.go +++ b/internal/http/auth/auth.go @@ -10,7 +10,9 @@ import ( "time" "github.com/getkin/kin-openapi/openapi3filter" + "github.com/go-chi/chi/v5" "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" "github.com/lunogram/platform/internal/config" "github.com/lunogram/platform/internal/rbac" "github.com/lunogram/platform/internal/store/management" @@ -136,6 +138,10 @@ func WithJWT(config config.Auth, mgmt *management.State) Handler { // when the request is browser-originated (carries an Origin header); browser and // mobile clients authenticate via a trusted issuer or a short-lived session // instead. The management surface accepts any valid key. +// +// On the client surface the request URL names the project it acts on. A key is +// rejected (closed) when the URL project cannot be resolved or does not match the +// key's project, so a credential can never act on a project it is not scoped to. func WithKey(mgmt *management.State, surface Surface) Handler { return func(ctx context.Context, tokenString string) (context.Context, error) { if tokenString == "" { @@ -151,6 +157,10 @@ func WithKey(mgmt *management.State, surface Surface) Handler { return ctx, err } + if err := enforceURLProject(ctx, surface, key.ProjectID); err != nil { + return ctx, err + } + actor := rbac.NewActor( rbac.ActorAPIKey, key.ID, @@ -187,6 +197,61 @@ func browserOriginated(ctx context.Context) bool { return r != nil && r.Header.Get("Origin") != "" } +// enforceURLProject binds a resolved credential to the project named in the +// request URL. On the client surface every route is mounted under +// /api/client/projects/{projectID}; the credential may act only on that project. +// It fails closed (ErrUnauthorized) when the URL project cannot be resolved or +// does not match the credential's project. The management surface carries no +// project in its URL, so the check is a no-op there. +func enforceURLProject(ctx context.Context, surface Surface, credentialProject uuid.UUID) error { + if surface != SurfaceClient { + return nil + } + urlProject, ok := projectFromRequest(ctx) + if !ok || urlProject != credentialProject { + return ErrUnauthorized + } + return nil +} + +// projectFromRequest resolves the {projectID} path parameter of the in-flight +// request. Authentication runs inside the OpenAPI validator middleware, after chi +// has matched the route, so the chi route context carries the parameter; it falls +// back to scanning the URL path so the resolution is robust to middleware +// ordering. ok is false when no valid project UUID is present. +func projectFromRequest(ctx context.Context) (uuid.UUID, bool) { + r := RequestFromContext(ctx) + if r == nil { + return uuid.Nil, false + } + raw := "" + if rc := chi.RouteContext(r.Context()); rc != nil { + raw = rc.URLParam("projectID") + } + if raw == "" { + raw = projectIDFromPath(r.URL.Path) + } + id, err := uuid.Parse(raw) + if err != nil { + return uuid.Nil, false + } + return id, true +} + +// projectIDFromPath extracts the path segment following /api/client/projects/. +// It is the fallback for when the chi route context is not populated. +func projectIDFromPath(path string) string { + const prefix = "/api/client/projects/" + if !strings.HasPrefix(path, prefix) { + return "" + } + rest := path[len(prefix):] + if i := strings.IndexByte(rest, '/'); i >= 0 { + return rest[:i] + } + return rest +} + // OAuthResponse represents the OAuth token response stored in cookies type OAuthResponse struct { AccessToken string `json:"access_token"` diff --git a/internal/http/auth/project_test.go b/internal/http/auth/project_test.go new file mode 100644 index 00000000..b07e9aa7 --- /dev/null +++ b/internal/http/auth/project_test.go @@ -0,0 +1,83 @@ +package auth + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-chi/chi/v5" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// ctxWithChiProject builds a request context carrying the given projectID as a +// chi URL param, mirroring the middleware position where the route is matched. +func ctxWithChiProject(projectID string) context.Context { + r := httptest.NewRequest(http.MethodPost, "/api/client/projects/"+projectID+"/users", nil) + rctx := chi.NewRouteContext() + rctx.URLParams.Add("projectID", projectID) + r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) + return withRequest(context.Background(), r) +} + +func TestProjectFromRequest(t *testing.T) { + t.Parallel() + + want := uuid.New() + + t.Run("resolves from chi route context", func(t *testing.T) { + got, ok := projectFromRequest(ctxWithChiProject(want.String())) + require.True(t, ok) + assert.Equal(t, want, got) + }) + + t.Run("falls back to the URL path", func(t *testing.T) { + // No chi route context, only the raw path. + r := httptest.NewRequest(http.MethodPost, "/api/client/projects/"+want.String()+"/users/events", nil) + got, ok := projectFromRequest(withRequest(context.Background(), r)) + require.True(t, ok) + assert.Equal(t, want, got) + }) + + t.Run("fails closed without a project", func(t *testing.T) { + r := httptest.NewRequest(http.MethodGet, "/api/management/projects", nil) + _, ok := projectFromRequest(withRequest(context.Background(), r)) + assert.False(t, ok) + }) + + t.Run("fails closed on a malformed project", func(t *testing.T) { + _, ok := projectFromRequest(ctxWithChiProject("not-a-uuid")) + assert.False(t, ok) + }) +} + +func TestEnforceURLProject(t *testing.T) { + t.Parallel() + + credential := uuid.New() + other := uuid.New() + + t.Run("management surface ignores the URL project", func(t *testing.T) { + // No request/project on the context at all. + err := enforceURLProject(context.Background(), SurfaceManagement, credential) + assert.NoError(t, err) + }) + + t.Run("client surface accepts a matching project", func(t *testing.T) { + err := enforceURLProject(ctxWithChiProject(credential.String()), SurfaceClient, credential) + assert.NoError(t, err) + }) + + t.Run("client surface rejects a credential for another project", func(t *testing.T) { + err := enforceURLProject(ctxWithChiProject(other.String()), SurfaceClient, credential) + assert.ErrorIs(t, err, ErrUnauthorized) + }) + + t.Run("client surface fails closed when the URL has no project", func(t *testing.T) { + r := httptest.NewRequest(http.MethodPost, "/api/client/users", nil) + err := enforceURLProject(withRequest(context.Background(), r), SurfaceClient, credential) + assert.ErrorIs(t, err, ErrUnauthorized) + }) +} diff --git a/internal/http/auth/session.go b/internal/http/auth/session.go index 9b25453c..97a85524 100644 --- a/internal/http/auth/session.go +++ b/internal/http/auth/session.go @@ -130,6 +130,12 @@ func WithSession(mgmt *management.State, signer *SessionSigner) Handler { return ctx, ErrUnauthorized } + // The session is only valid on its own project's URL; a token minted for + // project A may not be presented on a project-B route. + if err := enforceURLProject(ctx, SurfaceClient, method.ProjectID); err != nil { + return ctx, err + } + actor := rbac.NewActor( rbac.ActorEndUser, method.ID.String(), diff --git a/internal/http/auth/trusted_issuer.go b/internal/http/auth/trusted_issuer.go index 2c0ccd7f..3fde53fa 100644 --- a/internal/http/auth/trusted_issuer.go +++ b/internal/http/auth/trusted_issuer.go @@ -18,23 +18,32 @@ import ( var trustedIssuerAlgorithms = []string{"RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "PS256", "PS384", "PS512"} // WithTrustedIssuer authenticates an externally-issued JWT against a -// trusted_issuer auth method. It resolves the method by the token's `iss`, -// verifies the signature against the issuer's JWKS (cached) or configured PEM, -// enforces `exp`/`iss`/`aud` and an asymmetric algorithm, and builds an end-user -// actor carrying the verified subject. +// trusted_issuer auth method. It resolves the method by the URL project together +// with the token's `iss` (an issuer is scoped to its project, so a token can only +// ever resolve within the project named in its URL), verifies the signature +// against the issuer's JWKS (cached) or configured PEM, enforces `exp`/`iss`/`aud` +// and an asymmetric algorithm, and builds an end-user actor carrying the verified +// subject. func WithTrustedIssuer(mgmt *management.State, cache *jwks.Cache) Handler { return func(ctx context.Context, tokenString string) (context.Context, error) { if tokenString == "" { return ctx, ErrUnauthorized } + // The URL names the project the token must belong to; resolution is scoped + // to it so a self-asserted `iss` can never reach another project's method. + projectID, ok := projectFromRequest(ctx) + if !ok { + return ctx, ErrUnauthorized + } + // Read the issuer without verifying, to select the verification keys. issuer, err := unverifiedIssuer(tokenString) if err != nil || issuer == "" { return ctx, ErrUnauthorized } - method, err := mgmt.GetTrustedIssuerByIssuer(ctx, issuer) + method, err := mgmt.GetTrustedIssuer(ctx, projectID, issuer) if err != nil { return ctx, ErrUnauthorized } diff --git a/internal/http/controllers/v1/client/client_test.go b/internal/http/controllers/v1/client/client_test.go index 77bbae56..993b0aac 100644 --- a/internal/http/controllers/v1/client/client_test.go +++ b/internal/http/controllers/v1/client/client_test.go @@ -181,7 +181,7 @@ func TestPostEvents(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostUserEvents(w, req) + controller.PostUserEvents(w, req, uuid.Nil) assert.Equal(t, tc.statusCode, w.Code) }) @@ -211,7 +211,7 @@ func TestPostEventsInvalidRequest(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostUserEvents(w, req) + controller.PostUserEvents(w, req, uuid.Nil) assert.Equal(t, 400, w.Code) } @@ -235,7 +235,7 @@ func TestPostEventsMissingRBACScope(t *testing.T) { req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - controller.PostUserEvents(w, req) + controller.PostUserEvents(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -267,7 +267,7 @@ func TestPostEventsMissingProjectID(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostUserEvents(w, req) + controller.PostUserEvents(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -318,7 +318,7 @@ func TestPostEventsWithNestedData(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostUserEvents(w, req) + controller.PostUserEvents(w, req, uuid.Nil) assert.Equal(t, 202, w.Code) } @@ -351,7 +351,7 @@ func TestPostEventsEmptyArray(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostUserEvents(w, req) + controller.PostUserEvents(w, req, uuid.Nil) assert.Equal(t, 202, w.Code) } @@ -437,7 +437,7 @@ func TestClientIdentifyUser(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.UpsertUserClient(w, req) + controller.UpsertUserClient(w, req, uuid.Nil) assert.Equal(t, tc.statusCode, w.Code) if w.Code == 200 { @@ -504,7 +504,7 @@ func TestClientIdentifyUserInvalidRequest(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.UpsertUserClient(w, req) + controller.UpsertUserClient(w, req, uuid.Nil) assert.Equal(t, tc.statusCode, w.Code) }) @@ -526,7 +526,7 @@ func TestClientIdentifyUserMissingRBACScope(t *testing.T) { req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - controller.UpsertUserClient(w, req) + controller.UpsertUserClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -554,7 +554,7 @@ func TestClientIdentifyUserMissingProjectID(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.UpsertUserClient(w, req) + controller.UpsertUserClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -593,7 +593,7 @@ func TestClientIdentifyUserUpdateExisting(t *testing.T) { req1 = req1.WithContext(rbac.WithActor(req1.Context(), actor)) w1 := httptest.NewRecorder() - controller.UpsertUserClient(w1, req1) + controller.UpsertUserClient(w1, req1, uuid.Nil) assert.Equal(t, 200, w1.Code) @@ -619,7 +619,7 @@ func TestClientIdentifyUserUpdateExisting(t *testing.T) { req2 = req2.WithContext(rbac.WithActor(req2.Context(), actor)) w2 := httptest.NewRecorder() - controller.UpsertUserClient(w2, req2) + controller.UpsertUserClient(w2, req2, uuid.Nil) assert.Equal(t, 200, w2.Code) @@ -665,7 +665,7 @@ func TestClientIdentifyUserWithBothIdentifiers(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.UpsertUserClient(w, req) + controller.UpsertUserClient(w, req, uuid.Nil) assert.Equal(t, 200, w.Code) @@ -737,7 +737,7 @@ func TestUpsertOrganizationClient(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.UpsertOrganizationClient(w, req) + controller.UpsertOrganizationClient(w, req, uuid.Nil) assert.Equal(t, tc.statusCode, w.Code) if w.Code == 200 { @@ -788,7 +788,7 @@ func TestUpsertOrganizationClientUpdate(t *testing.T) { req1 = req1.WithContext(rbac.WithActor(req1.Context(), actor)) w1 := httptest.NewRecorder() - controller.UpsertOrganizationClient(w1, req1) + controller.UpsertOrganizationClient(w1, req1, uuid.Nil) assert.Equal(t, 200, w1.Code) var response1 map[string]any @@ -811,7 +811,7 @@ func TestUpsertOrganizationClientUpdate(t *testing.T) { req2 = req2.WithContext(rbac.WithActor(req2.Context(), actor)) w2 := httptest.NewRecorder() - controller.UpsertOrganizationClient(w2, req2) + controller.UpsertOrganizationClient(w2, req2, uuid.Nil) assert.Equal(t, 200, w2.Code) var response2 map[string]any @@ -837,7 +837,7 @@ func TestUpsertOrganizationClientMissingRBACScope(t *testing.T) { req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - controller.UpsertOrganizationClient(w, req) + controller.UpsertOrganizationClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -865,7 +865,7 @@ func TestUpsertOrganizationClientMissingProjectID(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.UpsertOrganizationClient(w, req) + controller.UpsertOrganizationClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -893,7 +893,7 @@ func TestUpsertOrganizationClientInvalidRequest(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.UpsertOrganizationClient(w, req) + controller.UpsertOrganizationClient(w, req, uuid.Nil) assert.Equal(t, 400, w.Code) } @@ -965,7 +965,7 @@ func TestAddOrganizationUserClient(t *testing.T) { orgReq.Header.Set("Content-Type", "application/json") orgReq = orgReq.WithContext(rbac.WithActor(orgReq.Context(), actor)) orgW := httptest.NewRecorder() - controller.UpsertOrganizationClient(orgW, orgReq) + controller.UpsertOrganizationClient(orgW, orgReq, uuid.Nil) require.Equal(t, 200, orgW.Code) // Create the user @@ -982,7 +982,7 @@ func TestAddOrganizationUserClient(t *testing.T) { userReq.Header.Set("Content-Type", "application/json") userReq = userReq.WithContext(rbac.WithActor(userReq.Context(), actor)) userW := httptest.NewRecorder() - controller.UpsertUserClient(userW, userReq) + controller.UpsertUserClient(userW, userReq, uuid.Nil) require.Equal(t, 200, userW.Code) // Add user to organization @@ -994,7 +994,7 @@ func TestAddOrganizationUserClient(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.AddOrganizationUserClient(w, req) + controller.AddOrganizationUserClient(w, req, uuid.Nil) assert.Equal(t, tc.statusCode, w.Code) }) @@ -1034,7 +1034,7 @@ func TestAddOrganizationUserClientOrganizationNotFound(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.AddOrganizationUserClient(w, req) + controller.AddOrganizationUserClient(w, req, uuid.Nil) assert.Equal(t, 404, w.Code) } @@ -1068,7 +1068,7 @@ func TestAddOrganizationUserClientUserNotFound(t *testing.T) { orgReq.Header.Set("Content-Type", "application/json") orgReq = orgReq.WithContext(rbac.WithActor(orgReq.Context(), actor)) orgW := httptest.NewRecorder() - controller.UpsertOrganizationClient(orgW, orgReq) + controller.UpsertOrganizationClient(orgW, orgReq, uuid.Nil) require.Equal(t, 200, orgW.Code) body, err := json.Marshal(map[string]any{ @@ -1086,7 +1086,7 @@ func TestAddOrganizationUserClientUserNotFound(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.AddOrganizationUserClient(w, req) + controller.AddOrganizationUserClient(w, req, uuid.Nil) assert.Equal(t, 404, w.Code) } @@ -1110,7 +1110,7 @@ func TestAddOrganizationUserClientMissingRBACScope(t *testing.T) { req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - controller.AddOrganizationUserClient(w, req) + controller.AddOrganizationUserClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -1144,7 +1144,7 @@ func TestRemoveOrganizationUserClient(t *testing.T) { orgReq.Header.Set("Content-Type", "application/json") orgReq = orgReq.WithContext(rbac.WithActor(orgReq.Context(), actor)) orgW := httptest.NewRecorder() - controller.UpsertOrganizationClient(orgW, orgReq) + controller.UpsertOrganizationClient(orgW, orgReq, uuid.Nil) require.Equal(t, 200, orgW.Code) // Create the user @@ -1158,7 +1158,7 @@ func TestRemoveOrganizationUserClient(t *testing.T) { userReq.Header.Set("Content-Type", "application/json") userReq = userReq.WithContext(rbac.WithActor(userReq.Context(), actor)) userW := httptest.NewRecorder() - controller.UpsertUserClient(userW, userReq) + controller.UpsertUserClient(userW, userReq, uuid.Nil) require.Equal(t, 200, userW.Code) // Add user to organization @@ -1176,7 +1176,7 @@ func TestRemoveOrganizationUserClient(t *testing.T) { addReq.Header.Set("Content-Type", "application/json") addReq = addReq.WithContext(rbac.WithActor(addReq.Context(), actor)) addW := httptest.NewRecorder() - controller.AddOrganizationUserClient(addW, addReq) + controller.AddOrganizationUserClient(addW, addReq, uuid.Nil) require.Equal(t, 200, addW.Code) // Remove user from organization @@ -1195,7 +1195,7 @@ func TestRemoveOrganizationUserClient(t *testing.T) { removeReq = removeReq.WithContext(rbac.WithActor(removeReq.Context(), actor)) removeW := httptest.NewRecorder() - controller.RemoveOrganizationUserClient(removeW, removeReq) + controller.RemoveOrganizationUserClient(removeW, removeReq, uuid.Nil) assert.Equal(t, 204, removeW.Code) } @@ -1233,7 +1233,7 @@ func TestRemoveOrganizationUserClientOrganizationNotFound(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.RemoveOrganizationUserClient(w, req) + controller.RemoveOrganizationUserClient(w, req, uuid.Nil) assert.Equal(t, 404, w.Code) } @@ -1267,7 +1267,7 @@ func TestRemoveOrganizationUserClientUserNotFound(t *testing.T) { orgReq.Header.Set("Content-Type", "application/json") orgReq = orgReq.WithContext(rbac.WithActor(orgReq.Context(), actor)) orgW := httptest.NewRecorder() - controller.UpsertOrganizationClient(orgW, orgReq) + controller.UpsertOrganizationClient(orgW, orgReq, uuid.Nil) require.Equal(t, 200, orgW.Code) body, err := json.Marshal(map[string]any{ @@ -1285,7 +1285,7 @@ func TestRemoveOrganizationUserClientUserNotFound(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.RemoveOrganizationUserClient(w, req) + controller.RemoveOrganizationUserClient(w, req, uuid.Nil) assert.Equal(t, 404, w.Code) } @@ -1309,7 +1309,7 @@ func TestRemoveOrganizationUserClientMissingRBACScope(t *testing.T) { req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - controller.RemoveOrganizationUserClient(w, req) + controller.RemoveOrganizationUserClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -1396,7 +1396,7 @@ func TestPostOrganizationEventsClient(t *testing.T) { orgReq.Header.Set("Content-Type", "application/json") orgReq = orgReq.WithContext(rbac.WithActor(orgReq.Context(), actor)) orgW := httptest.NewRecorder() - controller.UpsertOrganizationClient(orgW, orgReq) + controller.UpsertOrganizationClient(orgW, orgReq, uuid.Nil) require.Equal(t, 200, orgW.Code) // Post organization events @@ -1408,7 +1408,7 @@ func TestPostOrganizationEventsClient(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostOrganizationEventsClient(w, req) + controller.PostOrganizationEventsClient(w, req, uuid.Nil) assert.Equal(t, tc.statusCode, w.Code) }) @@ -1448,7 +1448,7 @@ func TestPostOrganizationEventsClientNonexistentOrg(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostOrganizationEventsClient(w, req) + controller.PostOrganizationEventsClient(w, req, uuid.Nil) // Events for nonexistent orgs are skipped, not rejected assert.Equal(t, 202, w.Code) @@ -1473,7 +1473,7 @@ func TestPostOrganizationEventsClientMissingRBACScope(t *testing.T) { req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - controller.PostOrganizationEventsClient(w, req) + controller.PostOrganizationEventsClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -1505,7 +1505,7 @@ func TestPostOrganizationEventsClientMissingProjectID(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostOrganizationEventsClient(w, req) + controller.PostOrganizationEventsClient(w, req, uuid.Nil) assert.Equal(t, 401, w.Code) } @@ -1533,7 +1533,7 @@ func TestPostOrganizationEventsClientInvalidRequest(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostOrganizationEventsClient(w, req) + controller.PostOrganizationEventsClient(w, req, uuid.Nil) assert.Equal(t, 400, w.Code) } @@ -1567,7 +1567,7 @@ func TestPostOrganizationEventsClientWithNestedData(t *testing.T) { orgReq.Header.Set("Content-Type", "application/json") orgReq = orgReq.WithContext(rbac.WithActor(orgReq.Context(), actor)) orgW := httptest.NewRecorder() - controller.UpsertOrganizationClient(orgW, orgReq) + controller.UpsertOrganizationClient(orgW, orgReq, uuid.Nil) require.Equal(t, 200, orgW.Code) events := []map[string]any{ @@ -1597,7 +1597,7 @@ func TestPostOrganizationEventsClientWithNestedData(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.PostOrganizationEventsClient(w, req) + controller.PostOrganizationEventsClient(w, req, uuid.Nil) assert.Equal(t, 202, w.Code) } diff --git a/internal/http/controllers/v1/client/devices.go b/internal/http/controllers/v1/client/devices.go index c6dc073f..23068a78 100644 --- a/internal/http/controllers/v1/client/devices.go +++ b/internal/http/controllers/v1/client/devices.go @@ -25,7 +25,7 @@ func NewDevicesController(client *ClientController) *DevicesController { return &DevicesController{ClientController: client} } -func (srv *DevicesController) GetVapidPublicKey(w http.ResponseWriter, r *http.Request) { +func (srv *DevicesController) GetVapidPublicKey(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { ctx := r.Context() actor := rbac.FromContext(ctx) if actor == nil { @@ -52,7 +52,7 @@ func (srv *DevicesController) GetVapidPublicKey(w http.ResponseWriter, r *http.R json.Write(w, http.StatusOK, oapi.VapidPublicKey{PublicKey: key.PublicKey}) } -func (srv *DevicesController) RegisterDevice(w http.ResponseWriter, r *http.Request) { +func (srv *DevicesController) RegisterDevice(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "devices", rbac.Create) if err != nil { oapi.WriteProblem(w, err) diff --git a/internal/http/controllers/v1/client/events.go b/internal/http/controllers/v1/client/events.go index cc5d095b..090760dc 100644 --- a/internal/http/controllers/v1/client/events.go +++ b/internal/http/controllers/v1/client/events.go @@ -23,7 +23,7 @@ func NewEventsController(client *ClientController) *EventsController { return &EventsController{ClientController: client} } -func (srv *EventsController) PostUserEvents(w http.ResponseWriter, r *http.Request) { +func (srv *EventsController) PostUserEvents(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "events", rbac.Create) if err != nil { oapi.WriteProblem(w, err) @@ -108,7 +108,7 @@ func (srv *EventsController) PostUserEvents(w http.ResponseWriter, r *http.Reque w.WriteHeader(http.StatusAccepted) } -func (srv *EventsController) PostOrganizationEventsClient(w http.ResponseWriter, r *http.Request) { +func (srv *EventsController) PostOrganizationEventsClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "events", rbac.Create) if err != nil { oapi.WriteProblem(w, err) diff --git a/internal/http/controllers/v1/client/inbox.go b/internal/http/controllers/v1/client/inbox.go index e6ff22e5..5b915aa5 100644 --- a/internal/http/controllers/v1/client/inbox.go +++ b/internal/http/controllers/v1/client/inbox.go @@ -26,7 +26,7 @@ func NewInboxController(client *ClientController) *InboxController { return &InboxController{ClientController: client} } -func (srv *InboxController) PostUserInboxMessages(w http.ResponseWriter, r *http.Request) { +func (srv *InboxController) PostUserInboxMessages(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "inbox", rbac.Create) if err != nil { oapi.WriteProblem(w, err) @@ -67,7 +67,7 @@ func (srv *InboxController) PostUserInboxMessages(w http.ResponseWriter, r *http w.WriteHeader(http.StatusAccepted) } -func (srv *InboxController) GetUserInbox(w http.ResponseWriter, r *http.Request, params oapi.GetUserInboxParams) { +func (srv *InboxController) GetUserInbox(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID, params oapi.GetUserInboxParams) { projectID, err := srv.engine.AllowedProject(r.Context(), "inbox", rbac.Read) if err != nil { oapi.WriteProblem(w, err) @@ -101,7 +101,7 @@ func (srv *InboxController) GetUserInbox(w http.ResponseWriter, r *http.Request, }) } -func (srv *InboxController) GetUserInboxCount(w http.ResponseWriter, r *http.Request, params oapi.GetUserInboxCountParams) { +func (srv *InboxController) GetUserInboxCount(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID, params oapi.GetUserInboxCountParams) { projectID, err := srv.engine.AllowedProject(r.Context(), "inbox", rbac.Read) if err != nil { oapi.WriteProblem(w, err) @@ -129,15 +129,15 @@ func (srv *InboxController) GetUserInboxCount(w http.ResponseWriter, r *http.Req json.Write(w, http.StatusOK, oapi.InboxCount{Unread: counts.Unread, Total: counts.Total}) } -func (srv *InboxController) PostUserInboxRead(w http.ResponseWriter, r *http.Request) { +func (srv *InboxController) PostUserInboxRead(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { srv.publishUserInboxStateEvents(w, r, schemas.UserInboxRead, "read") } -func (srv *InboxController) PostUserInboxArchived(w http.ResponseWriter, r *http.Request) { +func (srv *InboxController) PostUserInboxArchived(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { srv.publishUserInboxStateEvents(w, r, schemas.UserInboxArchived, "archived") } -func (srv *InboxController) PostOrganizationInboxMessages(w http.ResponseWriter, r *http.Request) { +func (srv *InboxController) PostOrganizationInboxMessages(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "inbox", rbac.Create) if err != nil { oapi.WriteProblem(w, err) @@ -174,7 +174,7 @@ func (srv *InboxController) PostOrganizationInboxMessages(w http.ResponseWriter, w.WriteHeader(http.StatusAccepted) } -func (srv *InboxController) GetOrganizationInbox(w http.ResponseWriter, r *http.Request, params oapi.GetOrganizationInboxParams) { +func (srv *InboxController) GetOrganizationInbox(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID, params oapi.GetOrganizationInboxParams) { projectID, err := srv.engine.AllowedProject(r.Context(), "inbox", rbac.Read) if err != nil { oapi.WriteProblem(w, err) @@ -213,7 +213,7 @@ func (srv *InboxController) GetOrganizationInbox(w http.ResponseWriter, r *http. }) } -func (srv *InboxController) GetOrganizationInboxCount(w http.ResponseWriter, r *http.Request, params oapi.GetOrganizationInboxCountParams) { +func (srv *InboxController) GetOrganizationInboxCount(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID, params oapi.GetOrganizationInboxCountParams) { projectID, err := srv.engine.AllowedProject(r.Context(), "inbox", rbac.Read) if err != nil { oapi.WriteProblem(w, err) @@ -246,11 +246,11 @@ func (srv *InboxController) GetOrganizationInboxCount(w http.ResponseWriter, r * json.Write(w, http.StatusOK, oapi.InboxCount{Unread: counts.Unread, Total: counts.Total}) } -func (srv *InboxController) PostOrganizationInboxRead(w http.ResponseWriter, r *http.Request) { +func (srv *InboxController) PostOrganizationInboxRead(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { srv.publishOrganizationInboxStateEvents(w, r, schemas.OrganizationInboxRead, "read") } -func (srv *InboxController) PostOrganizationInboxArchived(w http.ResponseWriter, r *http.Request) { +func (srv *InboxController) PostOrganizationInboxArchived(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { srv.publishOrganizationInboxStateEvents(w, r, schemas.OrganizationInboxArchived, "archived") } diff --git a/internal/http/controllers/v1/client/inbox_test.go b/internal/http/controllers/v1/client/inbox_test.go index 6bf88da2..56ec6d3d 100644 --- a/internal/http/controllers/v1/client/inbox_test.go +++ b/internal/http/controllers/v1/client/inbox_test.go @@ -15,11 +15,22 @@ import ( "github.com/stretchr/testify/require" ) +// testProjectID is the concrete project UUID inlined into client request paths. +// Every authenticated client route is mounted under /api/client/projects/{projectID}. +const testProjectID = "11111111-1111-1111-1111-111111111111" + +// clientPath builds a concrete request path under the project prefix from a +// suffix such as "/users/inbox". +func clientPath(suffix string) string { + return "/api/client/projects/" + testProjectID + suffix +} + // newValidatedRouter creates a chi router with only the OpenAPI spec validation // middleware. Auth is skipped (NoopAuthenticationFunc) so we can test request // body validation in isolation. A 200 OK passthrough handler is mounted at the -// given path+method so that any request that passes validation returns 200. -func newValidatedRouter(t *testing.T, method, path string) chi.Router { +// chi route pattern for the given suffix (with a {projectID} segment) so that any +// request that passes validation returns 200. +func newValidatedRouter(t *testing.T, method, suffix string) chi.Router { t.Helper() spec, err := oapi.Spec() @@ -29,7 +40,7 @@ func newValidatedRouter(t *testing.T, method, path string) chi.Router { router.Use(oapi.Validator(spec, openapi3filter.Options{ AuthenticationFunc: openapi3filter.NoopAuthenticationFunc, })) - router.MethodFunc(method, path, func(w http.ResponseWriter, r *http.Request) { + router.MethodFunc(method, "/api/client/projects/{projectID}"+suffix, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) return router @@ -75,13 +86,13 @@ func TestInboxSpecValidation_EmptyTarget(t *testing.T) { body any }{ "user inbox messages": { - path: "/api/client/users/inbox", + path: "/users/inbox", body: []map[string]any{ withOverrides(validUserInboxMessage(), "target", []map[string]any{}), }, }, "user inbox events": { - path: "/api/client/users/inbox/read", + path: "/users/inbox/read", body: []map[string]any{ withOverrides(validUserInboxEvent(), "target", []map[string]any{}), }, @@ -92,7 +103,7 @@ func TestInboxSpecValidation_EmptyTarget(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() router := newValidatedRouter(t, http.MethodPost, tc.path) - w := postJSON(t, router, tc.path, tc.body) + w := postJSON(t, router, clientPath(tc.path), tc.body) assert.Equal(t, http.StatusBadRequest, w.Code, "empty target should be rejected") }) } @@ -106,13 +117,13 @@ func TestInboxSpecValidation_EmptyExternalID(t *testing.T) { body any }{ "user inbox messages": { - path: "/api/client/users/inbox", + path: "/users/inbox", body: []map[string]any{ withOverrides(validUserInboxMessage(), "target", []map[string]any{{"external_id": ""}}), }, }, "user inbox events": { - path: "/api/client/users/inbox/archived", + path: "/users/inbox/archived", body: []map[string]any{ withOverrides(validUserInboxEvent(), "target", []map[string]any{{"external_id": ""}}), }, @@ -123,7 +134,7 @@ func TestInboxSpecValidation_EmptyExternalID(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() router := newValidatedRouter(t, http.MethodPost, tc.path) - w := postJSON(t, router, tc.path, tc.body) + w := postJSON(t, router, clientPath(tc.path), tc.body) assert.Equal(t, http.StatusBadRequest, w.Code, "empty external_id should be rejected") }) } @@ -132,8 +143,8 @@ func TestInboxSpecValidation_EmptyExternalID(t *testing.T) { func TestInboxSpecValidation_InvalidChannel(t *testing.T) { t.Parallel() - router := newValidatedRouter(t, http.MethodPost, "/api/client/users/inbox") - w := postJSON(t, router, "/api/client/users/inbox", []map[string]any{ + router := newValidatedRouter(t, http.MethodPost, "/users/inbox") + w := postJSON(t, router, clientPath("/users/inbox"), []map[string]any{ withOverrides(validUserInboxMessage(), "channel", "carrier_pigeon"), }) assert.Equal(t, http.StatusBadRequest, w.Code, "invalid channel should be rejected") @@ -154,8 +165,8 @@ func TestInboxSpecValidation_InvalidPriority(t *testing.T) { msg := validUserInboxMessage() msg["priority"] = priority - router := newValidatedRouter(t, http.MethodPost, "/api/client/users/inbox") - w := postJSON(t, router, "/api/client/users/inbox", []map[string]any{msg}) + router := newValidatedRouter(t, http.MethodPost, "/users/inbox") + w := postJSON(t, router, clientPath("/users/inbox"), []map[string]any{msg}) assert.Equal(t, http.StatusBadRequest, w.Code, "invalid priority should be rejected") }) } @@ -167,18 +178,18 @@ func TestInboxSpecValidation_EmptyArray(t *testing.T) { tests := map[string]struct { path string }{ - "user inbox messages": {path: "/api/client/users/inbox"}, - "user inbox read": {path: "/api/client/users/inbox/read"}, - "user inbox archived": {path: "/api/client/users/inbox/archived"}, - "org inbox read": {path: "/api/client/organizations/inbox/read"}, - "org inbox archived": {path: "/api/client/organizations/inbox/archived"}, + "user inbox messages": {path: "/users/inbox"}, + "user inbox read": {path: "/users/inbox/read"}, + "user inbox archived": {path: "/users/inbox/archived"}, + "org inbox read": {path: "/organizations/inbox/read"}, + "org inbox archived": {path: "/organizations/inbox/archived"}, } for name, tc := range tests { t.Run(name, func(t *testing.T) { t.Parallel() router := newValidatedRouter(t, http.MethodPost, tc.path) - w := postJSON(t, router, tc.path, []map[string]any{}) + w := postJSON(t, router, clientPath(tc.path), []map[string]any{}) assert.Equal(t, http.StatusBadRequest, w.Code, "empty array should be rejected") }) } @@ -192,15 +203,15 @@ func TestInboxSpecValidation_ValidRequest(t *testing.T) { body any }{ "user inbox messages": { - path: "/api/client/users/inbox", + path: "/users/inbox", body: []map[string]any{validUserInboxMessage()}, }, "user inbox read": { - path: "/api/client/users/inbox/read", + path: "/users/inbox/read", body: []map[string]any{validUserInboxEvent()}, }, "user inbox archived": { - path: "/api/client/users/inbox/archived", + path: "/users/inbox/archived", body: []map[string]any{validUserInboxEvent()}, }, } @@ -209,7 +220,7 @@ func TestInboxSpecValidation_ValidRequest(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() router := newValidatedRouter(t, http.MethodPost, tc.path) - w := postJSON(t, router, tc.path, tc.body) + w := postJSON(t, router, clientPath(tc.path), tc.body) assert.Equal(t, http.StatusOK, w.Code, "valid request should pass spec validation") }) } @@ -222,8 +233,8 @@ func TestInboxSpecValidation_ValidCreateWithSchedulingMetadata(t *testing.T) { msg["identifier"] = map[string]any{"external_id": "message_123"} msg["scheduled_at"] = time.Now().Add(time.Hour).UTC().Format(time.RFC3339) - router := newValidatedRouter(t, http.MethodPost, "/api/client/users/inbox") - w := postJSON(t, router, "/api/client/users/inbox", []map[string]any{msg}) + router := newValidatedRouter(t, http.MethodPost, "/users/inbox") + w := postJSON(t, router, clientPath("/users/inbox"), []map[string]any{msg}) assert.Equal(t, http.StatusOK, w.Code, "valid scheduling metadata should pass") } @@ -236,8 +247,8 @@ func TestInboxSpecValidation_ValidPriority(t *testing.T) { msg := validUserInboxMessage() msg["priority"] = priority - router := newValidatedRouter(t, http.MethodPost, "/api/client/users/inbox") - w := postJSON(t, router, "/api/client/users/inbox", []map[string]any{msg}) + router := newValidatedRouter(t, http.MethodPost, "/users/inbox") + w := postJSON(t, router, clientPath("/users/inbox"), []map[string]any{msg}) assert.Equal(t, http.StatusOK, w.Code, "valid priority should pass") }) } diff --git a/internal/http/controllers/v1/client/oapi/resources.yml b/internal/http/controllers/v1/client/oapi/resources.yml index 9f27e963..5bdf2cab 100644 --- a/internal/http/controllers/v1/client/oapi/resources.yml +++ b/internal/http/controllers/v1/client/oapi/resources.yml @@ -5,10 +5,12 @@ info: version: 1.0.0 paths: - /api/client/users: + /api/client/projects/{projectID}/users: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Upsert user - description: Used by client libraries to create or update a user profile. The project is determined from the API key. + description: Used by client libraries to create or update a user profile. The project is taken from the projectID path parameter. operationId: upsertUserClient tags: - Client @@ -33,7 +35,7 @@ paths: summary: Delete user description: | Used by client libraries to delete a user by external_id or anonymous_id. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: deleteUserClient tags: - Client @@ -51,7 +53,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/users/events: + /api/client/projects/{projectID}/users/events: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Post user events description: | @@ -59,7 +63,7 @@ paths: Multiple events can be sent in a single request and are processed asynchronously. Each event is handled independently: if one event fails to be accepted or processed, other events in the same request may still be published successfully. Clients requiring deterministic retry or recovery behavior must submit events individually. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: postUserEvents tags: - Client @@ -77,7 +81,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/users/inbox: + /api/client/projects/{projectID}/users/inbox: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Create user inbox messages description: Creates one or more inbox messages for users identified by external identifiers. Messages are processed asynchronously. @@ -151,7 +157,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/users/inbox/count: + /api/client/projects/{projectID}/users/inbox/count: + parameters: + - $ref: "#/components/parameters/ProjectID" get: summary: Count user inbox messages description: Returns unread and total visible inbox message counts for a user. @@ -186,7 +194,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/users/inbox/read: + /api/client/projects/{projectID}/users/inbox/read: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Mark user inbox messages read description: Marks one or more user inbox messages as read. Processed asynchronously. @@ -207,7 +217,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/users/inbox/archived: + /api/client/projects/{projectID}/users/inbox/archived: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Mark user inbox messages archived description: Marks one or more user inbox messages as archived. Processed asynchronously. @@ -228,12 +240,14 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations: + /api/client/projects/{projectID}/organizations: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Upsert organization description: | Used by client libraries to create or update an organization by external_id. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: upsertOrganizationClient tags: - Client @@ -259,7 +273,7 @@ paths: description: | Used by client libraries to delete an organization by external_id. This will also remove all organization memberships. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: deleteOrganizationClient tags: - Client @@ -277,13 +291,15 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations/users: + /api/client/projects/{projectID}/organizations/users: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Add user to organization description: | Used by client libraries to add a user to an organization with optional org-specific data. Both organization and user are identified by their external_id. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: addOrganizationUserClient tags: - Client @@ -306,7 +322,7 @@ paths: description: | Used by client libraries to remove a user from an organization. Both organization and user are identified by their external_id. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: removeOrganizationUserClient tags: - Client @@ -324,14 +340,16 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/users/scheduled: + /api/client/projects/{projectID}/users/scheduled: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Upsert user scheduled description: | Used by client libraries to create or update a scheduled resource for a user. The user is identified by external_id or anonymous_id. This triggers journey entrance recalculation for any journeys that depend on the scheduled resource. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: upsertUserScheduledClient tags: - Client @@ -358,7 +376,7 @@ paths: Used by client libraries to delete all scheduled instances for a user with a given scheduled resource name. The user is identified by external_id or anonymous_id. This cancels any pending journey entrance states that depend on the scheduled resource. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: deleteUserScheduledClient tags: - Client @@ -376,14 +394,16 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations/scheduled: + /api/client/projects/{projectID}/organizations/scheduled: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Upsert organization scheduled description: | Used by client libraries to create or update a scheduled resource for an organization. The organization is identified by external_id. This triggers journey entrance recalculation for any journeys that depend on the scheduled resource. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: upsertOrganizationScheduledClient tags: - Client @@ -410,7 +430,7 @@ paths: Used by client libraries to delete all scheduled instances for an organization with a given scheduled resource name. The organization is identified by external_id. This cancels any pending journey entrance states that depend on the scheduled resource. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: deleteOrganizationScheduledClient tags: - Client @@ -428,14 +448,16 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations/events: + /api/client/projects/{projectID}/organizations/events: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Post organization events description: | Used by client libraries to trigger events on an organization. The organization is identified by external_id. Events are processed asynchronously and can trigger journeys for all users in the organization. - The project is determined from the API key. + The project is taken from the projectID path parameter. operationId: postOrganizationEventsClient tags: - Client @@ -453,7 +475,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations/inbox: + /api/client/projects/{projectID}/organizations/inbox: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Create organization inbox messages description: Creates one or more inbox messages for organizations identified by external identifiers. Messages are processed asynchronously. @@ -527,7 +551,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations/inbox/count: + /api/client/projects/{projectID}/organizations/inbox/count: + parameters: + - $ref: "#/components/parameters/ProjectID" get: summary: Count organization inbox messages description: Returns unread and total visible inbox message counts for an organization. @@ -562,7 +588,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations/inbox/read: + /api/client/projects/{projectID}/organizations/inbox/read: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Mark organization inbox messages read description: Marks one or more organization inbox messages as read. Processed asynchronously. @@ -583,7 +611,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/organizations/inbox/archived: + /api/client/projects/{projectID}/organizations/inbox/archived: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Mark organization inbox messages archived description: Marks one or more organization inbox messages as archived. Processed asynchronously. @@ -706,10 +736,12 @@ paths: schema: type: string - /api/client/users/devices: + /api/client/projects/{projectID}/users/devices: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Register device - description: Register or update a device's push subscription. The project is determined from the API key. + description: Register or update a device's push subscription. The project is taken from the projectID path parameter. operationId: registerDevice tags: - Client @@ -727,7 +759,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/push/vapid: + /api/client/projects/{projectID}/push/vapid: + parameters: + - $ref: "#/components/parameters/ProjectID" get: summary: Get VAPID public key description: Retrieves the VAPID public key for push notifications @@ -746,7 +780,9 @@ paths: default: $ref: "#/components/responses/Error" - /api/client/auth-methods/{authMethodID}/sessions: + /api/client/projects/{projectID}/auth-methods/{authMethodID}/sessions: + parameters: + - $ref: "#/components/parameters/ProjectID" post: summary: Mint a session token description: | @@ -784,6 +820,15 @@ paths: components: parameters: + ProjectID: + name: projectID + in: path + required: true + schema: + type: string + format: uuid + description: The project the request acts on. Must match the project the presented credential is authorized for. + Limit: name: limit in: query diff --git a/internal/http/controllers/v1/client/oapi/resources_gen.go b/internal/http/controllers/v1/client/oapi/resources_gen.go index b4545197..976597ac 100644 --- a/internal/http/controllers/v1/client/oapi/resources_gen.go +++ b/internal/http/controllers/v1/client/oapi/resources_gen.go @@ -531,6 +531,9 @@ type Limit = PaginationLimit // Offset defines model for Offset. type Offset = PaginationOffset +// ProjectID defines model for ProjectID. +type ProjectID = openapi_types.UUID + // Error defines model for Error. type Error = Problem @@ -744,119 +747,119 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption { // The interface specification for the client above. type ClientInterface interface { // CreateSessionWithBody request with any body - CreateSessionWithBody(ctx context.Context, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + CreateSessionWithBody(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - CreateSession(ctx context.Context, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + CreateSession(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteOrganizationClientWithBody request with any body - DeleteOrganizationClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteOrganizationClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - DeleteOrganizationClient(ctx context.Context, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteOrganizationClient(ctx context.Context, projectID ProjectID, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // UpsertOrganizationClientWithBody request with any body - UpsertOrganizationClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertOrganizationClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - UpsertOrganizationClient(ctx context.Context, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertOrganizationClient(ctx context.Context, projectID ProjectID, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // PostOrganizationEventsClientWithBody request with any body - PostOrganizationEventsClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationEventsClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostOrganizationEventsClient(ctx context.Context, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationEventsClient(ctx context.Context, projectID ProjectID, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // GetOrganizationInbox request - GetOrganizationInbox(ctx context.Context, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) + GetOrganizationInbox(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) // PostOrganizationInboxMessagesWithBody request with any body - PostOrganizationInboxMessagesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationInboxMessagesWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostOrganizationInboxMessages(ctx context.Context, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationInboxMessages(ctx context.Context, projectID ProjectID, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // PostOrganizationInboxArchivedWithBody request with any body - PostOrganizationInboxArchivedWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationInboxArchivedWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostOrganizationInboxArchived(ctx context.Context, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationInboxArchived(ctx context.Context, projectID ProjectID, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // GetOrganizationInboxCount request - GetOrganizationInboxCount(ctx context.Context, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) + GetOrganizationInboxCount(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) // PostOrganizationInboxReadWithBody request with any body - PostOrganizationInboxReadWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationInboxReadWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostOrganizationInboxRead(ctx context.Context, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostOrganizationInboxRead(ctx context.Context, projectID ProjectID, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteOrganizationScheduledClientWithBody request with any body - DeleteOrganizationScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteOrganizationScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - DeleteOrganizationScheduledClient(ctx context.Context, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteOrganizationScheduledClient(ctx context.Context, projectID ProjectID, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // UpsertOrganizationScheduledClientWithBody request with any body - UpsertOrganizationScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertOrganizationScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - UpsertOrganizationScheduledClient(ctx context.Context, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertOrganizationScheduledClient(ctx context.Context, projectID ProjectID, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // RemoveOrganizationUserClientWithBody request with any body - RemoveOrganizationUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + RemoveOrganizationUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - RemoveOrganizationUserClient(ctx context.Context, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + RemoveOrganizationUserClient(ctx context.Context, projectID ProjectID, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // AddOrganizationUserClientWithBody request with any body - AddOrganizationUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + AddOrganizationUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - AddOrganizationUserClient(ctx context.Context, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + AddOrganizationUserClient(ctx context.Context, projectID ProjectID, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // GetVapidPublicKey request - GetVapidPublicKey(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + GetVapidPublicKey(ctx context.Context, projectID ProjectID, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteUserClientWithBody request with any body - DeleteUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - DeleteUserClient(ctx context.Context, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteUserClient(ctx context.Context, projectID ProjectID, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // UpsertUserClientWithBody request with any body - UpsertUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - UpsertUserClient(ctx context.Context, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertUserClient(ctx context.Context, projectID ProjectID, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // RegisterDeviceWithBody request with any body - RegisterDeviceWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + RegisterDeviceWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - RegisterDevice(ctx context.Context, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + RegisterDevice(ctx context.Context, projectID ProjectID, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // PostUserEventsWithBody request with any body - PostUserEventsWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserEventsWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostUserEvents(ctx context.Context, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserEvents(ctx context.Context, projectID ProjectID, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // GetUserInbox request - GetUserInbox(ctx context.Context, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) + GetUserInbox(ctx context.Context, projectID ProjectID, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) // PostUserInboxMessagesWithBody request with any body - PostUserInboxMessagesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserInboxMessagesWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostUserInboxMessages(ctx context.Context, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserInboxMessages(ctx context.Context, projectID ProjectID, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // PostUserInboxArchivedWithBody request with any body - PostUserInboxArchivedWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserInboxArchivedWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostUserInboxArchived(ctx context.Context, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserInboxArchived(ctx context.Context, projectID ProjectID, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // GetUserInboxCount request - GetUserInboxCount(ctx context.Context, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) + GetUserInboxCount(ctx context.Context, projectID ProjectID, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) // PostUserInboxReadWithBody request with any body - PostUserInboxReadWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserInboxReadWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - PostUserInboxRead(ctx context.Context, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + PostUserInboxRead(ctx context.Context, projectID ProjectID, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteUserScheduledClientWithBody request with any body - DeleteUserScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteUserScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - DeleteUserScheduledClient(ctx context.Context, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteUserScheduledClient(ctx context.Context, projectID ProjectID, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // UpsertUserScheduledClientWithBody request with any body - UpsertUserScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertUserScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - UpsertUserScheduledClient(ctx context.Context, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + UpsertUserScheduledClient(ctx context.Context, projectID ProjectID, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // GetPreferencesPage request GetPreferencesPage(ctx context.Context, projectID openapi_types.UUID, userID openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -870,8 +873,8 @@ type ClientInterface interface { EmailUnsubscribe(ctx context.Context, params *EmailUnsubscribeParams, reqEditors ...RequestEditorFn) (*http.Response, error) } -func (c *Client) CreateSessionWithBody(ctx context.Context, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateSessionRequestWithBody(c.Server, authMethodID, contentType, body) +func (c *Client) CreateSessionWithBody(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateSessionRequestWithBody(c.Server, projectID, authMethodID, contentType, body) if err != nil { return nil, err } @@ -882,8 +885,8 @@ func (c *Client) CreateSessionWithBody(ctx context.Context, authMethodID openapi return c.Client.Do(req) } -func (c *Client) CreateSession(ctx context.Context, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateSessionRequest(c.Server, authMethodID, body) +func (c *Client) CreateSession(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateSessionRequest(c.Server, projectID, authMethodID, body) if err != nil { return nil, err } @@ -894,8 +897,8 @@ func (c *Client) CreateSession(ctx context.Context, authMethodID openapi_types.U return c.Client.Do(req) } -func (c *Client) DeleteOrganizationClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteOrganizationClientRequestWithBody(c.Server, contentType, body) +func (c *Client) DeleteOrganizationClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteOrganizationClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -906,8 +909,8 @@ func (c *Client) DeleteOrganizationClientWithBody(ctx context.Context, contentTy return c.Client.Do(req) } -func (c *Client) DeleteOrganizationClient(ctx context.Context, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteOrganizationClientRequest(c.Server, body) +func (c *Client) DeleteOrganizationClient(ctx context.Context, projectID ProjectID, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteOrganizationClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -918,8 +921,8 @@ func (c *Client) DeleteOrganizationClient(ctx context.Context, body DeleteOrgani return c.Client.Do(req) } -func (c *Client) UpsertOrganizationClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertOrganizationClientRequestWithBody(c.Server, contentType, body) +func (c *Client) UpsertOrganizationClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertOrganizationClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -930,8 +933,8 @@ func (c *Client) UpsertOrganizationClientWithBody(ctx context.Context, contentTy return c.Client.Do(req) } -func (c *Client) UpsertOrganizationClient(ctx context.Context, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertOrganizationClientRequest(c.Server, body) +func (c *Client) UpsertOrganizationClient(ctx context.Context, projectID ProjectID, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertOrganizationClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -942,8 +945,8 @@ func (c *Client) UpsertOrganizationClient(ctx context.Context, body UpsertOrgani return c.Client.Do(req) } -func (c *Client) PostOrganizationEventsClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationEventsClientRequestWithBody(c.Server, contentType, body) +func (c *Client) PostOrganizationEventsClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationEventsClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -954,8 +957,8 @@ func (c *Client) PostOrganizationEventsClientWithBody(ctx context.Context, conte return c.Client.Do(req) } -func (c *Client) PostOrganizationEventsClient(ctx context.Context, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationEventsClientRequest(c.Server, body) +func (c *Client) PostOrganizationEventsClient(ctx context.Context, projectID ProjectID, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationEventsClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -966,8 +969,8 @@ func (c *Client) PostOrganizationEventsClient(ctx context.Context, body PostOrga return c.Client.Do(req) } -func (c *Client) GetOrganizationInbox(ctx context.Context, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetOrganizationInboxRequest(c.Server, params) +func (c *Client) GetOrganizationInbox(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetOrganizationInboxRequest(c.Server, projectID, params) if err != nil { return nil, err } @@ -978,8 +981,8 @@ func (c *Client) GetOrganizationInbox(ctx context.Context, params *GetOrganizati return c.Client.Do(req) } -func (c *Client) PostOrganizationInboxMessagesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationInboxMessagesRequestWithBody(c.Server, contentType, body) +func (c *Client) PostOrganizationInboxMessagesWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationInboxMessagesRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -990,8 +993,8 @@ func (c *Client) PostOrganizationInboxMessagesWithBody(ctx context.Context, cont return c.Client.Do(req) } -func (c *Client) PostOrganizationInboxMessages(ctx context.Context, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationInboxMessagesRequest(c.Server, body) +func (c *Client) PostOrganizationInboxMessages(ctx context.Context, projectID ProjectID, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationInboxMessagesRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1002,8 +1005,8 @@ func (c *Client) PostOrganizationInboxMessages(ctx context.Context, body PostOrg return c.Client.Do(req) } -func (c *Client) PostOrganizationInboxArchivedWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationInboxArchivedRequestWithBody(c.Server, contentType, body) +func (c *Client) PostOrganizationInboxArchivedWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationInboxArchivedRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1014,8 +1017,8 @@ func (c *Client) PostOrganizationInboxArchivedWithBody(ctx context.Context, cont return c.Client.Do(req) } -func (c *Client) PostOrganizationInboxArchived(ctx context.Context, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationInboxArchivedRequest(c.Server, body) +func (c *Client) PostOrganizationInboxArchived(ctx context.Context, projectID ProjectID, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationInboxArchivedRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1026,8 +1029,8 @@ func (c *Client) PostOrganizationInboxArchived(ctx context.Context, body PostOrg return c.Client.Do(req) } -func (c *Client) GetOrganizationInboxCount(ctx context.Context, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetOrganizationInboxCountRequest(c.Server, params) +func (c *Client) GetOrganizationInboxCount(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetOrganizationInboxCountRequest(c.Server, projectID, params) if err != nil { return nil, err } @@ -1038,8 +1041,8 @@ func (c *Client) GetOrganizationInboxCount(ctx context.Context, params *GetOrgan return c.Client.Do(req) } -func (c *Client) PostOrganizationInboxReadWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationInboxReadRequestWithBody(c.Server, contentType, body) +func (c *Client) PostOrganizationInboxReadWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationInboxReadRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1050,8 +1053,8 @@ func (c *Client) PostOrganizationInboxReadWithBody(ctx context.Context, contentT return c.Client.Do(req) } -func (c *Client) PostOrganizationInboxRead(ctx context.Context, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostOrganizationInboxReadRequest(c.Server, body) +func (c *Client) PostOrganizationInboxRead(ctx context.Context, projectID ProjectID, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostOrganizationInboxReadRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1062,8 +1065,8 @@ func (c *Client) PostOrganizationInboxRead(ctx context.Context, body PostOrganiz return c.Client.Do(req) } -func (c *Client) DeleteOrganizationScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteOrganizationScheduledClientRequestWithBody(c.Server, contentType, body) +func (c *Client) DeleteOrganizationScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteOrganizationScheduledClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1074,8 +1077,8 @@ func (c *Client) DeleteOrganizationScheduledClientWithBody(ctx context.Context, return c.Client.Do(req) } -func (c *Client) DeleteOrganizationScheduledClient(ctx context.Context, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteOrganizationScheduledClientRequest(c.Server, body) +func (c *Client) DeleteOrganizationScheduledClient(ctx context.Context, projectID ProjectID, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteOrganizationScheduledClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1086,8 +1089,8 @@ func (c *Client) DeleteOrganizationScheduledClient(ctx context.Context, body Del return c.Client.Do(req) } -func (c *Client) UpsertOrganizationScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertOrganizationScheduledClientRequestWithBody(c.Server, contentType, body) +func (c *Client) UpsertOrganizationScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertOrganizationScheduledClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1098,8 +1101,8 @@ func (c *Client) UpsertOrganizationScheduledClientWithBody(ctx context.Context, return c.Client.Do(req) } -func (c *Client) UpsertOrganizationScheduledClient(ctx context.Context, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertOrganizationScheduledClientRequest(c.Server, body) +func (c *Client) UpsertOrganizationScheduledClient(ctx context.Context, projectID ProjectID, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertOrganizationScheduledClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1110,8 +1113,8 @@ func (c *Client) UpsertOrganizationScheduledClient(ctx context.Context, body Ups return c.Client.Do(req) } -func (c *Client) RemoveOrganizationUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRemoveOrganizationUserClientRequestWithBody(c.Server, contentType, body) +func (c *Client) RemoveOrganizationUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRemoveOrganizationUserClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1122,8 +1125,8 @@ func (c *Client) RemoveOrganizationUserClientWithBody(ctx context.Context, conte return c.Client.Do(req) } -func (c *Client) RemoveOrganizationUserClient(ctx context.Context, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRemoveOrganizationUserClientRequest(c.Server, body) +func (c *Client) RemoveOrganizationUserClient(ctx context.Context, projectID ProjectID, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRemoveOrganizationUserClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1134,8 +1137,8 @@ func (c *Client) RemoveOrganizationUserClient(ctx context.Context, body RemoveOr return c.Client.Do(req) } -func (c *Client) AddOrganizationUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewAddOrganizationUserClientRequestWithBody(c.Server, contentType, body) +func (c *Client) AddOrganizationUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewAddOrganizationUserClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1146,8 +1149,8 @@ func (c *Client) AddOrganizationUserClientWithBody(ctx context.Context, contentT return c.Client.Do(req) } -func (c *Client) AddOrganizationUserClient(ctx context.Context, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewAddOrganizationUserClientRequest(c.Server, body) +func (c *Client) AddOrganizationUserClient(ctx context.Context, projectID ProjectID, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewAddOrganizationUserClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1158,8 +1161,8 @@ func (c *Client) AddOrganizationUserClient(ctx context.Context, body AddOrganiza return c.Client.Do(req) } -func (c *Client) GetVapidPublicKey(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetVapidPublicKeyRequest(c.Server) +func (c *Client) GetVapidPublicKey(ctx context.Context, projectID ProjectID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetVapidPublicKeyRequest(c.Server, projectID) if err != nil { return nil, err } @@ -1170,8 +1173,8 @@ func (c *Client) GetVapidPublicKey(ctx context.Context, reqEditors ...RequestEdi return c.Client.Do(req) } -func (c *Client) DeleteUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteUserClientRequestWithBody(c.Server, contentType, body) +func (c *Client) DeleteUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteUserClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1182,8 +1185,8 @@ func (c *Client) DeleteUserClientWithBody(ctx context.Context, contentType strin return c.Client.Do(req) } -func (c *Client) DeleteUserClient(ctx context.Context, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteUserClientRequest(c.Server, body) +func (c *Client) DeleteUserClient(ctx context.Context, projectID ProjectID, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteUserClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1194,8 +1197,8 @@ func (c *Client) DeleteUserClient(ctx context.Context, body DeleteUserClientJSON return c.Client.Do(req) } -func (c *Client) UpsertUserClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertUserClientRequestWithBody(c.Server, contentType, body) +func (c *Client) UpsertUserClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertUserClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1206,8 +1209,8 @@ func (c *Client) UpsertUserClientWithBody(ctx context.Context, contentType strin return c.Client.Do(req) } -func (c *Client) UpsertUserClient(ctx context.Context, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertUserClientRequest(c.Server, body) +func (c *Client) UpsertUserClient(ctx context.Context, projectID ProjectID, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertUserClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1218,8 +1221,8 @@ func (c *Client) UpsertUserClient(ctx context.Context, body UpsertUserClientJSON return c.Client.Do(req) } -func (c *Client) RegisterDeviceWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRegisterDeviceRequestWithBody(c.Server, contentType, body) +func (c *Client) RegisterDeviceWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRegisterDeviceRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1230,8 +1233,8 @@ func (c *Client) RegisterDeviceWithBody(ctx context.Context, contentType string, return c.Client.Do(req) } -func (c *Client) RegisterDevice(ctx context.Context, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRegisterDeviceRequest(c.Server, body) +func (c *Client) RegisterDevice(ctx context.Context, projectID ProjectID, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRegisterDeviceRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1242,8 +1245,8 @@ func (c *Client) RegisterDevice(ctx context.Context, body RegisterDeviceJSONRequ return c.Client.Do(req) } -func (c *Client) PostUserEventsWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserEventsRequestWithBody(c.Server, contentType, body) +func (c *Client) PostUserEventsWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserEventsRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1254,8 +1257,8 @@ func (c *Client) PostUserEventsWithBody(ctx context.Context, contentType string, return c.Client.Do(req) } -func (c *Client) PostUserEvents(ctx context.Context, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserEventsRequest(c.Server, body) +func (c *Client) PostUserEvents(ctx context.Context, projectID ProjectID, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserEventsRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1266,8 +1269,8 @@ func (c *Client) PostUserEvents(ctx context.Context, body PostUserEventsJSONRequ return c.Client.Do(req) } -func (c *Client) GetUserInbox(ctx context.Context, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetUserInboxRequest(c.Server, params) +func (c *Client) GetUserInbox(ctx context.Context, projectID ProjectID, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetUserInboxRequest(c.Server, projectID, params) if err != nil { return nil, err } @@ -1278,8 +1281,8 @@ func (c *Client) GetUserInbox(ctx context.Context, params *GetUserInboxParams, r return c.Client.Do(req) } -func (c *Client) PostUserInboxMessagesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserInboxMessagesRequestWithBody(c.Server, contentType, body) +func (c *Client) PostUserInboxMessagesWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserInboxMessagesRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1290,8 +1293,8 @@ func (c *Client) PostUserInboxMessagesWithBody(ctx context.Context, contentType return c.Client.Do(req) } -func (c *Client) PostUserInboxMessages(ctx context.Context, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserInboxMessagesRequest(c.Server, body) +func (c *Client) PostUserInboxMessages(ctx context.Context, projectID ProjectID, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserInboxMessagesRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1302,8 +1305,8 @@ func (c *Client) PostUserInboxMessages(ctx context.Context, body PostUserInboxMe return c.Client.Do(req) } -func (c *Client) PostUserInboxArchivedWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserInboxArchivedRequestWithBody(c.Server, contentType, body) +func (c *Client) PostUserInboxArchivedWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserInboxArchivedRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1314,8 +1317,8 @@ func (c *Client) PostUserInboxArchivedWithBody(ctx context.Context, contentType return c.Client.Do(req) } -func (c *Client) PostUserInboxArchived(ctx context.Context, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserInboxArchivedRequest(c.Server, body) +func (c *Client) PostUserInboxArchived(ctx context.Context, projectID ProjectID, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserInboxArchivedRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1326,8 +1329,8 @@ func (c *Client) PostUserInboxArchived(ctx context.Context, body PostUserInboxAr return c.Client.Do(req) } -func (c *Client) GetUserInboxCount(ctx context.Context, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetUserInboxCountRequest(c.Server, params) +func (c *Client) GetUserInboxCount(ctx context.Context, projectID ProjectID, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetUserInboxCountRequest(c.Server, projectID, params) if err != nil { return nil, err } @@ -1338,8 +1341,8 @@ func (c *Client) GetUserInboxCount(ctx context.Context, params *GetUserInboxCoun return c.Client.Do(req) } -func (c *Client) PostUserInboxReadWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserInboxReadRequestWithBody(c.Server, contentType, body) +func (c *Client) PostUserInboxReadWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserInboxReadRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1350,8 +1353,8 @@ func (c *Client) PostUserInboxReadWithBody(ctx context.Context, contentType stri return c.Client.Do(req) } -func (c *Client) PostUserInboxRead(ctx context.Context, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostUserInboxReadRequest(c.Server, body) +func (c *Client) PostUserInboxRead(ctx context.Context, projectID ProjectID, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostUserInboxReadRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1362,8 +1365,8 @@ func (c *Client) PostUserInboxRead(ctx context.Context, body PostUserInboxReadJS return c.Client.Do(req) } -func (c *Client) DeleteUserScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteUserScheduledClientRequestWithBody(c.Server, contentType, body) +func (c *Client) DeleteUserScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteUserScheduledClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1374,8 +1377,8 @@ func (c *Client) DeleteUserScheduledClientWithBody(ctx context.Context, contentT return c.Client.Do(req) } -func (c *Client) DeleteUserScheduledClient(ctx context.Context, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteUserScheduledClientRequest(c.Server, body) +func (c *Client) DeleteUserScheduledClient(ctx context.Context, projectID ProjectID, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteUserScheduledClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1386,8 +1389,8 @@ func (c *Client) DeleteUserScheduledClient(ctx context.Context, body DeleteUserS return c.Client.Do(req) } -func (c *Client) UpsertUserScheduledClientWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertUserScheduledClientRequestWithBody(c.Server, contentType, body) +func (c *Client) UpsertUserScheduledClientWithBody(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertUserScheduledClientRequestWithBody(c.Server, projectID, contentType, body) if err != nil { return nil, err } @@ -1398,8 +1401,8 @@ func (c *Client) UpsertUserScheduledClientWithBody(ctx context.Context, contentT return c.Client.Do(req) } -func (c *Client) UpsertUserScheduledClient(ctx context.Context, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpsertUserScheduledClientRequest(c.Server, body) +func (c *Client) UpsertUserScheduledClient(ctx context.Context, projectID ProjectID, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertUserScheduledClientRequest(c.Server, projectID, body) if err != nil { return nil, err } @@ -1459,23 +1462,30 @@ func (c *Client) EmailUnsubscribe(ctx context.Context, params *EmailUnsubscribeP } // NewCreateSessionRequest calls the generic CreateSession builder with application/json body -func NewCreateSessionRequest(server string, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody) (*http.Request, error) { +func NewCreateSessionRequest(server string, projectID ProjectID, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewCreateSessionRequestWithBody(server, authMethodID, "application/json", bodyReader) + return NewCreateSessionRequestWithBody(server, projectID, authMethodID, "application/json", bodyReader) } // NewCreateSessionRequestWithBody generates requests for CreateSession with any type of body -func NewCreateSessionRequestWithBody(server string, authMethodID openapi_types.UUID, contentType string, body io.Reader) (*http.Request, error) { +func NewCreateSessionRequestWithBody(server string, projectID ProjectID, authMethodID openapi_types.UUID, contentType string, body io.Reader) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "authMethodID", authMethodID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithOptions("simple", false, "authMethodID", authMethodID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) if err != nil { return nil, err } @@ -1485,7 +1495,7 @@ func NewCreateSessionRequestWithBody(server string, authMethodID openapi_types.U return nil, err } - operationPath := fmt.Sprintf("/api/client/auth-methods/%s/sessions", pathParam0) + operationPath := fmt.Sprintf("/api/client/projects/%s/auth-methods/%s/sessions", pathParam0, pathParam1) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1506,26 +1516,33 @@ func NewCreateSessionRequestWithBody(server string, authMethodID openapi_types.U } // NewDeleteOrganizationClientRequest calls the generic DeleteOrganizationClient builder with application/json body -func NewDeleteOrganizationClientRequest(server string, body DeleteOrganizationClientJSONRequestBody) (*http.Request, error) { +func NewDeleteOrganizationClientRequest(server string, projectID ProjectID, body DeleteOrganizationClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewDeleteOrganizationClientRequestWithBody(server, "application/json", bodyReader) + return NewDeleteOrganizationClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewDeleteOrganizationClientRequestWithBody generates requests for DeleteOrganizationClient with any type of body -func NewDeleteOrganizationClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewDeleteOrganizationClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1546,26 +1563,33 @@ func NewDeleteOrganizationClientRequestWithBody(server string, contentType strin } // NewUpsertOrganizationClientRequest calls the generic UpsertOrganizationClient builder with application/json body -func NewUpsertOrganizationClientRequest(server string, body UpsertOrganizationClientJSONRequestBody) (*http.Request, error) { +func NewUpsertOrganizationClientRequest(server string, projectID ProjectID, body UpsertOrganizationClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewUpsertOrganizationClientRequestWithBody(server, "application/json", bodyReader) + return NewUpsertOrganizationClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewUpsertOrganizationClientRequestWithBody generates requests for UpsertOrganizationClient with any type of body -func NewUpsertOrganizationClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewUpsertOrganizationClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1586,26 +1610,33 @@ func NewUpsertOrganizationClientRequestWithBody(server string, contentType strin } // NewPostOrganizationEventsClientRequest calls the generic PostOrganizationEventsClient builder with application/json body -func NewPostOrganizationEventsClientRequest(server string, body PostOrganizationEventsClientJSONRequestBody) (*http.Request, error) { +func NewPostOrganizationEventsClientRequest(server string, projectID ProjectID, body PostOrganizationEventsClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostOrganizationEventsClientRequestWithBody(server, "application/json", bodyReader) + return NewPostOrganizationEventsClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostOrganizationEventsClientRequestWithBody generates requests for PostOrganizationEventsClient with any type of body -func NewPostOrganizationEventsClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostOrganizationEventsClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/events") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/events", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1626,15 +1657,22 @@ func NewPostOrganizationEventsClientRequestWithBody(server string, contentType s } // NewGetOrganizationInboxRequest generates requests for GetOrganizationInbox -func NewGetOrganizationInboxRequest(server string, params *GetOrganizationInboxParams) (*http.Request, error) { +func NewGetOrganizationInboxRequest(server string, projectID ProjectID, params *GetOrganizationInboxParams) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/inbox") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/inbox", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1764,26 +1802,33 @@ func NewGetOrganizationInboxRequest(server string, params *GetOrganizationInboxP } // NewPostOrganizationInboxMessagesRequest calls the generic PostOrganizationInboxMessages builder with application/json body -func NewPostOrganizationInboxMessagesRequest(server string, body PostOrganizationInboxMessagesJSONRequestBody) (*http.Request, error) { +func NewPostOrganizationInboxMessagesRequest(server string, projectID ProjectID, body PostOrganizationInboxMessagesJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostOrganizationInboxMessagesRequestWithBody(server, "application/json", bodyReader) + return NewPostOrganizationInboxMessagesRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostOrganizationInboxMessagesRequestWithBody generates requests for PostOrganizationInboxMessages with any type of body -func NewPostOrganizationInboxMessagesRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostOrganizationInboxMessagesRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/inbox") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/inbox", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1804,26 +1849,33 @@ func NewPostOrganizationInboxMessagesRequestWithBody(server string, contentType } // NewPostOrganizationInboxArchivedRequest calls the generic PostOrganizationInboxArchived builder with application/json body -func NewPostOrganizationInboxArchivedRequest(server string, body PostOrganizationInboxArchivedJSONRequestBody) (*http.Request, error) { +func NewPostOrganizationInboxArchivedRequest(server string, projectID ProjectID, body PostOrganizationInboxArchivedJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostOrganizationInboxArchivedRequestWithBody(server, "application/json", bodyReader) + return NewPostOrganizationInboxArchivedRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostOrganizationInboxArchivedRequestWithBody generates requests for PostOrganizationInboxArchived with any type of body -func NewPostOrganizationInboxArchivedRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostOrganizationInboxArchivedRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/inbox/archived") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/inbox/archived", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1844,15 +1896,22 @@ func NewPostOrganizationInboxArchivedRequestWithBody(server string, contentType } // NewGetOrganizationInboxCountRequest generates requests for GetOrganizationInboxCount -func NewGetOrganizationInboxCountRequest(server string, params *GetOrganizationInboxCountParams) (*http.Request, error) { +func NewGetOrganizationInboxCountRequest(server string, projectID ProjectID, params *GetOrganizationInboxCountParams) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/inbox/count") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/inbox/count", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1910,26 +1969,33 @@ func NewGetOrganizationInboxCountRequest(server string, params *GetOrganizationI } // NewPostOrganizationInboxReadRequest calls the generic PostOrganizationInboxRead builder with application/json body -func NewPostOrganizationInboxReadRequest(server string, body PostOrganizationInboxReadJSONRequestBody) (*http.Request, error) { +func NewPostOrganizationInboxReadRequest(server string, projectID ProjectID, body PostOrganizationInboxReadJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostOrganizationInboxReadRequestWithBody(server, "application/json", bodyReader) + return NewPostOrganizationInboxReadRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostOrganizationInboxReadRequestWithBody generates requests for PostOrganizationInboxRead with any type of body -func NewPostOrganizationInboxReadRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostOrganizationInboxReadRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/inbox/read") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/inbox/read", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1950,26 +2016,33 @@ func NewPostOrganizationInboxReadRequestWithBody(server string, contentType stri } // NewDeleteOrganizationScheduledClientRequest calls the generic DeleteOrganizationScheduledClient builder with application/json body -func NewDeleteOrganizationScheduledClientRequest(server string, body DeleteOrganizationScheduledClientJSONRequestBody) (*http.Request, error) { +func NewDeleteOrganizationScheduledClientRequest(server string, projectID ProjectID, body DeleteOrganizationScheduledClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewDeleteOrganizationScheduledClientRequestWithBody(server, "application/json", bodyReader) + return NewDeleteOrganizationScheduledClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewDeleteOrganizationScheduledClientRequestWithBody generates requests for DeleteOrganizationScheduledClient with any type of body -func NewDeleteOrganizationScheduledClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewDeleteOrganizationScheduledClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/scheduled") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/scheduled", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -1990,26 +2063,33 @@ func NewDeleteOrganizationScheduledClientRequestWithBody(server string, contentT } // NewUpsertOrganizationScheduledClientRequest calls the generic UpsertOrganizationScheduledClient builder with application/json body -func NewUpsertOrganizationScheduledClientRequest(server string, body UpsertOrganizationScheduledClientJSONRequestBody) (*http.Request, error) { +func NewUpsertOrganizationScheduledClientRequest(server string, projectID ProjectID, body UpsertOrganizationScheduledClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewUpsertOrganizationScheduledClientRequestWithBody(server, "application/json", bodyReader) + return NewUpsertOrganizationScheduledClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewUpsertOrganizationScheduledClientRequestWithBody generates requests for UpsertOrganizationScheduledClient with any type of body -func NewUpsertOrganizationScheduledClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewUpsertOrganizationScheduledClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/scheduled") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/scheduled", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2030,26 +2110,33 @@ func NewUpsertOrganizationScheduledClientRequestWithBody(server string, contentT } // NewRemoveOrganizationUserClientRequest calls the generic RemoveOrganizationUserClient builder with application/json body -func NewRemoveOrganizationUserClientRequest(server string, body RemoveOrganizationUserClientJSONRequestBody) (*http.Request, error) { +func NewRemoveOrganizationUserClientRequest(server string, projectID ProjectID, body RemoveOrganizationUserClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewRemoveOrganizationUserClientRequestWithBody(server, "application/json", bodyReader) + return NewRemoveOrganizationUserClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewRemoveOrganizationUserClientRequestWithBody generates requests for RemoveOrganizationUserClient with any type of body -func NewRemoveOrganizationUserClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewRemoveOrganizationUserClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/users") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/users", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2070,26 +2157,33 @@ func NewRemoveOrganizationUserClientRequestWithBody(server string, contentType s } // NewAddOrganizationUserClientRequest calls the generic AddOrganizationUserClient builder with application/json body -func NewAddOrganizationUserClientRequest(server string, body AddOrganizationUserClientJSONRequestBody) (*http.Request, error) { +func NewAddOrganizationUserClientRequest(server string, projectID ProjectID, body AddOrganizationUserClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewAddOrganizationUserClientRequestWithBody(server, "application/json", bodyReader) + return NewAddOrganizationUserClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewAddOrganizationUserClientRequestWithBody generates requests for AddOrganizationUserClient with any type of body -func NewAddOrganizationUserClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewAddOrganizationUserClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/organizations/users") + operationPath := fmt.Sprintf("/api/client/projects/%s/organizations/users", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2110,15 +2204,22 @@ func NewAddOrganizationUserClientRequestWithBody(server string, contentType stri } // NewGetVapidPublicKeyRequest generates requests for GetVapidPublicKey -func NewGetVapidPublicKeyRequest(server string) (*http.Request, error) { +func NewGetVapidPublicKeyRequest(server string, projectID ProjectID) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/push/vapid") + operationPath := fmt.Sprintf("/api/client/projects/%s/push/vapid", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2137,26 +2238,33 @@ func NewGetVapidPublicKeyRequest(server string) (*http.Request, error) { } // NewDeleteUserClientRequest calls the generic DeleteUserClient builder with application/json body -func NewDeleteUserClientRequest(server string, body DeleteUserClientJSONRequestBody) (*http.Request, error) { +func NewDeleteUserClientRequest(server string, projectID ProjectID, body DeleteUserClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewDeleteUserClientRequestWithBody(server, "application/json", bodyReader) + return NewDeleteUserClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewDeleteUserClientRequestWithBody generates requests for DeleteUserClient with any type of body -func NewDeleteUserClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewDeleteUserClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users") + operationPath := fmt.Sprintf("/api/client/projects/%s/users", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2177,26 +2285,33 @@ func NewDeleteUserClientRequestWithBody(server string, contentType string, body } // NewUpsertUserClientRequest calls the generic UpsertUserClient builder with application/json body -func NewUpsertUserClientRequest(server string, body UpsertUserClientJSONRequestBody) (*http.Request, error) { +func NewUpsertUserClientRequest(server string, projectID ProjectID, body UpsertUserClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewUpsertUserClientRequestWithBody(server, "application/json", bodyReader) + return NewUpsertUserClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewUpsertUserClientRequestWithBody generates requests for UpsertUserClient with any type of body -func NewUpsertUserClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewUpsertUserClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users") + operationPath := fmt.Sprintf("/api/client/projects/%s/users", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2217,26 +2332,33 @@ func NewUpsertUserClientRequestWithBody(server string, contentType string, body } // NewRegisterDeviceRequest calls the generic RegisterDevice builder with application/json body -func NewRegisterDeviceRequest(server string, body RegisterDeviceJSONRequestBody) (*http.Request, error) { +func NewRegisterDeviceRequest(server string, projectID ProjectID, body RegisterDeviceJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewRegisterDeviceRequestWithBody(server, "application/json", bodyReader) + return NewRegisterDeviceRequestWithBody(server, projectID, "application/json", bodyReader) } // NewRegisterDeviceRequestWithBody generates requests for RegisterDevice with any type of body -func NewRegisterDeviceRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewRegisterDeviceRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/devices") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/devices", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2257,26 +2379,33 @@ func NewRegisterDeviceRequestWithBody(server string, contentType string, body io } // NewPostUserEventsRequest calls the generic PostUserEvents builder with application/json body -func NewPostUserEventsRequest(server string, body PostUserEventsJSONRequestBody) (*http.Request, error) { +func NewPostUserEventsRequest(server string, projectID ProjectID, body PostUserEventsJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostUserEventsRequestWithBody(server, "application/json", bodyReader) + return NewPostUserEventsRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostUserEventsRequestWithBody generates requests for PostUserEvents with any type of body -func NewPostUserEventsRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostUserEventsRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/events") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/events", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2297,15 +2426,22 @@ func NewPostUserEventsRequestWithBody(server string, contentType string, body io } // NewGetUserInboxRequest generates requests for GetUserInbox -func NewGetUserInboxRequest(server string, params *GetUserInboxParams) (*http.Request, error) { +func NewGetUserInboxRequest(server string, projectID ProjectID, params *GetUserInboxParams) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/inbox") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/inbox", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2435,26 +2571,33 @@ func NewGetUserInboxRequest(server string, params *GetUserInboxParams) (*http.Re } // NewPostUserInboxMessagesRequest calls the generic PostUserInboxMessages builder with application/json body -func NewPostUserInboxMessagesRequest(server string, body PostUserInboxMessagesJSONRequestBody) (*http.Request, error) { +func NewPostUserInboxMessagesRequest(server string, projectID ProjectID, body PostUserInboxMessagesJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostUserInboxMessagesRequestWithBody(server, "application/json", bodyReader) + return NewPostUserInboxMessagesRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostUserInboxMessagesRequestWithBody generates requests for PostUserInboxMessages with any type of body -func NewPostUserInboxMessagesRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostUserInboxMessagesRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/inbox") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/inbox", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2475,26 +2618,33 @@ func NewPostUserInboxMessagesRequestWithBody(server string, contentType string, } // NewPostUserInboxArchivedRequest calls the generic PostUserInboxArchived builder with application/json body -func NewPostUserInboxArchivedRequest(server string, body PostUserInboxArchivedJSONRequestBody) (*http.Request, error) { +func NewPostUserInboxArchivedRequest(server string, projectID ProjectID, body PostUserInboxArchivedJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostUserInboxArchivedRequestWithBody(server, "application/json", bodyReader) + return NewPostUserInboxArchivedRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostUserInboxArchivedRequestWithBody generates requests for PostUserInboxArchived with any type of body -func NewPostUserInboxArchivedRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostUserInboxArchivedRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/inbox/archived") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/inbox/archived", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2515,15 +2665,22 @@ func NewPostUserInboxArchivedRequestWithBody(server string, contentType string, } // NewGetUserInboxCountRequest generates requests for GetUserInboxCount -func NewGetUserInboxCountRequest(server string, params *GetUserInboxCountParams) (*http.Request, error) { +func NewGetUserInboxCountRequest(server string, projectID ProjectID, params *GetUserInboxCountParams) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/inbox/count") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/inbox/count", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2581,26 +2738,33 @@ func NewGetUserInboxCountRequest(server string, params *GetUserInboxCountParams) } // NewPostUserInboxReadRequest calls the generic PostUserInboxRead builder with application/json body -func NewPostUserInboxReadRequest(server string, body PostUserInboxReadJSONRequestBody) (*http.Request, error) { +func NewPostUserInboxReadRequest(server string, projectID ProjectID, body PostUserInboxReadJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewPostUserInboxReadRequestWithBody(server, "application/json", bodyReader) + return NewPostUserInboxReadRequestWithBody(server, projectID, "application/json", bodyReader) } // NewPostUserInboxReadRequestWithBody generates requests for PostUserInboxRead with any type of body -func NewPostUserInboxReadRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewPostUserInboxReadRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/inbox/read") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/inbox/read", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2621,26 +2785,33 @@ func NewPostUserInboxReadRequestWithBody(server string, contentType string, body } // NewDeleteUserScheduledClientRequest calls the generic DeleteUserScheduledClient builder with application/json body -func NewDeleteUserScheduledClientRequest(server string, body DeleteUserScheduledClientJSONRequestBody) (*http.Request, error) { +func NewDeleteUserScheduledClientRequest(server string, projectID ProjectID, body DeleteUserScheduledClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewDeleteUserScheduledClientRequestWithBody(server, "application/json", bodyReader) + return NewDeleteUserScheduledClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewDeleteUserScheduledClientRequestWithBody generates requests for DeleteUserScheduledClient with any type of body -func NewDeleteUserScheduledClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewDeleteUserScheduledClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/scheduled") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/scheduled", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2661,26 +2832,33 @@ func NewDeleteUserScheduledClientRequestWithBody(server string, contentType stri } // NewUpsertUserScheduledClientRequest calls the generic UpsertUserScheduledClient builder with application/json body -func NewUpsertUserScheduledClientRequest(server string, body UpsertUserScheduledClientJSONRequestBody) (*http.Request, error) { +func NewUpsertUserScheduledClientRequest(server string, projectID ProjectID, body UpsertUserScheduledClientJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader buf, err := json.Marshal(body) if err != nil { return nil, err } bodyReader = bytes.NewReader(buf) - return NewUpsertUserScheduledClientRequestWithBody(server, "application/json", bodyReader) + return NewUpsertUserScheduledClientRequestWithBody(server, projectID, "application/json", bodyReader) } // NewUpsertUserScheduledClientRequestWithBody generates requests for UpsertUserScheduledClient with any type of body -func NewUpsertUserScheduledClientRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { +func NewUpsertUserScheduledClientRequestWithBody(server string, projectID ProjectID, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithOptions("simple", false, "projectID", projectID, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: "uuid"}) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/api/client/users/scheduled") + operationPath := fmt.Sprintf("/api/client/projects/%s/users/scheduled", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -2889,119 +3067,119 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { // CreateSessionWithBodyWithResponse request with any body - CreateSessionWithBodyWithResponse(ctx context.Context, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) + CreateSessionWithBodyWithResponse(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) - CreateSessionWithResponse(ctx context.Context, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) + CreateSessionWithResponse(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) // DeleteOrganizationClientWithBodyWithResponse request with any body - DeleteOrganizationClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) + DeleteOrganizationClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) - DeleteOrganizationClientWithResponse(ctx context.Context, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) + DeleteOrganizationClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) // UpsertOrganizationClientWithBodyWithResponse request with any body - UpsertOrganizationClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) + UpsertOrganizationClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) - UpsertOrganizationClientWithResponse(ctx context.Context, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) + UpsertOrganizationClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) // PostOrganizationEventsClientWithBodyWithResponse request with any body - PostOrganizationEventsClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) + PostOrganizationEventsClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) - PostOrganizationEventsClientWithResponse(ctx context.Context, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) + PostOrganizationEventsClientWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) // GetOrganizationInboxWithResponse request - GetOrganizationInboxWithResponse(ctx context.Context, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxResponse, error) + GetOrganizationInboxWithResponse(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxResponse, error) // PostOrganizationInboxMessagesWithBodyWithResponse request with any body - PostOrganizationInboxMessagesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) + PostOrganizationInboxMessagesWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) - PostOrganizationInboxMessagesWithResponse(ctx context.Context, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) + PostOrganizationInboxMessagesWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) // PostOrganizationInboxArchivedWithBodyWithResponse request with any body - PostOrganizationInboxArchivedWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) + PostOrganizationInboxArchivedWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) - PostOrganizationInboxArchivedWithResponse(ctx context.Context, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) + PostOrganizationInboxArchivedWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) // GetOrganizationInboxCountWithResponse request - GetOrganizationInboxCountWithResponse(ctx context.Context, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxCountResponse, error) + GetOrganizationInboxCountWithResponse(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxCountResponse, error) // PostOrganizationInboxReadWithBodyWithResponse request with any body - PostOrganizationInboxReadWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) + PostOrganizationInboxReadWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) - PostOrganizationInboxReadWithResponse(ctx context.Context, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) + PostOrganizationInboxReadWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) // DeleteOrganizationScheduledClientWithBodyWithResponse request with any body - DeleteOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) + DeleteOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) - DeleteOrganizationScheduledClientWithResponse(ctx context.Context, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) + DeleteOrganizationScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) // UpsertOrganizationScheduledClientWithBodyWithResponse request with any body - UpsertOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) + UpsertOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) - UpsertOrganizationScheduledClientWithResponse(ctx context.Context, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) + UpsertOrganizationScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) // RemoveOrganizationUserClientWithBodyWithResponse request with any body - RemoveOrganizationUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) + RemoveOrganizationUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) - RemoveOrganizationUserClientWithResponse(ctx context.Context, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) + RemoveOrganizationUserClientWithResponse(ctx context.Context, projectID ProjectID, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) // AddOrganizationUserClientWithBodyWithResponse request with any body - AddOrganizationUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) + AddOrganizationUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) - AddOrganizationUserClientWithResponse(ctx context.Context, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) + AddOrganizationUserClientWithResponse(ctx context.Context, projectID ProjectID, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) // GetVapidPublicKeyWithResponse request - GetVapidPublicKeyWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetVapidPublicKeyResponse, error) + GetVapidPublicKeyWithResponse(ctx context.Context, projectID ProjectID, reqEditors ...RequestEditorFn) (*GetVapidPublicKeyResponse, error) // DeleteUserClientWithBodyWithResponse request with any body - DeleteUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) + DeleteUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) - DeleteUserClientWithResponse(ctx context.Context, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) + DeleteUserClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) // UpsertUserClientWithBodyWithResponse request with any body - UpsertUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) + UpsertUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) - UpsertUserClientWithResponse(ctx context.Context, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) + UpsertUserClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) // RegisterDeviceWithBodyWithResponse request with any body - RegisterDeviceWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) + RegisterDeviceWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) - RegisterDeviceWithResponse(ctx context.Context, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) + RegisterDeviceWithResponse(ctx context.Context, projectID ProjectID, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) // PostUserEventsWithBodyWithResponse request with any body - PostUserEventsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) + PostUserEventsWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) - PostUserEventsWithResponse(ctx context.Context, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) + PostUserEventsWithResponse(ctx context.Context, projectID ProjectID, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) // GetUserInboxWithResponse request - GetUserInboxWithResponse(ctx context.Context, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*GetUserInboxResponse, error) + GetUserInboxWithResponse(ctx context.Context, projectID ProjectID, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*GetUserInboxResponse, error) // PostUserInboxMessagesWithBodyWithResponse request with any body - PostUserInboxMessagesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) + PostUserInboxMessagesWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) - PostUserInboxMessagesWithResponse(ctx context.Context, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) + PostUserInboxMessagesWithResponse(ctx context.Context, projectID ProjectID, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) // PostUserInboxArchivedWithBodyWithResponse request with any body - PostUserInboxArchivedWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) + PostUserInboxArchivedWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) - PostUserInboxArchivedWithResponse(ctx context.Context, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) + PostUserInboxArchivedWithResponse(ctx context.Context, projectID ProjectID, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) // GetUserInboxCountWithResponse request - GetUserInboxCountWithResponse(ctx context.Context, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*GetUserInboxCountResponse, error) + GetUserInboxCountWithResponse(ctx context.Context, projectID ProjectID, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*GetUserInboxCountResponse, error) // PostUserInboxReadWithBodyWithResponse request with any body - PostUserInboxReadWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) + PostUserInboxReadWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) - PostUserInboxReadWithResponse(ctx context.Context, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) + PostUserInboxReadWithResponse(ctx context.Context, projectID ProjectID, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) // DeleteUserScheduledClientWithBodyWithResponse request with any body - DeleteUserScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) + DeleteUserScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) - DeleteUserScheduledClientWithResponse(ctx context.Context, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) + DeleteUserScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) // UpsertUserScheduledClientWithBodyWithResponse request with any body - UpsertUserScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) + UpsertUserScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) - UpsertUserScheduledClientWithResponse(ctx context.Context, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) + UpsertUserScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) // GetPreferencesPageWithResponse request GetPreferencesPageWithResponse(ctx context.Context, projectID openapi_types.UUID, userID openapi_types.UUID, reqEditors ...RequestEditorFn) (*GetPreferencesPageResponse, error) @@ -3863,16 +4041,16 @@ func (r EmailUnsubscribeResponse) ContentType() string { } // CreateSessionWithBodyWithResponse request with arbitrary body returning *CreateSessionResponse -func (c *ClientWithResponses) CreateSessionWithBodyWithResponse(ctx context.Context, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) { - rsp, err := c.CreateSessionWithBody(ctx, authMethodID, contentType, body, reqEditors...) +func (c *ClientWithResponses) CreateSessionWithBodyWithResponse(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) { + rsp, err := c.CreateSessionWithBody(ctx, projectID, authMethodID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseCreateSessionResponse(rsp) } -func (c *ClientWithResponses) CreateSessionWithResponse(ctx context.Context, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) { - rsp, err := c.CreateSession(ctx, authMethodID, body, reqEditors...) +func (c *ClientWithResponses) CreateSessionWithResponse(ctx context.Context, projectID ProjectID, authMethodID openapi_types.UUID, body CreateSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateSessionResponse, error) { + rsp, err := c.CreateSession(ctx, projectID, authMethodID, body, reqEditors...) if err != nil { return nil, err } @@ -3880,16 +4058,16 @@ func (c *ClientWithResponses) CreateSessionWithResponse(ctx context.Context, aut } // DeleteOrganizationClientWithBodyWithResponse request with arbitrary body returning *DeleteOrganizationClientResponse -func (c *ClientWithResponses) DeleteOrganizationClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) { - rsp, err := c.DeleteOrganizationClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) DeleteOrganizationClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) { + rsp, err := c.DeleteOrganizationClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseDeleteOrganizationClientResponse(rsp) } -func (c *ClientWithResponses) DeleteOrganizationClientWithResponse(ctx context.Context, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) { - rsp, err := c.DeleteOrganizationClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) DeleteOrganizationClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationClientResponse, error) { + rsp, err := c.DeleteOrganizationClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -3897,16 +4075,16 @@ func (c *ClientWithResponses) DeleteOrganizationClientWithResponse(ctx context.C } // UpsertOrganizationClientWithBodyWithResponse request with arbitrary body returning *UpsertOrganizationClientResponse -func (c *ClientWithResponses) UpsertOrganizationClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) { - rsp, err := c.UpsertOrganizationClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) UpsertOrganizationClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) { + rsp, err := c.UpsertOrganizationClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseUpsertOrganizationClientResponse(rsp) } -func (c *ClientWithResponses) UpsertOrganizationClientWithResponse(ctx context.Context, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) { - rsp, err := c.UpsertOrganizationClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) UpsertOrganizationClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertOrganizationClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationClientResponse, error) { + rsp, err := c.UpsertOrganizationClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -3914,16 +4092,16 @@ func (c *ClientWithResponses) UpsertOrganizationClientWithResponse(ctx context.C } // PostOrganizationEventsClientWithBodyWithResponse request with arbitrary body returning *PostOrganizationEventsClientResponse -func (c *ClientWithResponses) PostOrganizationEventsClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) { - rsp, err := c.PostOrganizationEventsClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationEventsClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) { + rsp, err := c.PostOrganizationEventsClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostOrganizationEventsClientResponse(rsp) } -func (c *ClientWithResponses) PostOrganizationEventsClientWithResponse(ctx context.Context, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) { - rsp, err := c.PostOrganizationEventsClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationEventsClientWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationEventsClientJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationEventsClientResponse, error) { + rsp, err := c.PostOrganizationEventsClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -3931,8 +4109,8 @@ func (c *ClientWithResponses) PostOrganizationEventsClientWithResponse(ctx conte } // GetOrganizationInboxWithResponse request returning *GetOrganizationInboxResponse -func (c *ClientWithResponses) GetOrganizationInboxWithResponse(ctx context.Context, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxResponse, error) { - rsp, err := c.GetOrganizationInbox(ctx, params, reqEditors...) +func (c *ClientWithResponses) GetOrganizationInboxWithResponse(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxResponse, error) { + rsp, err := c.GetOrganizationInbox(ctx, projectID, params, reqEditors...) if err != nil { return nil, err } @@ -3940,16 +4118,16 @@ func (c *ClientWithResponses) GetOrganizationInboxWithResponse(ctx context.Conte } // PostOrganizationInboxMessagesWithBodyWithResponse request with arbitrary body returning *PostOrganizationInboxMessagesResponse -func (c *ClientWithResponses) PostOrganizationInboxMessagesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) { - rsp, err := c.PostOrganizationInboxMessagesWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationInboxMessagesWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) { + rsp, err := c.PostOrganizationInboxMessagesWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostOrganizationInboxMessagesResponse(rsp) } -func (c *ClientWithResponses) PostOrganizationInboxMessagesWithResponse(ctx context.Context, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) { - rsp, err := c.PostOrganizationInboxMessages(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationInboxMessagesWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxMessagesResponse, error) { + rsp, err := c.PostOrganizationInboxMessages(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -3957,16 +4135,16 @@ func (c *ClientWithResponses) PostOrganizationInboxMessagesWithResponse(ctx cont } // PostOrganizationInboxArchivedWithBodyWithResponse request with arbitrary body returning *PostOrganizationInboxArchivedResponse -func (c *ClientWithResponses) PostOrganizationInboxArchivedWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) { - rsp, err := c.PostOrganizationInboxArchivedWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationInboxArchivedWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) { + rsp, err := c.PostOrganizationInboxArchivedWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostOrganizationInboxArchivedResponse(rsp) } -func (c *ClientWithResponses) PostOrganizationInboxArchivedWithResponse(ctx context.Context, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) { - rsp, err := c.PostOrganizationInboxArchived(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationInboxArchivedWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxArchivedResponse, error) { + rsp, err := c.PostOrganizationInboxArchived(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -3974,8 +4152,8 @@ func (c *ClientWithResponses) PostOrganizationInboxArchivedWithResponse(ctx cont } // GetOrganizationInboxCountWithResponse request returning *GetOrganizationInboxCountResponse -func (c *ClientWithResponses) GetOrganizationInboxCountWithResponse(ctx context.Context, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxCountResponse, error) { - rsp, err := c.GetOrganizationInboxCount(ctx, params, reqEditors...) +func (c *ClientWithResponses) GetOrganizationInboxCountWithResponse(ctx context.Context, projectID ProjectID, params *GetOrganizationInboxCountParams, reqEditors ...RequestEditorFn) (*GetOrganizationInboxCountResponse, error) { + rsp, err := c.GetOrganizationInboxCount(ctx, projectID, params, reqEditors...) if err != nil { return nil, err } @@ -3983,16 +4161,16 @@ func (c *ClientWithResponses) GetOrganizationInboxCountWithResponse(ctx context. } // PostOrganizationInboxReadWithBodyWithResponse request with arbitrary body returning *PostOrganizationInboxReadResponse -func (c *ClientWithResponses) PostOrganizationInboxReadWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) { - rsp, err := c.PostOrganizationInboxReadWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationInboxReadWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) { + rsp, err := c.PostOrganizationInboxReadWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostOrganizationInboxReadResponse(rsp) } -func (c *ClientWithResponses) PostOrganizationInboxReadWithResponse(ctx context.Context, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) { - rsp, err := c.PostOrganizationInboxRead(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostOrganizationInboxReadWithResponse(ctx context.Context, projectID ProjectID, body PostOrganizationInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOrganizationInboxReadResponse, error) { + rsp, err := c.PostOrganizationInboxRead(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4000,16 +4178,16 @@ func (c *ClientWithResponses) PostOrganizationInboxReadWithResponse(ctx context. } // DeleteOrganizationScheduledClientWithBodyWithResponse request with arbitrary body returning *DeleteOrganizationScheduledClientResponse -func (c *ClientWithResponses) DeleteOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) { - rsp, err := c.DeleteOrganizationScheduledClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) DeleteOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) { + rsp, err := c.DeleteOrganizationScheduledClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseDeleteOrganizationScheduledClientResponse(rsp) } -func (c *ClientWithResponses) DeleteOrganizationScheduledClientWithResponse(ctx context.Context, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) { - rsp, err := c.DeleteOrganizationScheduledClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) DeleteOrganizationScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteOrganizationScheduledClientResponse, error) { + rsp, err := c.DeleteOrganizationScheduledClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4017,16 +4195,16 @@ func (c *ClientWithResponses) DeleteOrganizationScheduledClientWithResponse(ctx } // UpsertOrganizationScheduledClientWithBodyWithResponse request with arbitrary body returning *UpsertOrganizationScheduledClientResponse -func (c *ClientWithResponses) UpsertOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) { - rsp, err := c.UpsertOrganizationScheduledClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) UpsertOrganizationScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) { + rsp, err := c.UpsertOrganizationScheduledClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseUpsertOrganizationScheduledClientResponse(rsp) } -func (c *ClientWithResponses) UpsertOrganizationScheduledClientWithResponse(ctx context.Context, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) { - rsp, err := c.UpsertOrganizationScheduledClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) UpsertOrganizationScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertOrganizationScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertOrganizationScheduledClientResponse, error) { + rsp, err := c.UpsertOrganizationScheduledClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4034,16 +4212,16 @@ func (c *ClientWithResponses) UpsertOrganizationScheduledClientWithResponse(ctx } // RemoveOrganizationUserClientWithBodyWithResponse request with arbitrary body returning *RemoveOrganizationUserClientResponse -func (c *ClientWithResponses) RemoveOrganizationUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) { - rsp, err := c.RemoveOrganizationUserClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) RemoveOrganizationUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) { + rsp, err := c.RemoveOrganizationUserClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseRemoveOrganizationUserClientResponse(rsp) } -func (c *ClientWithResponses) RemoveOrganizationUserClientWithResponse(ctx context.Context, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) { - rsp, err := c.RemoveOrganizationUserClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) RemoveOrganizationUserClientWithResponse(ctx context.Context, projectID ProjectID, body RemoveOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*RemoveOrganizationUserClientResponse, error) { + rsp, err := c.RemoveOrganizationUserClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4051,16 +4229,16 @@ func (c *ClientWithResponses) RemoveOrganizationUserClientWithResponse(ctx conte } // AddOrganizationUserClientWithBodyWithResponse request with arbitrary body returning *AddOrganizationUserClientResponse -func (c *ClientWithResponses) AddOrganizationUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) { - rsp, err := c.AddOrganizationUserClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) AddOrganizationUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) { + rsp, err := c.AddOrganizationUserClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseAddOrganizationUserClientResponse(rsp) } -func (c *ClientWithResponses) AddOrganizationUserClientWithResponse(ctx context.Context, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) { - rsp, err := c.AddOrganizationUserClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) AddOrganizationUserClientWithResponse(ctx context.Context, projectID ProjectID, body AddOrganizationUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*AddOrganizationUserClientResponse, error) { + rsp, err := c.AddOrganizationUserClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4068,8 +4246,8 @@ func (c *ClientWithResponses) AddOrganizationUserClientWithResponse(ctx context. } // GetVapidPublicKeyWithResponse request returning *GetVapidPublicKeyResponse -func (c *ClientWithResponses) GetVapidPublicKeyWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetVapidPublicKeyResponse, error) { - rsp, err := c.GetVapidPublicKey(ctx, reqEditors...) +func (c *ClientWithResponses) GetVapidPublicKeyWithResponse(ctx context.Context, projectID ProjectID, reqEditors ...RequestEditorFn) (*GetVapidPublicKeyResponse, error) { + rsp, err := c.GetVapidPublicKey(ctx, projectID, reqEditors...) if err != nil { return nil, err } @@ -4077,16 +4255,16 @@ func (c *ClientWithResponses) GetVapidPublicKeyWithResponse(ctx context.Context, } // DeleteUserClientWithBodyWithResponse request with arbitrary body returning *DeleteUserClientResponse -func (c *ClientWithResponses) DeleteUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) { - rsp, err := c.DeleteUserClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) DeleteUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) { + rsp, err := c.DeleteUserClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseDeleteUserClientResponse(rsp) } -func (c *ClientWithResponses) DeleteUserClientWithResponse(ctx context.Context, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) { - rsp, err := c.DeleteUserClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) DeleteUserClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserClientResponse, error) { + rsp, err := c.DeleteUserClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4094,16 +4272,16 @@ func (c *ClientWithResponses) DeleteUserClientWithResponse(ctx context.Context, } // UpsertUserClientWithBodyWithResponse request with arbitrary body returning *UpsertUserClientResponse -func (c *ClientWithResponses) UpsertUserClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) { - rsp, err := c.UpsertUserClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) UpsertUserClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) { + rsp, err := c.UpsertUserClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseUpsertUserClientResponse(rsp) } -func (c *ClientWithResponses) UpsertUserClientWithResponse(ctx context.Context, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) { - rsp, err := c.UpsertUserClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) UpsertUserClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertUserClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserClientResponse, error) { + rsp, err := c.UpsertUserClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4111,16 +4289,16 @@ func (c *ClientWithResponses) UpsertUserClientWithResponse(ctx context.Context, } // RegisterDeviceWithBodyWithResponse request with arbitrary body returning *RegisterDeviceResponse -func (c *ClientWithResponses) RegisterDeviceWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) { - rsp, err := c.RegisterDeviceWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) RegisterDeviceWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) { + rsp, err := c.RegisterDeviceWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseRegisterDeviceResponse(rsp) } -func (c *ClientWithResponses) RegisterDeviceWithResponse(ctx context.Context, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) { - rsp, err := c.RegisterDevice(ctx, body, reqEditors...) +func (c *ClientWithResponses) RegisterDeviceWithResponse(ctx context.Context, projectID ProjectID, body RegisterDeviceJSONRequestBody, reqEditors ...RequestEditorFn) (*RegisterDeviceResponse, error) { + rsp, err := c.RegisterDevice(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4128,16 +4306,16 @@ func (c *ClientWithResponses) RegisterDeviceWithResponse(ctx context.Context, bo } // PostUserEventsWithBodyWithResponse request with arbitrary body returning *PostUserEventsResponse -func (c *ClientWithResponses) PostUserEventsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) { - rsp, err := c.PostUserEventsWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostUserEventsWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) { + rsp, err := c.PostUserEventsWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostUserEventsResponse(rsp) } -func (c *ClientWithResponses) PostUserEventsWithResponse(ctx context.Context, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) { - rsp, err := c.PostUserEvents(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostUserEventsWithResponse(ctx context.Context, projectID ProjectID, body PostUserEventsJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserEventsResponse, error) { + rsp, err := c.PostUserEvents(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4145,8 +4323,8 @@ func (c *ClientWithResponses) PostUserEventsWithResponse(ctx context.Context, bo } // GetUserInboxWithResponse request returning *GetUserInboxResponse -func (c *ClientWithResponses) GetUserInboxWithResponse(ctx context.Context, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*GetUserInboxResponse, error) { - rsp, err := c.GetUserInbox(ctx, params, reqEditors...) +func (c *ClientWithResponses) GetUserInboxWithResponse(ctx context.Context, projectID ProjectID, params *GetUserInboxParams, reqEditors ...RequestEditorFn) (*GetUserInboxResponse, error) { + rsp, err := c.GetUserInbox(ctx, projectID, params, reqEditors...) if err != nil { return nil, err } @@ -4154,16 +4332,16 @@ func (c *ClientWithResponses) GetUserInboxWithResponse(ctx context.Context, para } // PostUserInboxMessagesWithBodyWithResponse request with arbitrary body returning *PostUserInboxMessagesResponse -func (c *ClientWithResponses) PostUserInboxMessagesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) { - rsp, err := c.PostUserInboxMessagesWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostUserInboxMessagesWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) { + rsp, err := c.PostUserInboxMessagesWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostUserInboxMessagesResponse(rsp) } -func (c *ClientWithResponses) PostUserInboxMessagesWithResponse(ctx context.Context, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) { - rsp, err := c.PostUserInboxMessages(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostUserInboxMessagesWithResponse(ctx context.Context, projectID ProjectID, body PostUserInboxMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxMessagesResponse, error) { + rsp, err := c.PostUserInboxMessages(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4171,16 +4349,16 @@ func (c *ClientWithResponses) PostUserInboxMessagesWithResponse(ctx context.Cont } // PostUserInboxArchivedWithBodyWithResponse request with arbitrary body returning *PostUserInboxArchivedResponse -func (c *ClientWithResponses) PostUserInboxArchivedWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) { - rsp, err := c.PostUserInboxArchivedWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostUserInboxArchivedWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) { + rsp, err := c.PostUserInboxArchivedWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostUserInboxArchivedResponse(rsp) } -func (c *ClientWithResponses) PostUserInboxArchivedWithResponse(ctx context.Context, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) { - rsp, err := c.PostUserInboxArchived(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostUserInboxArchivedWithResponse(ctx context.Context, projectID ProjectID, body PostUserInboxArchivedJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxArchivedResponse, error) { + rsp, err := c.PostUserInboxArchived(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4188,8 +4366,8 @@ func (c *ClientWithResponses) PostUserInboxArchivedWithResponse(ctx context.Cont } // GetUserInboxCountWithResponse request returning *GetUserInboxCountResponse -func (c *ClientWithResponses) GetUserInboxCountWithResponse(ctx context.Context, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*GetUserInboxCountResponse, error) { - rsp, err := c.GetUserInboxCount(ctx, params, reqEditors...) +func (c *ClientWithResponses) GetUserInboxCountWithResponse(ctx context.Context, projectID ProjectID, params *GetUserInboxCountParams, reqEditors ...RequestEditorFn) (*GetUserInboxCountResponse, error) { + rsp, err := c.GetUserInboxCount(ctx, projectID, params, reqEditors...) if err != nil { return nil, err } @@ -4197,16 +4375,16 @@ func (c *ClientWithResponses) GetUserInboxCountWithResponse(ctx context.Context, } // PostUserInboxReadWithBodyWithResponse request with arbitrary body returning *PostUserInboxReadResponse -func (c *ClientWithResponses) PostUserInboxReadWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) { - rsp, err := c.PostUserInboxReadWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) PostUserInboxReadWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) { + rsp, err := c.PostUserInboxReadWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParsePostUserInboxReadResponse(rsp) } -func (c *ClientWithResponses) PostUserInboxReadWithResponse(ctx context.Context, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) { - rsp, err := c.PostUserInboxRead(ctx, body, reqEditors...) +func (c *ClientWithResponses) PostUserInboxReadWithResponse(ctx context.Context, projectID ProjectID, body PostUserInboxReadJSONRequestBody, reqEditors ...RequestEditorFn) (*PostUserInboxReadResponse, error) { + rsp, err := c.PostUserInboxRead(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4214,16 +4392,16 @@ func (c *ClientWithResponses) PostUserInboxReadWithResponse(ctx context.Context, } // DeleteUserScheduledClientWithBodyWithResponse request with arbitrary body returning *DeleteUserScheduledClientResponse -func (c *ClientWithResponses) DeleteUserScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) { - rsp, err := c.DeleteUserScheduledClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) DeleteUserScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) { + rsp, err := c.DeleteUserScheduledClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseDeleteUserScheduledClientResponse(rsp) } -func (c *ClientWithResponses) DeleteUserScheduledClientWithResponse(ctx context.Context, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) { - rsp, err := c.DeleteUserScheduledClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) DeleteUserScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body DeleteUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteUserScheduledClientResponse, error) { + rsp, err := c.DeleteUserScheduledClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -4231,16 +4409,16 @@ func (c *ClientWithResponses) DeleteUserScheduledClientWithResponse(ctx context. } // UpsertUserScheduledClientWithBodyWithResponse request with arbitrary body returning *UpsertUserScheduledClientResponse -func (c *ClientWithResponses) UpsertUserScheduledClientWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) { - rsp, err := c.UpsertUserScheduledClientWithBody(ctx, contentType, body, reqEditors...) +func (c *ClientWithResponses) UpsertUserScheduledClientWithBodyWithResponse(ctx context.Context, projectID ProjectID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) { + rsp, err := c.UpsertUserScheduledClientWithBody(ctx, projectID, contentType, body, reqEditors...) if err != nil { return nil, err } return ParseUpsertUserScheduledClientResponse(rsp) } -func (c *ClientWithResponses) UpsertUserScheduledClientWithResponse(ctx context.Context, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) { - rsp, err := c.UpsertUserScheduledClient(ctx, body, reqEditors...) +func (c *ClientWithResponses) UpsertUserScheduledClientWithResponse(ctx context.Context, projectID ProjectID, body UpsertUserScheduledClientJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertUserScheduledClientResponse, error) { + rsp, err := c.UpsertUserScheduledClient(ctx, projectID, body, reqEditors...) if err != nil { return nil, err } @@ -5053,80 +5231,80 @@ func ParseEmailUnsubscribeResponse(rsp *http.Response) (*EmailUnsubscribeRespons // ServerInterface represents all server handlers. type ServerInterface interface { // Mint a session token - // (POST /api/client/auth-methods/{authMethodID}/sessions) - CreateSession(w http.ResponseWriter, r *http.Request, authMethodID openapi_types.UUID) + // (POST /api/client/projects/{projectID}/auth-methods/{authMethodID}/sessions) + CreateSession(w http.ResponseWriter, r *http.Request, projectID ProjectID, authMethodID openapi_types.UUID) // Delete organization - // (DELETE /api/client/organizations) - DeleteOrganizationClient(w http.ResponseWriter, r *http.Request) + // (DELETE /api/client/projects/{projectID}/organizations) + DeleteOrganizationClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Upsert organization - // (POST /api/client/organizations) - UpsertOrganizationClient(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/organizations) + UpsertOrganizationClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Post organization events - // (POST /api/client/organizations/events) - PostOrganizationEventsClient(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/organizations/events) + PostOrganizationEventsClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Query organization inbox messages - // (GET /api/client/organizations/inbox) - GetOrganizationInbox(w http.ResponseWriter, r *http.Request, params GetOrganizationInboxParams) + // (GET /api/client/projects/{projectID}/organizations/inbox) + GetOrganizationInbox(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetOrganizationInboxParams) // Create organization inbox messages - // (POST /api/client/organizations/inbox) - PostOrganizationInboxMessages(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/organizations/inbox) + PostOrganizationInboxMessages(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Mark organization inbox messages archived - // (POST /api/client/organizations/inbox/archived) - PostOrganizationInboxArchived(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/organizations/inbox/archived) + PostOrganizationInboxArchived(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Count organization inbox messages - // (GET /api/client/organizations/inbox/count) - GetOrganizationInboxCount(w http.ResponseWriter, r *http.Request, params GetOrganizationInboxCountParams) + // (GET /api/client/projects/{projectID}/organizations/inbox/count) + GetOrganizationInboxCount(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetOrganizationInboxCountParams) // Mark organization inbox messages read - // (POST /api/client/organizations/inbox/read) - PostOrganizationInboxRead(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/organizations/inbox/read) + PostOrganizationInboxRead(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Delete organization scheduled - // (DELETE /api/client/organizations/scheduled) - DeleteOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) + // (DELETE /api/client/projects/{projectID}/organizations/scheduled) + DeleteOrganizationScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Upsert organization scheduled - // (POST /api/client/organizations/scheduled) - UpsertOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/organizations/scheduled) + UpsertOrganizationScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Remove user from organization - // (DELETE /api/client/organizations/users) - RemoveOrganizationUserClient(w http.ResponseWriter, r *http.Request) + // (DELETE /api/client/projects/{projectID}/organizations/users) + RemoveOrganizationUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Add user to organization - // (POST /api/client/organizations/users) - AddOrganizationUserClient(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/organizations/users) + AddOrganizationUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Get VAPID public key - // (GET /api/client/push/vapid) - GetVapidPublicKey(w http.ResponseWriter, r *http.Request) + // (GET /api/client/projects/{projectID}/push/vapid) + GetVapidPublicKey(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Delete user - // (DELETE /api/client/users) - DeleteUserClient(w http.ResponseWriter, r *http.Request) + // (DELETE /api/client/projects/{projectID}/users) + DeleteUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Upsert user - // (POST /api/client/users) - UpsertUserClient(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/users) + UpsertUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Register device - // (POST /api/client/users/devices) - RegisterDevice(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/users/devices) + RegisterDevice(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Post user events - // (POST /api/client/users/events) - PostUserEvents(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/users/events) + PostUserEvents(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Query user inbox messages - // (GET /api/client/users/inbox) - GetUserInbox(w http.ResponseWriter, r *http.Request, params GetUserInboxParams) + // (GET /api/client/projects/{projectID}/users/inbox) + GetUserInbox(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetUserInboxParams) // Create user inbox messages - // (POST /api/client/users/inbox) - PostUserInboxMessages(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/users/inbox) + PostUserInboxMessages(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Mark user inbox messages archived - // (POST /api/client/users/inbox/archived) - PostUserInboxArchived(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/users/inbox/archived) + PostUserInboxArchived(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Count user inbox messages - // (GET /api/client/users/inbox/count) - GetUserInboxCount(w http.ResponseWriter, r *http.Request, params GetUserInboxCountParams) + // (GET /api/client/projects/{projectID}/users/inbox/count) + GetUserInboxCount(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetUserInboxCountParams) // Mark user inbox messages read - // (POST /api/client/users/inbox/read) - PostUserInboxRead(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/users/inbox/read) + PostUserInboxRead(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Delete user scheduled - // (DELETE /api/client/users/scheduled) - DeleteUserScheduledClient(w http.ResponseWriter, r *http.Request) + // (DELETE /api/client/projects/{projectID}/users/scheduled) + DeleteUserScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Upsert user scheduled - // (POST /api/client/users/scheduled) - UpsertUserScheduledClient(w http.ResponseWriter, r *http.Request) + // (POST /api/client/projects/{projectID}/users/scheduled) + UpsertUserScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) // Subscription preferences page // (GET /preferences/{projectID}/{userID}) GetPreferencesPage(w http.ResponseWriter, r *http.Request, projectID openapi_types.UUID, userID openapi_types.UUID) @@ -5143,152 +5321,152 @@ type ServerInterface interface { type Unimplemented struct{} // Mint a session token -// (POST /api/client/auth-methods/{authMethodID}/sessions) -func (_ Unimplemented) CreateSession(w http.ResponseWriter, r *http.Request, authMethodID openapi_types.UUID) { +// (POST /api/client/projects/{projectID}/auth-methods/{authMethodID}/sessions) +func (_ Unimplemented) CreateSession(w http.ResponseWriter, r *http.Request, projectID ProjectID, authMethodID openapi_types.UUID) { w.WriteHeader(http.StatusNotImplemented) } // Delete organization -// (DELETE /api/client/organizations) -func (_ Unimplemented) DeleteOrganizationClient(w http.ResponseWriter, r *http.Request) { +// (DELETE /api/client/projects/{projectID}/organizations) +func (_ Unimplemented) DeleteOrganizationClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Upsert organization -// (POST /api/client/organizations) -func (_ Unimplemented) UpsertOrganizationClient(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/organizations) +func (_ Unimplemented) UpsertOrganizationClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Post organization events -// (POST /api/client/organizations/events) -func (_ Unimplemented) PostOrganizationEventsClient(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/organizations/events) +func (_ Unimplemented) PostOrganizationEventsClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Query organization inbox messages -// (GET /api/client/organizations/inbox) -func (_ Unimplemented) GetOrganizationInbox(w http.ResponseWriter, r *http.Request, params GetOrganizationInboxParams) { +// (GET /api/client/projects/{projectID}/organizations/inbox) +func (_ Unimplemented) GetOrganizationInbox(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetOrganizationInboxParams) { w.WriteHeader(http.StatusNotImplemented) } // Create organization inbox messages -// (POST /api/client/organizations/inbox) -func (_ Unimplemented) PostOrganizationInboxMessages(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/organizations/inbox) +func (_ Unimplemented) PostOrganizationInboxMessages(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Mark organization inbox messages archived -// (POST /api/client/organizations/inbox/archived) -func (_ Unimplemented) PostOrganizationInboxArchived(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/organizations/inbox/archived) +func (_ Unimplemented) PostOrganizationInboxArchived(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Count organization inbox messages -// (GET /api/client/organizations/inbox/count) -func (_ Unimplemented) GetOrganizationInboxCount(w http.ResponseWriter, r *http.Request, params GetOrganizationInboxCountParams) { +// (GET /api/client/projects/{projectID}/organizations/inbox/count) +func (_ Unimplemented) GetOrganizationInboxCount(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetOrganizationInboxCountParams) { w.WriteHeader(http.StatusNotImplemented) } // Mark organization inbox messages read -// (POST /api/client/organizations/inbox/read) -func (_ Unimplemented) PostOrganizationInboxRead(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/organizations/inbox/read) +func (_ Unimplemented) PostOrganizationInboxRead(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Delete organization scheduled -// (DELETE /api/client/organizations/scheduled) -func (_ Unimplemented) DeleteOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) { +// (DELETE /api/client/projects/{projectID}/organizations/scheduled) +func (_ Unimplemented) DeleteOrganizationScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Upsert organization scheduled -// (POST /api/client/organizations/scheduled) -func (_ Unimplemented) UpsertOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/organizations/scheduled) +func (_ Unimplemented) UpsertOrganizationScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Remove user from organization -// (DELETE /api/client/organizations/users) -func (_ Unimplemented) RemoveOrganizationUserClient(w http.ResponseWriter, r *http.Request) { +// (DELETE /api/client/projects/{projectID}/organizations/users) +func (_ Unimplemented) RemoveOrganizationUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Add user to organization -// (POST /api/client/organizations/users) -func (_ Unimplemented) AddOrganizationUserClient(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/organizations/users) +func (_ Unimplemented) AddOrganizationUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Get VAPID public key -// (GET /api/client/push/vapid) -func (_ Unimplemented) GetVapidPublicKey(w http.ResponseWriter, r *http.Request) { +// (GET /api/client/projects/{projectID}/push/vapid) +func (_ Unimplemented) GetVapidPublicKey(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Delete user -// (DELETE /api/client/users) -func (_ Unimplemented) DeleteUserClient(w http.ResponseWriter, r *http.Request) { +// (DELETE /api/client/projects/{projectID}/users) +func (_ Unimplemented) DeleteUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Upsert user -// (POST /api/client/users) -func (_ Unimplemented) UpsertUserClient(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/users) +func (_ Unimplemented) UpsertUserClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Register device -// (POST /api/client/users/devices) -func (_ Unimplemented) RegisterDevice(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/users/devices) +func (_ Unimplemented) RegisterDevice(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Post user events -// (POST /api/client/users/events) -func (_ Unimplemented) PostUserEvents(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/users/events) +func (_ Unimplemented) PostUserEvents(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Query user inbox messages -// (GET /api/client/users/inbox) -func (_ Unimplemented) GetUserInbox(w http.ResponseWriter, r *http.Request, params GetUserInboxParams) { +// (GET /api/client/projects/{projectID}/users/inbox) +func (_ Unimplemented) GetUserInbox(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetUserInboxParams) { w.WriteHeader(http.StatusNotImplemented) } // Create user inbox messages -// (POST /api/client/users/inbox) -func (_ Unimplemented) PostUserInboxMessages(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/users/inbox) +func (_ Unimplemented) PostUserInboxMessages(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Mark user inbox messages archived -// (POST /api/client/users/inbox/archived) -func (_ Unimplemented) PostUserInboxArchived(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/users/inbox/archived) +func (_ Unimplemented) PostUserInboxArchived(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Count user inbox messages -// (GET /api/client/users/inbox/count) -func (_ Unimplemented) GetUserInboxCount(w http.ResponseWriter, r *http.Request, params GetUserInboxCountParams) { +// (GET /api/client/projects/{projectID}/users/inbox/count) +func (_ Unimplemented) GetUserInboxCount(w http.ResponseWriter, r *http.Request, projectID ProjectID, params GetUserInboxCountParams) { w.WriteHeader(http.StatusNotImplemented) } // Mark user inbox messages read -// (POST /api/client/users/inbox/read) -func (_ Unimplemented) PostUserInboxRead(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/users/inbox/read) +func (_ Unimplemented) PostUserInboxRead(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Delete user scheduled -// (DELETE /api/client/users/scheduled) -func (_ Unimplemented) DeleteUserScheduledClient(w http.ResponseWriter, r *http.Request) { +// (DELETE /api/client/projects/{projectID}/users/scheduled) +func (_ Unimplemented) DeleteUserScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } // Upsert user scheduled -// (POST /api/client/users/scheduled) -func (_ Unimplemented) UpsertUserScheduledClient(w http.ResponseWriter, r *http.Request) { +// (POST /api/client/projects/{projectID}/users/scheduled) +func (_ Unimplemented) UpsertUserScheduledClient(w http.ResponseWriter, r *http.Request, projectID ProjectID) { w.WriteHeader(http.StatusNotImplemented) } @@ -5325,6 +5503,15 @@ func (siw *ServerInterfaceWrapper) CreateSession(w http.ResponseWriter, r *http. var err error _ = err + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + // ------------- Path parameter "authMethodID" ------------- var authMethodID openapi_types.UUID @@ -5341,7 +5528,7 @@ func (siw *ServerInterfaceWrapper) CreateSession(w http.ResponseWriter, r *http. r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.CreateSession(w, r, authMethodID) + siw.Handler.CreateSession(w, r, projectID, authMethodID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5354,6 +5541,18 @@ func (siw *ServerInterfaceWrapper) CreateSession(w http.ResponseWriter, r *http. // DeleteOrganizationClient operation middleware func (siw *ServerInterfaceWrapper) DeleteOrganizationClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5361,7 +5560,7 @@ func (siw *ServerInterfaceWrapper) DeleteOrganizationClient(w http.ResponseWrite r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.DeleteOrganizationClient(w, r) + siw.Handler.DeleteOrganizationClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5374,6 +5573,18 @@ func (siw *ServerInterfaceWrapper) DeleteOrganizationClient(w http.ResponseWrite // UpsertOrganizationClient operation middleware func (siw *ServerInterfaceWrapper) UpsertOrganizationClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5381,7 +5592,7 @@ func (siw *ServerInterfaceWrapper) UpsertOrganizationClient(w http.ResponseWrite r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.UpsertOrganizationClient(w, r) + siw.Handler.UpsertOrganizationClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5394,6 +5605,18 @@ func (siw *ServerInterfaceWrapper) UpsertOrganizationClient(w http.ResponseWrite // PostOrganizationEventsClient operation middleware func (siw *ServerInterfaceWrapper) PostOrganizationEventsClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5401,7 +5624,7 @@ func (siw *ServerInterfaceWrapper) PostOrganizationEventsClient(w http.ResponseW r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostOrganizationEventsClient(w, r) + siw.Handler.PostOrganizationEventsClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5417,6 +5640,15 @@ func (siw *ServerInterfaceWrapper) GetOrganizationInbox(w http.ResponseWriter, r var err error _ = err + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5544,7 +5776,7 @@ func (siw *ServerInterfaceWrapper) GetOrganizationInbox(w http.ResponseWriter, r } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetOrganizationInbox(w, r, params) + siw.Handler.GetOrganizationInbox(w, r, projectID, params) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5557,6 +5789,18 @@ func (siw *ServerInterfaceWrapper) GetOrganizationInbox(w http.ResponseWriter, r // PostOrganizationInboxMessages operation middleware func (siw *ServerInterfaceWrapper) PostOrganizationInboxMessages(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5564,7 +5808,7 @@ func (siw *ServerInterfaceWrapper) PostOrganizationInboxMessages(w http.Response r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostOrganizationInboxMessages(w, r) + siw.Handler.PostOrganizationInboxMessages(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5577,6 +5821,18 @@ func (siw *ServerInterfaceWrapper) PostOrganizationInboxMessages(w http.Response // PostOrganizationInboxArchived operation middleware func (siw *ServerInterfaceWrapper) PostOrganizationInboxArchived(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5584,7 +5840,7 @@ func (siw *ServerInterfaceWrapper) PostOrganizationInboxArchived(w http.Response r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostOrganizationInboxArchived(w, r) + siw.Handler.PostOrganizationInboxArchived(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5600,6 +5856,15 @@ func (siw *ServerInterfaceWrapper) GetOrganizationInboxCount(w http.ResponseWrit var err error _ = err + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5649,7 +5914,7 @@ func (siw *ServerInterfaceWrapper) GetOrganizationInboxCount(w http.ResponseWrit } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetOrganizationInboxCount(w, r, params) + siw.Handler.GetOrganizationInboxCount(w, r, projectID, params) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5662,6 +5927,18 @@ func (siw *ServerInterfaceWrapper) GetOrganizationInboxCount(w http.ResponseWrit // PostOrganizationInboxRead operation middleware func (siw *ServerInterfaceWrapper) PostOrganizationInboxRead(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5669,7 +5946,7 @@ func (siw *ServerInterfaceWrapper) PostOrganizationInboxRead(w http.ResponseWrit r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostOrganizationInboxRead(w, r) + siw.Handler.PostOrganizationInboxRead(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5682,6 +5959,18 @@ func (siw *ServerInterfaceWrapper) PostOrganizationInboxRead(w http.ResponseWrit // DeleteOrganizationScheduledClient operation middleware func (siw *ServerInterfaceWrapper) DeleteOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5689,7 +5978,7 @@ func (siw *ServerInterfaceWrapper) DeleteOrganizationScheduledClient(w http.Resp r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.DeleteOrganizationScheduledClient(w, r) + siw.Handler.DeleteOrganizationScheduledClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5702,6 +5991,18 @@ func (siw *ServerInterfaceWrapper) DeleteOrganizationScheduledClient(w http.Resp // UpsertOrganizationScheduledClient operation middleware func (siw *ServerInterfaceWrapper) UpsertOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5709,7 +6010,7 @@ func (siw *ServerInterfaceWrapper) UpsertOrganizationScheduledClient(w http.Resp r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.UpsertOrganizationScheduledClient(w, r) + siw.Handler.UpsertOrganizationScheduledClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5722,6 +6023,18 @@ func (siw *ServerInterfaceWrapper) UpsertOrganizationScheduledClient(w http.Resp // RemoveOrganizationUserClient operation middleware func (siw *ServerInterfaceWrapper) RemoveOrganizationUserClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5729,7 +6042,7 @@ func (siw *ServerInterfaceWrapper) RemoveOrganizationUserClient(w http.ResponseW r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.RemoveOrganizationUserClient(w, r) + siw.Handler.RemoveOrganizationUserClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5742,6 +6055,18 @@ func (siw *ServerInterfaceWrapper) RemoveOrganizationUserClient(w http.ResponseW // AddOrganizationUserClient operation middleware func (siw *ServerInterfaceWrapper) AddOrganizationUserClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5749,7 +6074,7 @@ func (siw *ServerInterfaceWrapper) AddOrganizationUserClient(w http.ResponseWrit r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.AddOrganizationUserClient(w, r) + siw.Handler.AddOrganizationUserClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5762,6 +6087,18 @@ func (siw *ServerInterfaceWrapper) AddOrganizationUserClient(w http.ResponseWrit // GetVapidPublicKey operation middleware func (siw *ServerInterfaceWrapper) GetVapidPublicKey(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5769,7 +6106,7 @@ func (siw *ServerInterfaceWrapper) GetVapidPublicKey(w http.ResponseWriter, r *h r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetVapidPublicKey(w, r) + siw.Handler.GetVapidPublicKey(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5782,6 +6119,18 @@ func (siw *ServerInterfaceWrapper) GetVapidPublicKey(w http.ResponseWriter, r *h // DeleteUserClient operation middleware func (siw *ServerInterfaceWrapper) DeleteUserClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5789,7 +6138,7 @@ func (siw *ServerInterfaceWrapper) DeleteUserClient(w http.ResponseWriter, r *ht r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.DeleteUserClient(w, r) + siw.Handler.DeleteUserClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5802,6 +6151,18 @@ func (siw *ServerInterfaceWrapper) DeleteUserClient(w http.ResponseWriter, r *ht // UpsertUserClient operation middleware func (siw *ServerInterfaceWrapper) UpsertUserClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5809,7 +6170,7 @@ func (siw *ServerInterfaceWrapper) UpsertUserClient(w http.ResponseWriter, r *ht r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.UpsertUserClient(w, r) + siw.Handler.UpsertUserClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5822,6 +6183,18 @@ func (siw *ServerInterfaceWrapper) UpsertUserClient(w http.ResponseWriter, r *ht // RegisterDevice operation middleware func (siw *ServerInterfaceWrapper) RegisterDevice(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5829,7 +6202,7 @@ func (siw *ServerInterfaceWrapper) RegisterDevice(w http.ResponseWriter, r *http r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.RegisterDevice(w, r) + siw.Handler.RegisterDevice(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5842,6 +6215,18 @@ func (siw *ServerInterfaceWrapper) RegisterDevice(w http.ResponseWriter, r *http // PostUserEvents operation middleware func (siw *ServerInterfaceWrapper) PostUserEvents(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5849,7 +6234,7 @@ func (siw *ServerInterfaceWrapper) PostUserEvents(w http.ResponseWriter, r *http r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostUserEvents(w, r) + siw.Handler.PostUserEvents(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -5865,6 +6250,15 @@ func (siw *ServerInterfaceWrapper) GetUserInbox(w http.ResponseWriter, r *http.R var err error _ = err + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -5992,7 +6386,7 @@ func (siw *ServerInterfaceWrapper) GetUserInbox(w http.ResponseWriter, r *http.R } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetUserInbox(w, r, params) + siw.Handler.GetUserInbox(w, r, projectID, params) })) for _, middleware := range siw.HandlerMiddlewares { @@ -6005,6 +6399,18 @@ func (siw *ServerInterfaceWrapper) GetUserInbox(w http.ResponseWriter, r *http.R // PostUserInboxMessages operation middleware func (siw *ServerInterfaceWrapper) PostUserInboxMessages(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -6012,7 +6418,7 @@ func (siw *ServerInterfaceWrapper) PostUserInboxMessages(w http.ResponseWriter, r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostUserInboxMessages(w, r) + siw.Handler.PostUserInboxMessages(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -6025,6 +6431,18 @@ func (siw *ServerInterfaceWrapper) PostUserInboxMessages(w http.ResponseWriter, // PostUserInboxArchived operation middleware func (siw *ServerInterfaceWrapper) PostUserInboxArchived(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -6032,7 +6450,7 @@ func (siw *ServerInterfaceWrapper) PostUserInboxArchived(w http.ResponseWriter, r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostUserInboxArchived(w, r) + siw.Handler.PostUserInboxArchived(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -6048,6 +6466,15 @@ func (siw *ServerInterfaceWrapper) GetUserInboxCount(w http.ResponseWriter, r *h var err error _ = err + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -6097,7 +6524,7 @@ func (siw *ServerInterfaceWrapper) GetUserInboxCount(w http.ResponseWriter, r *h } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetUserInboxCount(w, r, params) + siw.Handler.GetUserInboxCount(w, r, projectID, params) })) for _, middleware := range siw.HandlerMiddlewares { @@ -6110,6 +6537,18 @@ func (siw *ServerInterfaceWrapper) GetUserInboxCount(w http.ResponseWriter, r *h // PostUserInboxRead operation middleware func (siw *ServerInterfaceWrapper) PostUserInboxRead(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -6117,7 +6556,7 @@ func (siw *ServerInterfaceWrapper) PostUserInboxRead(w http.ResponseWriter, r *h r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostUserInboxRead(w, r) + siw.Handler.PostUserInboxRead(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -6130,6 +6569,18 @@ func (siw *ServerInterfaceWrapper) PostUserInboxRead(w http.ResponseWriter, r *h // DeleteUserScheduledClient operation middleware func (siw *ServerInterfaceWrapper) DeleteUserScheduledClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -6137,7 +6588,7 @@ func (siw *ServerInterfaceWrapper) DeleteUserScheduledClient(w http.ResponseWrit r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.DeleteUserScheduledClient(w, r) + siw.Handler.DeleteUserScheduledClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -6150,6 +6601,18 @@ func (siw *ServerInterfaceWrapper) DeleteUserScheduledClient(w http.ResponseWrit // UpsertUserScheduledClient operation middleware func (siw *ServerInterfaceWrapper) UpsertUserScheduledClient(w http.ResponseWriter, r *http.Request) { + var err error + _ = err + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectID + + err = runtime.BindStyledParameterWithOptions("simple", "projectID", chi.URLParam(r, "projectID"), &projectID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "uuid"}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + ctx := r.Context() ctx = context.WithValue(ctx, HttpBearerAuthScopes, []string{}) @@ -6157,7 +6620,7 @@ func (siw *ServerInterfaceWrapper) UpsertUserScheduledClient(w http.ResponseWrit r = r.WithContext(ctx) handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.UpsertUserScheduledClient(w, r) + siw.Handler.UpsertUserScheduledClient(w, r, projectID) })) for _, middleware := range siw.HandlerMiddlewares { @@ -6384,79 +6847,79 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl } r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/auth-methods/{authMethodID}/sessions", wrapper.CreateSession) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/auth-methods/{authMethodID}/sessions", wrapper.CreateSession) }) r.Group(func(r chi.Router) { - r.Delete(options.BaseURL+"/api/client/organizations", wrapper.DeleteOrganizationClient) + r.Delete(options.BaseURL+"/api/client/projects/{projectID}/organizations", wrapper.DeleteOrganizationClient) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/organizations", wrapper.UpsertOrganizationClient) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/organizations", wrapper.UpsertOrganizationClient) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/organizations/events", wrapper.PostOrganizationEventsClient) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/organizations/events", wrapper.PostOrganizationEventsClient) }) r.Group(func(r chi.Router) { - r.Get(options.BaseURL+"/api/client/organizations/inbox", wrapper.GetOrganizationInbox) + r.Get(options.BaseURL+"/api/client/projects/{projectID}/organizations/inbox", wrapper.GetOrganizationInbox) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/organizations/inbox", wrapper.PostOrganizationInboxMessages) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/organizations/inbox", wrapper.PostOrganizationInboxMessages) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/organizations/inbox/archived", wrapper.PostOrganizationInboxArchived) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/organizations/inbox/archived", wrapper.PostOrganizationInboxArchived) }) r.Group(func(r chi.Router) { - r.Get(options.BaseURL+"/api/client/organizations/inbox/count", wrapper.GetOrganizationInboxCount) + r.Get(options.BaseURL+"/api/client/projects/{projectID}/organizations/inbox/count", wrapper.GetOrganizationInboxCount) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/organizations/inbox/read", wrapper.PostOrganizationInboxRead) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/organizations/inbox/read", wrapper.PostOrganizationInboxRead) }) r.Group(func(r chi.Router) { - r.Delete(options.BaseURL+"/api/client/organizations/scheduled", wrapper.DeleteOrganizationScheduledClient) + r.Delete(options.BaseURL+"/api/client/projects/{projectID}/organizations/scheduled", wrapper.DeleteOrganizationScheduledClient) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/organizations/scheduled", wrapper.UpsertOrganizationScheduledClient) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/organizations/scheduled", wrapper.UpsertOrganizationScheduledClient) }) r.Group(func(r chi.Router) { - r.Delete(options.BaseURL+"/api/client/organizations/users", wrapper.RemoveOrganizationUserClient) + r.Delete(options.BaseURL+"/api/client/projects/{projectID}/organizations/users", wrapper.RemoveOrganizationUserClient) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/organizations/users", wrapper.AddOrganizationUserClient) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/organizations/users", wrapper.AddOrganizationUserClient) }) r.Group(func(r chi.Router) { - r.Get(options.BaseURL+"/api/client/push/vapid", wrapper.GetVapidPublicKey) + r.Get(options.BaseURL+"/api/client/projects/{projectID}/push/vapid", wrapper.GetVapidPublicKey) }) r.Group(func(r chi.Router) { - r.Delete(options.BaseURL+"/api/client/users", wrapper.DeleteUserClient) + r.Delete(options.BaseURL+"/api/client/projects/{projectID}/users", wrapper.DeleteUserClient) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/users", wrapper.UpsertUserClient) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/users", wrapper.UpsertUserClient) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/users/devices", wrapper.RegisterDevice) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/users/devices", wrapper.RegisterDevice) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/users/events", wrapper.PostUserEvents) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/users/events", wrapper.PostUserEvents) }) r.Group(func(r chi.Router) { - r.Get(options.BaseURL+"/api/client/users/inbox", wrapper.GetUserInbox) + r.Get(options.BaseURL+"/api/client/projects/{projectID}/users/inbox", wrapper.GetUserInbox) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/users/inbox", wrapper.PostUserInboxMessages) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/users/inbox", wrapper.PostUserInboxMessages) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/users/inbox/archived", wrapper.PostUserInboxArchived) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/users/inbox/archived", wrapper.PostUserInboxArchived) }) r.Group(func(r chi.Router) { - r.Get(options.BaseURL+"/api/client/users/inbox/count", wrapper.GetUserInboxCount) + r.Get(options.BaseURL+"/api/client/projects/{projectID}/users/inbox/count", wrapper.GetUserInboxCount) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/users/inbox/read", wrapper.PostUserInboxRead) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/users/inbox/read", wrapper.PostUserInboxRead) }) r.Group(func(r chi.Router) { - r.Delete(options.BaseURL+"/api/client/users/scheduled", wrapper.DeleteUserScheduledClient) + r.Delete(options.BaseURL+"/api/client/projects/{projectID}/users/scheduled", wrapper.DeleteUserScheduledClient) }) r.Group(func(r chi.Router) { - r.Post(options.BaseURL+"/api/client/users/scheduled", wrapper.UpsertUserScheduledClient) + r.Post(options.BaseURL+"/api/client/projects/{projectID}/users/scheduled", wrapper.UpsertUserScheduledClient) }) r.Group(func(r chi.Router) { r.Get(options.BaseURL+"/preferences/{projectID}/{userID}", wrapper.GetPreferencesPage) diff --git a/internal/http/controllers/v1/client/organizations.go b/internal/http/controllers/v1/client/organizations.go index 2d36d9dd..7ebc60ba 100644 --- a/internal/http/controllers/v1/client/organizations.go +++ b/internal/http/controllers/v1/client/organizations.go @@ -22,7 +22,7 @@ func NewOrganizationsController(client *ClientController) *OrganizationsControll return &OrganizationsController{ClientController: client} } -func (srv *OrganizationsController) UpsertOrganizationClient(w http.ResponseWriter, r *http.Request) { +func (srv *OrganizationsController) UpsertOrganizationClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "organizations", rbac.Create) if err != nil { oapi.WriteProblem(w, err) @@ -113,7 +113,7 @@ func (srv *OrganizationsController) UpsertOrganizationClient(w http.ResponseWrit json.Write(w, http.StatusOK, orgToClientOAPI(org)) } -func (srv *OrganizationsController) DeleteOrganizationClient(w http.ResponseWriter, r *http.Request) { +func (srv *OrganizationsController) DeleteOrganizationClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "organizations", rbac.Delete) if err != nil { oapi.WriteProblem(w, err) @@ -164,7 +164,7 @@ func (srv *OrganizationsController) DeleteOrganizationClient(w http.ResponseWrit w.WriteHeader(http.StatusNoContent) } -func (srv *OrganizationsController) AddOrganizationUserClient(w http.ResponseWriter, r *http.Request) { +func (srv *OrganizationsController) AddOrganizationUserClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "organizations", rbac.Update) if err != nil { oapi.WriteProblem(w, err) @@ -267,7 +267,7 @@ func (srv *OrganizationsController) AddOrganizationUserClient(w http.ResponseWri w.WriteHeader(http.StatusOK) } -func (srv *OrganizationsController) RemoveOrganizationUserClient(w http.ResponseWriter, r *http.Request) { +func (srv *OrganizationsController) RemoveOrganizationUserClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "organizations", rbac.Update) if err != nil { oapi.WriteProblem(w, err) diff --git a/internal/http/controllers/v1/client/scheduled.go b/internal/http/controllers/v1/client/scheduled.go index 5a034f84..398303ff 100644 --- a/internal/http/controllers/v1/client/scheduled.go +++ b/internal/http/controllers/v1/client/scheduled.go @@ -25,7 +25,7 @@ func NewScheduledController(client *ClientController) *ScheduledController { return &ScheduledController{ClientController: client} } -func (srv *ScheduledController) UpsertUserScheduledClient(w http.ResponseWriter, r *http.Request) { +func (srv *ScheduledController) UpsertUserScheduledClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "scheduled", rbac.Create) if err != nil { oapi.WriteProblem(w, err) @@ -116,7 +116,7 @@ func (srv *ScheduledController) UpsertUserScheduledClient(w http.ResponseWriter, }) } -func (srv *ScheduledController) DeleteUserScheduledClient(w http.ResponseWriter, r *http.Request) { +func (srv *ScheduledController) DeleteUserScheduledClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "scheduled", rbac.Delete) if err != nil { oapi.WriteProblem(w, err) @@ -177,7 +177,7 @@ func (srv *ScheduledController) DeleteUserScheduledClient(w http.ResponseWriter, w.WriteHeader(http.StatusOK) } -func (srv *ScheduledController) UpsertOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) { +func (srv *ScheduledController) UpsertOrganizationScheduledClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "scheduled", rbac.Create) if err != nil { oapi.WriteProblem(w, err) @@ -280,7 +280,7 @@ func (srv *ScheduledController) UpsertOrganizationScheduledClient(w http.Respons }) } -func (srv *ScheduledController) DeleteOrganizationScheduledClient(w http.ResponseWriter, r *http.Request) { +func (srv *ScheduledController) DeleteOrganizationScheduledClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "scheduled", rbac.Delete) if err != nil { oapi.WriteProblem(w, err) diff --git a/internal/http/controllers/v1/client/sessions.go b/internal/http/controllers/v1/client/sessions.go index b6a300b6..49088847 100644 --- a/internal/http/controllers/v1/client/sessions.go +++ b/internal/http/controllers/v1/client/sessions.go @@ -25,9 +25,13 @@ type SessionsController struct { // CreateSession mints a short-lived session token for an end user under a // session policy. It is a privileged backend operation: only an authorized API // key may call it (API keys are private/backend-only), and the session auth -// method named in the path must belong to the key's project. The session's -// permissions come from the policy. -func (srv *SessionsController) CreateSession(w http.ResponseWriter, r *http.Request, authMethodID openapi_types.UUID) { +// method named in the path must belong to the project named in the URL. The +// session's permissions come from the policy. +// +// The URL projectID is authoritative: the auth layer already bound the API key +// to it, so actor.ProjectID equals projectID here, but the session method is +// validated against the URL project directly. +func (srv *SessionsController) CreateSession(w http.ResponseWriter, r *http.Request, projectID oapi.ProjectID, authMethodID openapi_types.UUID) { ctx := r.Context() actor := rbac.FromContext(ctx) @@ -47,9 +51,9 @@ func (srv *SessionsController) CreateSession(w http.ResponseWriter, r *http.Requ return } - // The policy must exist, be a session method, and live in the key's project. + // The policy must exist, be a session method, and live in the URL project. method, err := srv.client.mgmt.GetSessionAuthMethod(authMethodID) - if err != nil || method.ProjectID != actor.ProjectID { + if err != nil || method.ProjectID != projectID { oapi.WriteProblem(w, problem.ErrNotFound(problem.Describe("session auth method not found"))) return } diff --git a/internal/http/controllers/v1/client/users.go b/internal/http/controllers/v1/client/users.go index 0190026a..9920b3ce 100644 --- a/internal/http/controllers/v1/client/users.go +++ b/internal/http/controllers/v1/client/users.go @@ -22,7 +22,7 @@ func NewUsersController(client *ClientController) *UsersController { return &UsersController{ClientController: client} } -func (srv *UsersController) DeleteUserClient(w http.ResponseWriter, r *http.Request) { +func (srv *UsersController) DeleteUserClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "users", rbac.Delete) if err != nil { oapi.WriteProblem(w, err) @@ -71,7 +71,7 @@ func (srv *UsersController) DeleteUserClient(w http.ResponseWriter, r *http.Requ w.WriteHeader(http.StatusNoContent) } -func (srv *UsersController) UpsertUserClient(w http.ResponseWriter, r *http.Request) { +func (srv *UsersController) UpsertUserClient(w http.ResponseWriter, r *http.Request, _ oapi.ProjectID) { projectID, err := srv.engine.AllowedProject(r.Context(), "users", rbac.Create) if err != nil { oapi.WriteProblem(w, err) diff --git a/internal/store/management/auth.go b/internal/store/management/auth.go index 778c17bc..8850a6b3 100644 --- a/internal/store/management/auth.go +++ b/internal/store/management/auth.go @@ -73,21 +73,23 @@ type TrustedIssuerAuthMethod struct { SubjectClaim string `db:"subject_claim"` } -// GetTrustedIssuerByIssuer resolves the trusted_issuer auth method registered -// for the given JWT `iss`. It is used to pick the verification keys and expected -// claims for an incoming external token. The result is cached by issuer -// (read-through); auth-method writes invalidate it. -func (s *AuthStore) GetTrustedIssuerByIssuer(ctx context.Context, issuer string) (*TrustedIssuerAuthMethod, error) { - result, err := s.issuers.GetOrLoad(ctx, issuer, func(ctx context.Context) (TrustedIssuerAuthMethod, error) { +// GetTrustedIssuer resolves the trusted_issuer auth method registered for the +// given JWT `iss` within projectID. Resolution is project-scoped so a +// self-asserted issuer can never be served to a different project. It is used to +// pick the verification keys and expected claims for an incoming external token. +// The result is cached by (projectID, issuer) (read-through); auth-method writes +// invalidate it. +func (s *AuthStore) GetTrustedIssuer(ctx context.Context, projectID uuid.UUID, issuer string) (*TrustedIssuerAuthMethod, error) { + result, err := s.issuers.GetOrLoad(ctx, trustedIssuerCacheKey(projectID, issuer), func(ctx context.Context) (TrustedIssuerAuthMethod, error) { const query = ` SELECT m.id, p.organization_id, m.project_id, m.role, m.subject_scope, t.jwks_url, t.public_cert, t.issuer, t.audience, t.subject_claim FROM auth_method_trusted_issuers t JOIN auth_methods m ON m.id = t.auth_method_id JOIN projects p ON p.id = m.project_id - WHERE t.issuer = $1 AND m.deleted_at IS NULL` + WHERE m.project_id = $1 AND t.issuer = $2 AND m.deleted_at IS NULL` var r TrustedIssuerAuthMethod - if err := s.db.GetContext(ctx, &r, query, issuer); err != nil { + if err := s.db.GetContext(ctx, &r, query, projectID, issuer); err != nil { return TrustedIssuerAuthMethod{}, err } return r, nil @@ -98,6 +100,12 @@ func (s *AuthStore) GetTrustedIssuerByIssuer(ctx context.Context, issuer string) return &result, nil } +// trustedIssuerCacheKey namespaces the issuer cache by project so a method +// registered for project A can never be served to project B from the cache. +func trustedIssuerCacheKey(projectID uuid.UUID, issuer string) string { + return projectID.String() + ":" + issuer +} + // SessionAuthMethod is a session auth method resolved when verifying a minted // session token: its RBAC identity (the scope the session confers) plus its // project/org. diff --git a/internal/store/management/auth_methods.go b/internal/store/management/auth_methods.go index 5e31b783..1bf9c6c7 100644 --- a/internal/store/management/auth_methods.go +++ b/internal/store/management/auth_methods.go @@ -111,11 +111,12 @@ func (s *AuthMethodsStore) invalidateCaches(ctx context.Context, methodID uuid.U return } var row struct { - SecretHash *string `db:"secret_hash"` - Issuer *string `db:"issuer"` + ProjectID uuid.UUID `db:"project_id"` + SecretHash *string `db:"secret_hash"` + Issuer *string `db:"issuer"` } const q = ` - SELECT k.secret_hash, t.issuer + SELECT m.project_id, k.secret_hash, t.issuer FROM auth_methods m LEFT JOIN auth_method_api_keys k ON k.auth_method_id = m.id LEFT JOIN auth_method_trusted_issuers t ON t.auth_method_id = m.id @@ -127,7 +128,7 @@ func (s *AuthMethodsStore) invalidateCaches(ctx context.Context, methodID uuid.U _ = s.apiKeys.Invalidate(ctx, *row.SecretHash) } if row.Issuer != nil { - _ = s.issuers.Invalidate(ctx, *row.Issuer) + _ = s.issuers.Invalidate(ctx, trustedIssuerCacheKey(row.ProjectID, *row.Issuer)) } } @@ -185,7 +186,7 @@ func (s *AuthMethodsStore) CreateAuthMethod(ctx context.Context, projectID uuid. case MethodTypeAPIKey: secret, err = insertAPIKey(ctx, tx, id) case MethodTypeTrustedIssuer: - err = insertTrustedIssuer(ctx, tx, id, in.TrustedIssuer) + err = insertTrustedIssuer(ctx, tx, projectID, id, in.TrustedIssuer) case MethodTypeSession: err = insertSession(ctx, tx, id, in.Session) default: @@ -227,12 +228,13 @@ func insertAPIKey(ctx context.Context, q sqlx.ExecerContext, methodID uuid.UUID) } // insertTrustedIssuer persists a trusted_issuer method's validation config. A -// trusted issuer is resolved at auth time by `iss` alone, with no project -// context, so the active issuer must be globally unique; otherwise a token could -// authenticate against the wrong project. (Soft-deleted methods keep their child -// row, so this is enforced here rather than via a DB constraint that would block -// re-adding a deleted issuer.) -func insertTrustedIssuer(ctx context.Context, q sqlx.ExtContext, methodID uuid.UUID, in *TrustedIssuer) error { +// trusted issuer is resolved at auth time by (project, `iss`), so the active +// issuer must be unique per project; otherwise a token could authenticate against +// the wrong method within the project. The app-level pre-check yields a clean 409 +// (the DB UNIQUE(project_id, issuer) is the backstop). Soft-deleting a method +// hard-deletes its child row (see DeleteAuthMethod), so a deleted issuer is +// re-registerable. +func insertTrustedIssuer(ctx context.Context, q sqlx.ExtContext, projectID, methodID uuid.UUID, in *TrustedIssuer) error { ti := ptr.FromOr(in, TrustedIssuer{}) subjectClaim := ti.SubjectClaim if subjectClaim == "" { @@ -243,18 +245,19 @@ func insertTrustedIssuer(ctx context.Context, q sqlx.ExtContext, methodID uuid.U err := sqlx.GetContext(ctx, q, &existing, `SELECT m.id FROM auth_method_trusted_issuers t JOIN auth_methods m ON m.id = t.auth_method_id - WHERE t.issuer = $1 AND m.deleted_at IS NULL LIMIT 1`, ti.Issuer) + WHERE t.project_id = $1 AND t.issuer = $2 AND m.deleted_at IS NULL LIMIT 1`, projectID, ti.Issuer) if err == nil { - return problem.ErrConflict(problem.Describe("a trusted issuer is already registered for this iss")) + return problem.ErrConflict(problem.Describe("a trusted issuer is already registered for this iss in this project")) } if !errors.Is(err, sql.ErrNoRows) { return err } _, err = q.ExecContext(ctx, - `INSERT INTO auth_method_trusted_issuers (auth_method_id, jwks_url, public_cert, issuer, audience, subject_claim) - VALUES ($1, $2, $3, $4, $5, $6)`, + `INSERT INTO auth_method_trusted_issuers (auth_method_id, project_id, jwks_url, public_cert, issuer, audience, subject_claim) + VALUES ($1, $2, $3, $4, $5, $6, $7)`, methodID, + projectID, sql.NullString{String: ti.JWKSURL, Valid: ti.JWKSURL != ""}, sql.NullString{String: ti.PublicCert, Valid: ti.PublicCert != ""}, ti.Issuer, @@ -524,15 +527,38 @@ func replaceGrants(ctx context.Context, q sqlx.ExtContext, methodID uuid.UUID, g return insertGrants(ctx, q, methodID, grants) } +// DeleteAuthMethod soft-deletes an auth method. For trusted_issuer methods the +// child row is hard-deleted so its (project_id, issuer) is freed for +// re-registration: the issuer uniqueness constraint applies to live child rows +// only, and a soft-deleted parent must not keep occupying an issuer slot. Other +// credential children are kept (their soft-deleted parent excludes them from +// resolution). Cache invalidation runs first because it reads the child row. func (s *AuthMethodsStore) DeleteAuthMethod(ctx context.Context, projectID, methodID uuid.UUID) error { - const stmt = ` - UPDATE auth_methods - SET deleted_at = NOW() - WHERE id = $1 AND project_id = $2 AND deleted_at IS NULL` + // Invalidate before the child row is gone — invalidateCaches resolves the + // credential keys (secret hash, issuer) from the child rows. + s.invalidateCaches(ctx, methodID) - if _, err := s.db.ExecContext(ctx, stmt, methodID, projectID); err != nil { + tx, err := s.begin(ctx) + if err != nil { return err } - s.invalidateCaches(ctx, methodID) - return nil + defer tx.Rollback() //nolint:errcheck // no-op once committed + + res, err := tx.ExecContext(ctx, + `UPDATE auth_methods SET deleted_at = NOW() + WHERE id = $1 AND project_id = $2 AND deleted_at IS NULL`, + methodID, projectID) + if err != nil { + return err + } + // Only free the issuer slot when this call actually deleted the method, so a + // no-op delete (already gone / wrong project) leaves nothing to clean up. + if n, err := res.RowsAffected(); err == nil && n > 0 { + if _, err := tx.ExecContext(ctx, + `DELETE FROM auth_method_trusted_issuers WHERE auth_method_id = $1`, methodID); err != nil { + return err + } + } + + return tx.Commit() } diff --git a/internal/store/management/auth_methods_test.go b/internal/store/management/auth_methods_test.go index a8dff0e6..cb81824c 100644 --- a/internal/store/management/auth_methods_test.go +++ b/internal/store/management/auth_methods_test.go @@ -62,7 +62,7 @@ func TestAuthMethodsStore(t *testing.T) { }) require.NoError(t, err) - resolved, err := db.GetTrustedIssuerByIssuer(ctx, "https://lookup.example") + resolved, err := db.GetTrustedIssuer(ctx, projectID, "https://lookup.example") require.NoError(t, err) assert.Equal(t, created.ID, resolved.ID) assert.Equal(t, projectID, resolved.ProjectID) @@ -71,8 +71,22 @@ func TestAuthMethodsStore(t *testing.T) { assert.Equal(t, "https://lookup.example/jwks.json", *resolved.JWKSURL) assert.Equal(t, "sub", resolved.SubjectClaim) - _, err = db.GetTrustedIssuerByIssuer(ctx, "https://unknown.example") + _, err = db.GetTrustedIssuer(ctx, projectID, "https://unknown.example") assert.Error(t, err) + + // Resolution is project-scoped: the same issuer does not resolve under a + // different project. + otherOrg, err := db.CreateOrganization(ctx, "Other Org") + require.NoError(t, err) + otherProject, err := db.CreateProject(ctx, Project{ + OrganizationID: &otherOrg, + Name: "Other Project", + Timezone: "UTC", + Locale: "en", + }) + require.NoError(t, err) + _, err = db.GetTrustedIssuer(ctx, otherProject, "https://lookup.example") + assert.Error(t, err, "an issuer registered for one project must not resolve under another") }) t.Run("creates a trusted_issuer method", func(t *testing.T) { @@ -216,4 +230,70 @@ func TestAuthMethodsStore(t *testing.T) { require.NoError(t, err) assert.False(t, restricted, "a cleared allow-list is unrestricted") }) + + t.Run("enforces a unique active issuer per project and frees it on delete", func(t *testing.T) { + // A fresh project keeps this independent of the count assertions above. + uniqOrg, err := db.CreateOrganization(ctx, "Uniq Org") + require.NoError(t, err) + uniqProject, err := db.CreateProject(ctx, Project{ + OrganizationID: &uniqOrg, + Name: "Uniq Project", + Timezone: "UTC", + Locale: "en", + }) + require.NoError(t, err) + + const issuer = "https://uniq.example" + first, err := db.CreateAuthMethod(ctx, uniqProject, CreateAuthMethodInput{ + Type: MethodTypeTrustedIssuer, + Name: "uniq idp", + Role: "support", + TrustedIssuer: &TrustedIssuer{JWKSURL: "https://uniq.example/jwks.json", Issuer: issuer}, + }) + require.NoError(t, err) + + // A second active registration of the same issuer in the same project is rejected. + _, err = db.CreateAuthMethod(ctx, uniqProject, CreateAuthMethodInput{ + Type: MethodTypeTrustedIssuer, + Name: "dup idp", + Role: "support", + TrustedIssuer: &TrustedIssuer{JWKSURL: "https://uniq.example/jwks.json", Issuer: issuer}, + }) + require.Error(t, err, "a duplicate active issuer in the same project must be rejected") + + // The same issuer is allowed in a different project. + otherOrg, err := db.CreateOrganization(ctx, "Uniq Org 2") + require.NoError(t, err) + otherProject, err := db.CreateProject(ctx, Project{ + OrganizationID: &otherOrg, + Name: "Uniq Project 2", + Timezone: "UTC", + Locale: "en", + }) + require.NoError(t, err) + _, err = db.CreateAuthMethod(ctx, otherProject, CreateAuthMethodInput{ + Type: MethodTypeTrustedIssuer, + Name: "uniq idp p2", + Role: "support", + TrustedIssuer: &TrustedIssuer{JWKSURL: "https://uniq.example/jwks.json", Issuer: issuer}, + }) + require.NoError(t, err, "the same issuer is allowed under a different project") + + // Deleting the method frees the issuer slot so it can be re-registered. + require.NoError(t, db.DeleteAuthMethod(ctx, uniqProject, first.ID)) + _, err = db.GetTrustedIssuer(ctx, uniqProject, issuer) + assert.Error(t, err, "a deleted issuer no longer resolves") + + reAdded, err := db.CreateAuthMethod(ctx, uniqProject, CreateAuthMethodInput{ + Type: MethodTypeTrustedIssuer, + Name: "uniq idp again", + Role: "support", + TrustedIssuer: &TrustedIssuer{JWKSURL: "https://uniq.example/jwks.json", Issuer: issuer}, + }) + require.NoError(t, err, "re-registration after delete must succeed") + + resolved, err := db.GetTrustedIssuer(ctx, uniqProject, issuer) + require.NoError(t, err) + assert.Equal(t, reAdded.ID, resolved.ID) + }) } diff --git a/internal/store/management/migrations/1764116043_trusted_issuer_project_scope.down.sql b/internal/store/management/migrations/1764116043_trusted_issuer_project_scope.down.sql new file mode 100644 index 00000000..9b199f25 --- /dev/null +++ b/internal/store/management/migrations/1764116043_trusted_issuer_project_scope.down.sql @@ -0,0 +1,8 @@ +-- Reverse 1764116042_trusted_issuer_project_scope: drop the per-project unique +-- constraint and the denormalized project_id column from the child row. + +ALTER TABLE auth_method_trusted_issuers + DROP CONSTRAINT IF EXISTS auth_method_trusted_issuers_project_issuer_uniq; + +ALTER TABLE auth_method_trusted_issuers + DROP COLUMN IF EXISTS project_id; diff --git a/internal/store/management/migrations/1764116043_trusted_issuer_project_scope.up.sql b/internal/store/management/migrations/1764116043_trusted_issuer_project_scope.up.sql new file mode 100644 index 00000000..841c1f51 --- /dev/null +++ b/internal/store/management/migrations/1764116043_trusted_issuer_project_scope.up.sql @@ -0,0 +1,32 @@ +-- Migration: scope trusted issuers to their project. +-- +-- A trusted_issuer auth method is resolved at authentication time by the JWT +-- `iss`. Resolving by `iss` alone (with no project context) lets a token whose +-- self-asserted issuer collides with another project's registration authenticate +-- against the wrong project. The client API now carries the project in the URL, +-- so resolution becomes (project_id, issuer)-scoped and the issuer is unique per +-- project among active methods. +-- +-- The wrinkle: project_id and deleted_at live on the parent auth_methods row, +-- while issuer lives on the child auth_method_trusted_issuers row. We denormalize +-- an immutable project_id onto the child (backfilled from the parent) and add a +-- plain UNIQUE(project_id, issuer). Soft-deleting a method now hard-deletes its +-- trusted-issuer child row (see DeleteAuthMethod), so a deleted issuer is freed +-- and the simple unique constraint does not block re-registration. + +ALTER TABLE auth_method_trusted_issuers + ADD COLUMN project_id UUID REFERENCES projects(id) ON DELETE CASCADE; + +-- Backfill the project from the parent auth method. +UPDATE auth_method_trusted_issuers t +SET project_id = m.project_id +FROM auth_methods m +WHERE m.id = t.auth_method_id; + +ALTER TABLE auth_method_trusted_issuers + ALTER COLUMN project_id SET NOT NULL; + +-- A given issuer may be registered at most once per project. (Re-registration +-- after delete works because the child row is hard-deleted with its parent.) +ALTER TABLE auth_method_trusted_issuers + ADD CONSTRAINT auth_method_trusted_issuers_project_issuer_uniq UNIQUE (project_id, issuer); From 2a62e1f3040d0e2c49e4497fa2268023d2e661b4 Mon Sep 17 00:00:00 2001 From: Jeroen Rinzema Date: Tue, 23 Jun 2026 14:31:15 +0200 Subject: [PATCH 2/4] test(auth): URL project enforcement in client auth middleware --- internal/http/auth/middleware_project_test.go | 287 ++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 internal/http/auth/middleware_project_test.go diff --git a/internal/http/auth/middleware_project_test.go b/internal/http/auth/middleware_project_test.go new file mode 100644 index 00000000..7d434ea2 --- /dev/null +++ b/internal/http/auth/middleware_project_test.go @@ -0,0 +1,287 @@ +package auth + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/go-chi/chi/v5" + "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" + "github.com/lunogram/platform/internal/jwks" + "github.com/lunogram/platform/internal/rbac" + "github.com/lunogram/platform/internal/store/management" + teststore "github.com/lunogram/platform/internal/store/test" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// These tests exercise the client-auth middleware (WithKey, WithTrustedIssuer, +// WithSession) end-to-end against a real management store, proving that the URL +// project binding closes the cross-tenant gap: a credential resolved for project +// A can never act on project B's URL, and a credential fails closed when the URL +// names no project. The path helpers (projectFromRequest / enforceURLProject) +// are unit-tested in project_test.go; this file proves the handlers actually +// invoke them on the resolved credential's project. + +// clientRequestCtx builds a context carrying an in-flight client request whose +// URL (and chi route context) names urlProject, mirroring the middleware +// position after chi has matched /api/client/projects/{projectID}/... +// +// A blank urlProject yields a client URL with no project segment, used for the +// "URL has no project" fail-closed cases. +func clientRequestCtx(urlProject string) context.Context { + path := "/api/client/projects/" + urlProject + "/users" + if urlProject == "" { + path = "/api/client/users" + } + r := httptest.NewRequest(http.MethodPost, path, nil) + if urlProject != "" { + rctx := chi.NewRouteContext() + rctx.URLParams.Add("projectID", urlProject) + r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx)) + } + return withRequest(context.Background(), r) +} + +// twoProjects seeds two independent organizations/projects so a credential made +// in one can be presented on the other's URL. +func twoProjects(t *testing.T, mgmt *management.State) (a, b uuid.UUID) { + t.Helper() + ctx := context.Background() + + orgA, err := mgmt.CreateOrganization(ctx, "Org A") + require.NoError(t, err) + a, err = mgmt.CreateProject(ctx, management.Project{ + OrganizationID: &orgA, Name: "Project A", Timezone: "UTC", Locale: "en", + }) + require.NoError(t, err) + + orgB, err := mgmt.CreateOrganization(ctx, "Org B") + require.NoError(t, err) + b, err = mgmt.CreateProject(ctx, management.Project{ + OrganizationID: &orgB, Name: "Project B", Timezone: "UTC", Locale: "en", + }) + require.NoError(t, err) + + return a, b +} + +// newMgmt builds a real (Postgres-backed) management State with no Redis cache, +// so the auth lookups read straight from the database. +func newMgmt(t *testing.T) *management.State { + t.Helper() + db, _, _ := teststore.RunPostgreSQL(t) + return management.NewState(db) +} + +func TestWithKeyURLProject(t *testing.T) { + t.Parallel() + mgmt := newMgmt(t) + ctx := context.Background() + projectA, projectB := twoProjects(t, mgmt) + + created, err := mgmt.CreateAuthMethod(ctx, projectA, management.CreateAuthMethodInput{ + Type: management.MethodTypeAPIKey, + Name: "server key", + Role: "client", + }) + require.NoError(t, err) + require.NotNil(t, created.Secret) + secret := *created.Secret + + handler := WithKey(mgmt, SurfaceClient) + + t.Run("a key for project A is rejected on project B's URL", func(t *testing.T) { + _, err := handler(clientRequestCtx(projectB.String()), secret) + assert.ErrorIs(t, err, ErrUnauthorized, "a project-A key must not act on project B") + }) + + t.Run("a key for project A succeeds on project A's URL", func(t *testing.T) { + got, err := handler(clientRequestCtx(projectA.String()), secret) + require.NoError(t, err) + actor := rbac.FromContext(got) + require.NotNil(t, actor) + assert.Equal(t, rbac.ActorAPIKey, actor.Type) + assert.Equal(t, projectA, actor.ProjectID, "the actor is scoped to its own project") + }) + + t.Run("a valid key fails closed when the URL names no project", func(t *testing.T) { + _, err := handler(clientRequestCtx(""), secret) + assert.ErrorIs(t, err, ErrUnauthorized) + }) + + t.Run("a valid key fails closed on a malformed project segment", func(t *testing.T) { + _, err := handler(clientRequestCtx("not-a-uuid"), secret) + assert.ErrorIs(t, err, ErrUnauthorized) + }) + + t.Run("an unknown secret is rejected before any project check", func(t *testing.T) { + _, err := handler(clientRequestCtx(projectA.String()), "sk_does_not_exist") + assert.ErrorIs(t, err, ErrUnauthorized) + }) +} + +func TestWithTrustedIssuerURLProject(t *testing.T) { + t.Parallel() + mgmt := newMgmt(t) + ctx := context.Background() + projectA, projectB := twoProjects(t, mgmt) + + // Register the issuer under project A only, verifying with its PEM public key. + key, method := rsaIssuer(t) + _, err := mgmt.CreateAuthMethod(ctx, projectA, management.CreateAuthMethodInput{ + Type: management.MethodTypeTrustedIssuer, + Name: "idp", + Role: "client", + SubjectScope: management.SubjectScopeOwn, + TrustedIssuer: &management.TrustedIssuer{ + PublicCert: *method.PublicCert, + Issuer: testIssuer, + SubjectClaim: "sub", + }, + }) + require.NoError(t, err) + + cache := jwks.New(jwks.Config{}, nil, nil, nil) // PEM path; JWKS unused + handler := WithTrustedIssuer(mgmt, cache) + + token := signRS256(t, key, jwt.MapClaims{ + "iss": testIssuer, + "sub": "end-user-1", + "exp": time.Now().Add(time.Hour).Unix(), + }) + + t.Run("fails closed when the URL names no project", func(t *testing.T) { + _, err := handler(clientRequestCtx(""), token) + assert.ErrorIs(t, err, ErrUnauthorized, "an issuer must not resolve without a URL project") + }) + + t.Run("rejects a token on a project where the issuer is not registered", func(t *testing.T) { + // The issuer is registered only under A; resolution is project-scoped, so a + // self-asserted iss cannot reach project A's method via project B's URL. + _, err := handler(clientRequestCtx(projectB.String()), token) + assert.ErrorIs(t, err, ErrUnauthorized) + }) + + t.Run("authenticates on the matching project URL", func(t *testing.T) { + got, err := handler(clientRequestCtx(projectA.String()), token) + require.NoError(t, err) + actor := rbac.FromContext(got) + require.NotNil(t, actor) + assert.Equal(t, rbac.ActorEndUser, actor.Type) + assert.Equal(t, projectA, actor.ProjectID) + assert.Equal(t, "end-user-1", actor.Subject) + }) +} + +func TestWithSessionURLProject(t *testing.T) { + t.Parallel() + mgmt := newMgmt(t) + ctx := context.Background() + projectA, projectB := twoProjects(t, mgmt) + + sessionMethod, err := mgmt.CreateAuthMethod(ctx, projectA, management.CreateAuthMethodInput{ + Type: management.MethodTypeSession, + Name: "web sessions", + Role: "client", + SubjectScope: management.SubjectScopeOwn, + Session: &management.Session{TTLSeconds: 600}, + }) + require.NoError(t, err) + + signer := testSigner(t, "") + handler := WithSession(mgmt, signer) + + token, _, err := signer.Mint(sessionMethod.ID, "end-user-9", time.Hour) + require.NoError(t, err) + + t.Run("a session minted for project A is rejected on project B's URL", func(t *testing.T) { + _, err := handler(clientRequestCtx(projectB.String()), token) + assert.ErrorIs(t, err, ErrUnauthorized, "a project-A session must not act on project B") + }) + + t.Run("fails closed when the URL names no project", func(t *testing.T) { + _, err := handler(clientRequestCtx(""), token) + assert.ErrorIs(t, err, ErrUnauthorized) + }) + + t.Run("authenticates on the matching project URL", func(t *testing.T) { + got, err := handler(clientRequestCtx(projectA.String()), token) + require.NoError(t, err) + actor := rbac.FromContext(got) + require.NotNil(t, actor) + assert.Equal(t, rbac.ActorEndUser, actor.Type) + assert.Equal(t, projectA, actor.ProjectID) + assert.Equal(t, "end-user-9", actor.Subject) + }) + + t.Run("a nil signer declines (sessions disabled)", func(t *testing.T) { + _, err := WithSession(mgmt, nil)(clientRequestCtx(projectA.String()), token) + assert.ErrorIs(t, err, ErrUnauthorized) + }) +} + +// TestDeleteAuthMethodNoOpKeepsIssuerSlot proves that a no-op delete (wrong +// project, or an already-deleted method) does not free the trusted-issuer slot: +// only a delete that actually soft-deletes the parent hard-deletes the child +// issuer row. This guards the cross-tenant boundary at the store layer — a +// caller scoped to project B must not be able to free project A's issuer slot. +func TestDeleteAuthMethodNoOpKeepsIssuerSlot(t *testing.T) { + t.Parallel() + mgmt := newMgmt(t) + ctx := context.Background() + projectA, projectB := twoProjects(t, mgmt) + + const issuer = "https://keep-slot.example" + created, err := mgmt.CreateAuthMethod(ctx, projectA, management.CreateAuthMethodInput{ + Type: management.MethodTypeTrustedIssuer, + Name: "idp", + Role: "client", + TrustedIssuer: &management.TrustedIssuer{JWKSURL: "https://keep-slot.example/jwks.json", Issuer: issuer}, + }) + require.NoError(t, err) + + t.Run("a delete scoped to the wrong project does not free the slot", func(t *testing.T) { + // Deleting project A's method through project B is a no-op. + require.NoError(t, mgmt.DeleteAuthMethod(ctx, projectB, created.ID)) + + // The issuer still resolves under project A. + resolved, err := mgmt.GetTrustedIssuer(ctx, projectA, issuer) + require.NoError(t, err) + assert.Equal(t, created.ID, resolved.ID) + + // And the slot is still occupied: re-registering the same issuer in A fails. + _, err = mgmt.CreateAuthMethod(ctx, projectA, management.CreateAuthMethodInput{ + Type: management.MethodTypeTrustedIssuer, + Name: "dup idp", + Role: "client", + TrustedIssuer: &management.TrustedIssuer{JWKSURL: "https://keep-slot.example/jwks.json", Issuer: issuer}, + }) + assert.Error(t, err, "the issuer slot must remain occupied after a wrong-project delete") + }) + + t.Run("a real delete frees the slot; a repeat delete is a harmless no-op", func(t *testing.T) { + require.NoError(t, mgmt.DeleteAuthMethod(ctx, projectA, created.ID)) + _, err := mgmt.GetTrustedIssuer(ctx, projectA, issuer) + assert.Error(t, err, "a deleted issuer no longer resolves") + + // Re-registration now succeeds because the slot was freed. + reAdded, err := mgmt.CreateAuthMethod(ctx, projectA, management.CreateAuthMethodInput{ + Type: management.MethodTypeTrustedIssuer, + Name: "idp again", + Role: "client", + TrustedIssuer: &management.TrustedIssuer{JWKSURL: "https://keep-slot.example/jwks.json", Issuer: issuer}, + }) + require.NoError(t, err) + + // Deleting the original id again is a no-op and must not touch the live row + // that now owns the slot. + require.NoError(t, mgmt.DeleteAuthMethod(ctx, projectA, created.ID)) + resolved, err := mgmt.GetTrustedIssuer(ctx, projectA, issuer) + require.NoError(t, err, "the re-added issuer must survive a stale repeat delete") + assert.Equal(t, reAdded.ID, resolved.ID) + }) +} From 36f1d079a97c41dd98dd4b713547347913e95713 Mon Sep 17 00:00:00 2001 From: Jeroen Rinzema Date: Tue, 23 Jun 2026 17:33:14 +0200 Subject: [PATCH 3/4] fix(client/tests): repair v1/client test build and own-scope event tests on main Two PR merges collided in the v1/client test package, breaking `make lint` and `make test` on main (the build failure masked the second issue): - `capturingPublisher` was declared in both inbox_idor_test.go and ownscope_helpers_test.go. Drop the duplicate (simpler) copy from inbox_idor_test.go and adapt publishedIdentifiers to the canonical captured()/capturedMessage API in ownscope_helpers_test.go. - ownDataActor/allDataActor built actors with a random UUID and no auth-method row. After per-grant create-constraint enforcement landed (#261), CreateConstraints.Enforce looks the method up by the actor id and fails closed on a missing row (sql.ErrNoRows -> 500), breaking every PostUserEvents own/all-data test. Provision a real, unconstrained auth method and use its id as the actor identity, mirroring actorContext. go vet ./... and the full v1/client suite pass. --- .../controllers/v1/client/inbox_idor_test.go | 17 ++--------- .../v1/client/ownscope_helpers_test.go | 28 +++++++++++++++++-- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/internal/http/controllers/v1/client/inbox_idor_test.go b/internal/http/controllers/v1/client/inbox_idor_test.go index f254393c..c1315715 100644 --- a/internal/http/controllers/v1/client/inbox_idor_test.go +++ b/internal/http/controllers/v1/client/inbox_idor_test.go @@ -9,7 +9,6 @@ import ( "testing" "github.com/google/uuid" - "github.com/lunogram/platform/internal/pubsub" "github.com/lunogram/platform/internal/pubsub/schemas" "github.com/lunogram/platform/internal/rbac" "github.com/lunogram/platform/internal/store/subjects" @@ -18,17 +17,6 @@ import ( "go.uber.org/zap/zaptest" ) -// capturingPublisher records every published message so a controller test can -// assert on what was sent downstream without a real broker. -type capturingPublisher struct { - messages []any -} - -func (p *capturingPublisher) Publish(_ context.Context, _ schemas.Subject, v any, _ ...pubsub.PublishOption) error { - p.messages = append(p.messages, v) - return nil -} - // newInboxController wires an InboxController over an in-memory RBAC engine that // grants the actor the "client" project role (which carries inbox-create) and a // capturing publisher. It returns the controller, the publisher, and the @@ -67,8 +55,9 @@ func postInboxMessage(t *testing.T, srv *InboxController, ctx context.Context, s func publishedIdentifiers(t *testing.T, pub *capturingPublisher) []subjects.ExternalIDParam { t.Helper() - require.Len(t, pub.messages, 1, "exactly one inbox message should be published") - msg, ok := pub.messages[0].(schemas.InboxMessage) + captured := pub.captured() + require.Len(t, captured, 1, "exactly one inbox message should be published") + msg, ok := captured[0].Value.(schemas.InboxMessage) require.True(t, ok, "published value should be a schemas.InboxMessage") return msg.Identifiers } diff --git a/internal/http/controllers/v1/client/ownscope_helpers_test.go b/internal/http/controllers/v1/client/ownscope_helpers_test.go index 63de991b..13758c23 100644 --- a/internal/http/controllers/v1/client/ownscope_helpers_test.go +++ b/internal/http/controllers/v1/client/ownscope_helpers_test.go @@ -63,7 +63,20 @@ func (tc *testClientController) withCapturingPublisher() *capturingPublisher { func (tc *testClientController) ownDataActor(t *testing.T, orgID, projectID uuid.UUID, subject, source string) *rbac.Actor { t.Helper() - actor := rbac.NewActor(rbac.ActorEndUser, uuid.New().String(), + // Provision a real, unconstrained auth method and use its id as the actor + // identity, so per-grant create-constraint enforcement (which looks the method + // up by the actor id and fails closed on a missing row) resolves to a live + // method — mirroring how a credential-backed end user exists in prod. + method, err := tc.mgmt.CreateAuthMethod(t.Context(), projectID, management.CreateAuthMethodInput{ + Type: management.MethodTypeAPIKey, + Name: "own-data test method", + Role: rbac.ProjectClient, + }) + if err != nil { + t.Fatalf("create auth method: %v", err) + } + + actor := rbac.NewActor(rbac.ActorEndUser, method.ID.String(), rbac.WithOrganizationID(orgID), rbac.WithProjectID(projectID), rbac.WithSubject(subject, source), @@ -83,7 +96,18 @@ func (tc *testClientController) ownDataActor(t *testing.T, orgID, projectID uuid func (tc *testClientController) allDataActor(t *testing.T, orgID, projectID uuid.UUID) *rbac.Actor { t.Helper() - actor := rbac.NewActor(rbac.ActorEndUser, uuid.New().String(), + // See ownDataActor: the actor id must be a live auth method so per-grant + // create-constraint enforcement resolves instead of failing closed. + method, err := tc.mgmt.CreateAuthMethod(t.Context(), projectID, management.CreateAuthMethodInput{ + Type: management.MethodTypeAPIKey, + Name: "all-data test method", + Role: rbac.ProjectClient, + }) + if err != nil { + t.Fatalf("create auth method: %v", err) + } + + actor := rbac.NewActor(rbac.ActorEndUser, method.ID.String(), rbac.WithOrganizationID(orgID), rbac.WithProjectID(projectID), rbac.WithSubject("trusted-subject", "https://idp.example"), From cdcf9a961658569cf15388a8df127b4d917164fc Mon Sep 17 00:00:00 2001 From: Jeroen Rinzema Date: Tue, 23 Jun 2026 18:09:54 +0200 Subject: [PATCH 4/4] test: reconcile main's newer auth/client suites with the project-in-URL rework These suites landed on main after this branch's base and exercise the pre-rework contracts; rebasing onto the grant_instances model surfaced them: - store invariants: the trusted-issuer invariant flipped from "globally unique" to "unique per project, reusable across projects". Rewrite the subtest to assert per-project uniqueness plus cross-tenant resolution isolation (each project resolves the shared iss to its own method). - auth middleware: WithSession / WithTrustedIssuer now bind the credential to the URL project (enforceURLProject / project-scoped GetTrustedIssuer). Drive the existing positive tests through clientRequestCtx so they carry the URL project, and update the issuerDB fake to match the new (project_id, issuer) query. - client controllers: every chi-server handler now takes a ProjectID path param. Thread it through the own-scope/guard/session/inbox/event test call sites (uuid.Nil where the handler derives the project from the actor; the real project where CreateSession enforces URL == method project). go vet ./... clean; full suite green. --- internal/http/auth/session_middleware_test.go | 7 +-- .../auth/trusted_issuer_middleware_test.go | 34 +++++++------- .../v1/client/events_ownscope_test.go | 3 +- .../controllers/v1/client/inbox_idor_test.go | 2 +- .../v1/client/inbox_ownscope_test.go | 12 ++--- .../v1/client/ownscope_guards_test.go | 17 +++---- .../controllers/v1/client/sessions_test.go | 14 +++--- .../auth_methods_invariants_test.go | 47 +++++++++++++------ 8 files changed, 79 insertions(+), 57 deletions(-) diff --git a/internal/http/auth/session_middleware_test.go b/internal/http/auth/session_middleware_test.go index 50009594..7486d4a4 100644 --- a/internal/http/auth/session_middleware_test.go +++ b/internal/http/auth/session_middleware_test.go @@ -174,7 +174,8 @@ func TestWithSessionBuildsActor(t *testing.T) { token, _, err := signer.Mint(method.ID, "user_42", time.Hour) require.NoError(t, err) - ctx, err := WithSession(mgmt, signer)(context.Background(), token) + // The session is presented on its own project's URL (the post-#262 contract). + ctx, err := WithSession(mgmt, signer)(clientRequestCtx(projectID.String()), token) require.NoError(t, err) actor := rbac.FromContext(ctx) @@ -191,13 +192,13 @@ func TestWithSessionScopeAll(t *testing.T) { t.Parallel() mgmt := sessionMgmt(t) - method, orgID, _ := newSessionMethod(t, mgmt, management.SubjectScopeAll) + method, orgID, projectID := newSessionMethod(t, mgmt, management.SubjectScopeAll) signer := testSigner(t, "") token, _, err := signer.Mint(method.ID, "user_7", time.Hour) require.NoError(t, err) - ctx, err := WithSession(mgmt, signer)(context.Background(), token) + ctx, err := WithSession(mgmt, signer)(clientRequestCtx(projectID.String()), token) require.NoError(t, err) actor := rbac.FromContext(ctx) diff --git a/internal/http/auth/trusted_issuer_middleware_test.go b/internal/http/auth/trusted_issuer_middleware_test.go index 3f0f9389..7a65775c 100644 --- a/internal/http/auth/trusted_issuer_middleware_test.go +++ b/internal/http/auth/trusted_issuer_middleware_test.go @@ -25,9 +25,9 @@ import ( ) // issuerDB is a fake store.DB that resolves a single trusted_issuer row by its -// issuer. Only GetContext is exercised by GetTrustedIssuerByIssuer; every other -// method is left to the embedded nil interface (and would panic if called), -// which keeps the fake to the one query the middleware actually runs. +// issuer. Only GetContext is exercised by GetTrustedIssuer; every other method is +// left to the embedded nil interface (and would panic if called), which keeps the +// fake to the one query the middleware actually runs. type issuerDB struct { store.DB method *management.TrustedIssuerAuthMethod // resolved row, or nil to force a lookup miss @@ -41,10 +41,11 @@ func (d *issuerDB) GetContext(_ context.Context, dest any, _ string, args ...any if d.method == nil { return errors.New("sql: no rows in result set") } - // The loader passes the requested issuer as the only arg; mirror the SQL - // WHERE t.issuer = $1 so an unknown issuer misses like the real query. - if len(args) == 1 { - if issuer, ok := args[0].(string); ok && issuer != d.method.Issuer { + // GetTrustedIssuer queries by (project_id, issuer); the issuer is the string + // argument (project_id is a uuid.UUID). Mirror WHERE t.issuer = $2 so an + // unknown issuer misses like the real query. + for _, a := range args { + if issuer, ok := a.(string); ok && issuer != d.method.Issuer { return errors.New("sql: no rows in result set") } } @@ -76,17 +77,16 @@ func issuerMethod(t *testing.T) (*rsa.PrivateKey, *management.TrustedIssuerAuthM func TestWithTrustedIssuer(t *testing.T) { t.Parallel() cache := jwks.New(jwks.Config{}, nil, nil, nil) // PEM path: never touches the network - ctx := context.Background() t.Run("rejects an empty token", func(t *testing.T) { _, method := issuerMethod(t) - _, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, "") + _, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), "") assert.ErrorIs(t, err, ErrUnauthorized) }) t.Run("rejects an unparseable token (issuer extraction fails)", func(t *testing.T) { _, method := issuerMethod(t) - _, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, "not-a-jwt") + _, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), "not-a-jwt") assert.ErrorIs(t, err, ErrUnauthorized) }) @@ -96,7 +96,7 @@ func TestWithTrustedIssuer(t *testing.T) { "sub": "user_123", "exp": time.Now().Add(time.Hour).Unix(), }) - _, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, token) + _, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), token) assert.ErrorIs(t, err, ErrUnauthorized) }) @@ -108,7 +108,7 @@ func TestWithTrustedIssuer(t *testing.T) { "exp": time.Now().Add(time.Hour).Unix(), }) // State resolves only method.Issuer; the token's foreign issuer misses. - _, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, token) + _, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), token) assert.ErrorIs(t, err, ErrUnauthorized) }) @@ -121,7 +121,7 @@ func TestWithTrustedIssuer(t *testing.T) { "sub": "user_123", "exp": time.Now().Add(time.Hour).Unix(), }) - _, err = WithTrustedIssuer(newIssuerState(method), cache)(ctx, token) + _, err = WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), token) assert.ErrorIs(t, err, ErrUnauthorized) }) @@ -132,7 +132,7 @@ func TestWithTrustedIssuer(t *testing.T) { // no "sub": subject resolves to "" "exp": time.Now().Add(time.Hour).Unix(), }) - _, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, token) + _, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), token) assert.ErrorIs(t, err, ErrUnauthorized) }) @@ -144,7 +144,7 @@ func TestWithTrustedIssuer(t *testing.T) { "exp": time.Now().Add(time.Hour).Unix(), }) - newCtx, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, token) + newCtx, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), token) require.NoError(t, err) actor := rbac.FromContext(newCtx) @@ -167,7 +167,7 @@ func TestWithTrustedIssuer(t *testing.T) { "exp": time.Now().Add(time.Hour).Unix(), }) - newCtx, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, token) + newCtx, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), token) require.NoError(t, err) actor := rbac.FromContext(newCtx) require.NotNil(t, actor) @@ -183,7 +183,7 @@ func TestWithTrustedIssuer(t *testing.T) { "exp": time.Now().Add(time.Hour).Unix(), }) - newCtx, err := WithTrustedIssuer(newIssuerState(method), cache)(ctx, token) + newCtx, err := WithTrustedIssuer(newIssuerState(method), cache)(clientRequestCtx(method.ProjectID.String()), token) require.NoError(t, err) actor := rbac.FromContext(newCtx) require.NotNil(t, actor) diff --git a/internal/http/controllers/v1/client/events_ownscope_test.go b/internal/http/controllers/v1/client/events_ownscope_test.go index a61fe47f..95ccc78d 100644 --- a/internal/http/controllers/v1/client/events_ownscope_test.go +++ b/internal/http/controllers/v1/client/events_ownscope_test.go @@ -7,6 +7,7 @@ import ( "net/http/httptest" "testing" + "github.com/google/uuid" "github.com/lunogram/platform/internal/pubsub/schemas" "github.com/lunogram/platform/internal/rbac" "github.com/lunogram/platform/internal/store/subjects" @@ -29,7 +30,7 @@ func postEvents(t *testing.T, c *testClientController, actor *rbac.Actor, events req.Header.Set("Content-Type", "application/json") req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - c.PostUserEvents(w, req) + c.PostUserEvents(w, req, uuid.Nil) return w } diff --git a/internal/http/controllers/v1/client/inbox_idor_test.go b/internal/http/controllers/v1/client/inbox_idor_test.go index c1315715..03fb16e6 100644 --- a/internal/http/controllers/v1/client/inbox_idor_test.go +++ b/internal/http/controllers/v1/client/inbox_idor_test.go @@ -49,7 +49,7 @@ func postInboxMessage(t *testing.T, srv *InboxController, ctx context.Context, s req := httptest.NewRequest(http.MethodPost, "/api/client/users/inbox", bytes.NewReader(data)).WithContext(ctx) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - srv.PostUserInboxMessages(w, req) + srv.PostUserInboxMessages(w, req, uuid.Nil) return w } diff --git a/internal/http/controllers/v1/client/inbox_ownscope_test.go b/internal/http/controllers/v1/client/inbox_ownscope_test.go index 38c67c8d..6004f367 100644 --- a/internal/http/controllers/v1/client/inbox_ownscope_test.go +++ b/internal/http/controllers/v1/client/inbox_ownscope_test.go @@ -52,7 +52,7 @@ func TestPostUserInboxRead_OwnData_BindsToVerifiedSubject(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - c.PostUserInboxRead(w, req) + c.PostUserInboxRead(w, req, uuid.Nil) require.Equal(t, http.StatusAccepted, w.Code) @@ -86,7 +86,7 @@ func TestPostUserInboxRead_AllData_Passthrough(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - c.PostUserInboxRead(w, req) + c.PostUserInboxRead(w, req, uuid.Nil) require.Equal(t, http.StatusAccepted, w.Code) @@ -129,7 +129,7 @@ func TestOrgInbox_OwnData_Forbidden(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/api/client/organizations/inbox", nil) req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - ic.GetOrganizationInbox(w, req, oapi.GetOrganizationInboxParams{}) + ic.GetOrganizationInbox(w, req, uuid.Nil, oapi.GetOrganizationInboxParams{}) return w })) @@ -137,7 +137,7 @@ func TestOrgInbox_OwnData_Forbidden(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/api/client/organizations/inbox/count", nil) req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - ic.GetOrganizationInboxCount(w, req, oapi.GetOrganizationInboxCountParams{}) + ic.GetOrganizationInboxCount(w, req, uuid.Nil, oapi.GetOrganizationInboxCountParams{}) return w })) @@ -146,7 +146,7 @@ func TestOrgInbox_OwnData_Forbidden(t *testing.T) { req.Header.Set("Content-Type", "application/json") req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - ic.PostOrganizationInboxRead(w, req) + ic.PostOrganizationInboxRead(w, req, uuid.Nil) return w })) @@ -155,7 +155,7 @@ func TestOrgInbox_OwnData_Forbidden(t *testing.T) { req.Header.Set("Content-Type", "application/json") req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - ic.PostOrganizationInboxArchived(w, req) + ic.PostOrganizationInboxArchived(w, req, uuid.Nil) return w })) } diff --git a/internal/http/controllers/v1/client/ownscope_guards_test.go b/internal/http/controllers/v1/client/ownscope_guards_test.go index 1ca38187..b58efa6a 100644 --- a/internal/http/controllers/v1/client/ownscope_guards_test.go +++ b/internal/http/controllers/v1/client/ownscope_guards_test.go @@ -7,6 +7,7 @@ import ( "net/http/httptest" "testing" + "github.com/google/uuid" "github.com/lunogram/platform/internal/rbac" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -38,37 +39,37 @@ func TestOrgEndpoints_OwnData_Forbidden(t *testing.T) { "UpsertOrganizationClient": { req: func() *http.Request { return withBody(http.MethodPost, "/api/client/organizations") }, call: func(c *testClientController, r *http.Request, w http.ResponseWriter) { - c.UpsertOrganizationClient(w, r) + c.UpsertOrganizationClient(w, r, uuid.Nil) }, }, "DeleteOrganizationClient": { req: func() *http.Request { return withBody(http.MethodDelete, "/api/client/organizations") }, call: func(c *testClientController, r *http.Request, w http.ResponseWriter) { - c.DeleteOrganizationClient(w, r) + c.DeleteOrganizationClient(w, r, uuid.Nil) }, }, "AddOrganizationUserClient": { req: func() *http.Request { return withBody(http.MethodPost, "/api/client/organizations/users") }, call: func(c *testClientController, r *http.Request, w http.ResponseWriter) { - c.AddOrganizationUserClient(w, r) + c.AddOrganizationUserClient(w, r, uuid.Nil) }, }, "RemoveOrganizationUserClient": { req: func() *http.Request { return withBody(http.MethodDelete, "/api/client/organizations/users") }, call: func(c *testClientController, r *http.Request, w http.ResponseWriter) { - c.RemoveOrganizationUserClient(w, r) + c.RemoveOrganizationUserClient(w, r, uuid.Nil) }, }, "UpsertOrganizationScheduledClient": { req: func() *http.Request { return withBody(http.MethodPost, "/api/client/organizations/scheduled") }, call: func(c *testClientController, r *http.Request, w http.ResponseWriter) { - c.UpsertOrganizationScheduledClient(w, r) + c.UpsertOrganizationScheduledClient(w, r, uuid.Nil) }, }, "DeleteOrganizationScheduledClient": { req: func() *http.Request { return withBody(http.MethodDelete, "/api/client/organizations/scheduled") }, call: func(c *testClientController, r *http.Request, w http.ResponseWriter) { - c.DeleteOrganizationScheduledClient(w, r) + c.DeleteOrganizationScheduledClient(w, r, uuid.Nil) }, }, } @@ -112,7 +113,7 @@ func TestUpsertUserClient_OwnData_BindsToVerifiedSubject(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - c.UpsertUserClient(w, req) + c.UpsertUserClient(w, req, uuid.Nil) require.Equal(t, http.StatusOK, w.Code) @@ -150,7 +151,7 @@ func TestUpsertUserClient_AllData_Passthrough(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - c.UpsertUserClient(w, req) + c.UpsertUserClient(w, req, uuid.Nil) require.Equal(t, http.StatusOK, w.Code) diff --git a/internal/http/controllers/v1/client/sessions_test.go b/internal/http/controllers/v1/client/sessions_test.go index eb182f42..06050980 100644 --- a/internal/http/controllers/v1/client/sessions_test.go +++ b/internal/http/controllers/v1/client/sessions_test.go @@ -87,7 +87,8 @@ func TestCreateSession(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.CreateSession(w, req, methodID) + // The URL names the method's own project, so the mint is authorized. + controller.CreateSession(w, req, projectID, methodID) require.Equal(t, 201, w.Code) @@ -115,7 +116,7 @@ func TestCreateSessionNonAPIKeyActorForbidden(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.CreateSession(w, req, uuid.New()) + controller.CreateSession(w, req, uuid.New(), uuid.New()) assert.Equal(t, 403, w.Code) } @@ -133,7 +134,7 @@ func TestCreateSessionMissingActorForbidden(t *testing.T) { req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() - controller.CreateSession(w, req, uuid.New()) + controller.CreateSession(w, req, uuid.New(), uuid.New()) assert.Equal(t, 403, w.Code) } @@ -156,7 +157,7 @@ func TestCreateSessionMissingSigner(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.CreateSession(w, req, uuid.New()) + controller.CreateSession(w, req, uuid.New(), uuid.New()) assert.Equal(t, 500, w.Code) } @@ -200,7 +201,8 @@ func TestCreateSessionCrossProjectMethodRejected(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.CreateSession(w, req, methodID) + // The URL names projectB, but the method belongs to projectA. + controller.CreateSession(w, req, projectB, methodID) // A method in another project is reported as not found, never minted. assert.Equal(t, 404, w.Code) @@ -234,7 +236,7 @@ func TestCreateSessionUnknownMethodNotFound(t *testing.T) { req = req.WithContext(rbac.WithActor(req.Context(), actor)) w := httptest.NewRecorder() - controller.CreateSession(w, req, uuid.New()) + controller.CreateSession(w, req, uuid.New(), uuid.New()) assert.Equal(t, 404, w.Code) } diff --git a/internal/store/management/auth_methods_invariants_test.go b/internal/store/management/auth_methods_invariants_test.go index cbad6e82..6c841a3a 100644 --- a/internal/store/management/auth_methods_invariants_test.go +++ b/internal/store/management/auth_methods_invariants_test.go @@ -7,15 +7,14 @@ import ( "github.com/lunogram/platform/internal/http/problem" "github.com/lunogram/platform/internal/ptr" - "github.com/lunogram/platform/internal/store" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // TestAuthMethodsStoreInvariants covers the security- and correctness-relevant // invariants of the auth-method store that are not exercised by the happy-path -// suite: global trusted-issuer uniqueness, the session default TTL, and the -// nil-vs-empty grant update semantics. +// suite: per-project trusted-issuer uniqueness and cross-tenant isolation, the +// session default TTL, and the nil-vs-empty grant update semantics. func TestAuthMethodsStoreInvariants(t *testing.T) { t.Parallel() db := NewContainerStore(t) @@ -24,9 +23,9 @@ func TestAuthMethodsStoreInvariants(t *testing.T) { orgID, err := db.CreateOrganization(ctx, "Invariants Org") require.NoError(t, err) - // Two distinct projects to prove uniqueness is enforced globally, not - // per-project: a trusted issuer is resolved by `iss` alone with no project - // context, so a duplicate must never authenticate against another project. + // Two distinct projects to prove issuers are project-scoped: a trusted issuer + // is resolved by (project, `iss`), so the same `iss` may live in two projects + // and each must resolve only to its own method — never the other tenant's. projectA, err := db.CreateProject(ctx, Project{ OrganizationID: &orgID, Name: "Invariants Project A", @@ -42,7 +41,7 @@ func TestAuthMethodsStoreInvariants(t *testing.T) { }) require.NoError(t, err) - t.Run("trusted_issuer issuer is globally unique across projects", func(t *testing.T) { + t.Run("trusted_issuer issuer is unique per project but reusable across projects", func(t *testing.T) { const iss = "https://shared.example" first, err := db.CreateAuthMethod(ctx, projectA, CreateAuthMethodInput{ @@ -57,9 +56,10 @@ func TestAuthMethodsStoreInvariants(t *testing.T) { require.NoError(t, err) require.NotNil(t, first) - // A second ACTIVE method reusing the same iss must be rejected, even in - // a different project. - _, err = db.CreateAuthMethod(ctx, projectB, CreateAuthMethodInput{ + // A second ACTIVE method reusing the same iss in the SAME project is a + // conflict: resolution is (project, iss)-scoped, so a duplicate within a + // project would be ambiguous. + _, err = db.CreateAuthMethod(ctx, projectA, CreateAuthMethodInput{ Type: MethodTypeTrustedIssuer, Name: "duplicate idp", Role: "support", @@ -70,13 +70,30 @@ func TestAuthMethodsStoreInvariants(t *testing.T) { }) require.Error(t, err) assert.Equal(t, http.StatusConflict, problem.GetStatus(err), - "a duplicate active iss must be a conflict") + "a duplicate active iss in the same project must be a conflict") - // The conflict must not have persisted a row in project B. - methods, total, err := db.ListAuthMethods(ctx, projectB, store.Pagination{Limit: 10}) + // The same iss in a DIFFERENT project is allowed: issuers are project-scoped, + // so two tenants may each register the same upstream IdP. + second, err := db.CreateAuthMethod(ctx, projectB, CreateAuthMethodInput{ + Type: MethodTypeTrustedIssuer, + Name: "other-project idp", + Role: "support", + TrustedIssuer: &TrustedIssuer{ + JWKSURL: "https://shared.example/jwks.json", + Issuer: iss, + }, + }) + require.NoError(t, err, "the same iss must be registrable under a different project") + require.NotNil(t, second) + + // Each project resolves the shared iss to its own method — the cross-tenant + // isolation this whole change exists to guarantee. + resolvedA, err := db.GetTrustedIssuer(ctx, projectA, iss) + require.NoError(t, err) + assert.Equal(t, first.ID, resolvedA.ID) + resolvedB, err := db.GetTrustedIssuer(ctx, projectB, iss) require.NoError(t, err) - assert.Equal(t, 0, total) - assert.Empty(t, methods) + assert.Equal(t, second.ID, resolvedB.ID) }) t.Run("session TTL defaults to 900s when unset", func(t *testing.T) {