diff --git a/client.gen.go b/client.gen.go index cf7bb1c..adddef3 100644 --- a/client.gen.go +++ b/client.gen.go @@ -164,6 +164,11 @@ type ClientInterface interface { ReportPlatformData(ctx context.Context, body ReportPlatformDataJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // ConsumePlatformTenantMagicLinkWithBody request with any body + ConsumePlatformTenantMagicLinkWithBody(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + ConsumePlatformTenantMagicLink(ctx context.Context, tenantID openapi_types.UUID, body ConsumePlatformTenantMagicLinkJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // ReportTenantPlatformDataWithBody request with any body ReportTenantPlatformDataWithBody(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -408,6 +413,9 @@ type ClientInterface interface { // FinalizeTeamPlatformTenant request FinalizeTeamPlatformTenant(ctx context.Context, teamName TeamName, tenantId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + // RequestPlatformTenantMagicLink request + RequestPlatformTenantMagicLink(ctx context.Context, teamName TeamName, tenantId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeletePluginsByTeam request DeletePluginsByTeam(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -852,6 +860,30 @@ func (c *Client) ReportPlatformData(ctx context.Context, body ReportPlatformData return c.Client.Do(req) } +func (c *Client) ConsumePlatformTenantMagicLinkWithBody(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewConsumePlatformTenantMagicLinkRequestWithBody(c.Server, tenantID, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) ConsumePlatformTenantMagicLink(ctx context.Context, tenantID openapi_types.UUID, body ConsumePlatformTenantMagicLinkJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewConsumePlatformTenantMagicLinkRequest(c.Server, tenantID, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) ReportTenantPlatformDataWithBody(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewReportTenantPlatformDataRequestWithBody(c.Server, tenantID, contentType, body) if err != nil { @@ -1932,6 +1964,18 @@ func (c *Client) FinalizeTeamPlatformTenant(ctx context.Context, teamName TeamNa return c.Client.Do(req) } +func (c *Client) RequestPlatformTenantMagicLink(ctx context.Context, teamName TeamName, tenantId openapi_types.UUID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRequestPlatformTenantMagicLinkRequest(c.Server, teamName, tenantId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) DeletePluginsByTeam(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDeletePluginsByTeamRequest(c.Server, teamName) if err != nil { @@ -3461,6 +3505,53 @@ func NewReportPlatformDataRequestWithBody(server string, contentType string, bod return req, nil } +// NewConsumePlatformTenantMagicLinkRequest calls the generic ConsumePlatformTenantMagicLink builder with application/json body +func NewConsumePlatformTenantMagicLinkRequest(server string, tenantID openapi_types.UUID, body ConsumePlatformTenantMagicLinkJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewConsumePlatformTenantMagicLinkRequestWithBody(server, tenantID, "application/json", bodyReader) +} + +// NewConsumePlatformTenantMagicLinkRequestWithBody generates requests for ConsumePlatformTenantMagicLink with any type of body +func NewConsumePlatformTenantMagicLinkRequestWithBody(server string, tenantID openapi_types.UUID, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "tenant_id", runtime.ParamLocationPath, tenantID) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/platform/%s/magic-link/consume", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewReportTenantPlatformDataRequest calls the generic ReportTenantPlatformData builder with application/json body func NewReportTenantPlatformDataRequest(server string, tenantID openapi_types.UUID, body ReportTenantPlatformDataJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -7241,6 +7332,47 @@ func NewFinalizeTeamPlatformTenantRequest(server string, teamName TeamName, tena return req, nil } +// NewRequestPlatformTenantMagicLinkRequest generates requests for RequestPlatformTenantMagicLink +func NewRequestPlatformTenantMagicLinkRequest(server string, teamName TeamName, tenantId openapi_types.UUID) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "team_name", runtime.ParamLocationPath, teamName) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "tenant_id", runtime.ParamLocationPath, tenantId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/teams/%s/platform/tenant/%s/magic-link", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewDeletePluginsByTeamRequest generates requests for DeletePluginsByTeam func NewDeletePluginsByTeamRequest(server string, teamName TeamName) (*http.Request, error) { var err error @@ -9077,6 +9209,11 @@ type ClientWithResponsesInterface interface { ReportPlatformDataWithResponse(ctx context.Context, body ReportPlatformDataJSONRequestBody, reqEditors ...RequestEditorFn) (*ReportPlatformDataResponse, error) + // ConsumePlatformTenantMagicLinkWithBodyWithResponse request with any body + ConsumePlatformTenantMagicLinkWithBodyWithResponse(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ConsumePlatformTenantMagicLinkResponse, error) + + ConsumePlatformTenantMagicLinkWithResponse(ctx context.Context, tenantID openapi_types.UUID, body ConsumePlatformTenantMagicLinkJSONRequestBody, reqEditors ...RequestEditorFn) (*ConsumePlatformTenantMagicLinkResponse, error) + // ReportTenantPlatformDataWithBodyWithResponse request with any body ReportTenantPlatformDataWithBodyWithResponse(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ReportTenantPlatformDataResponse, error) @@ -9321,6 +9458,9 @@ type ClientWithResponsesInterface interface { // FinalizeTeamPlatformTenantWithResponse request FinalizeTeamPlatformTenantWithResponse(ctx context.Context, teamName TeamName, tenantId openapi_types.UUID, reqEditors ...RequestEditorFn) (*FinalizeTeamPlatformTenantResponse, error) + // RequestPlatformTenantMagicLinkWithResponse request + RequestPlatformTenantMagicLinkWithResponse(ctx context.Context, teamName TeamName, tenantId openapi_types.UUID, reqEditors ...RequestEditorFn) (*RequestPlatformTenantMagicLinkResponse, error) + // DeletePluginsByTeamWithResponse request DeletePluginsByTeamWithResponse(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*DeletePluginsByTeamResponse, error) @@ -9912,6 +10052,33 @@ func (r ReportPlatformDataResponse) StatusCode() int { return 0 } +type ConsumePlatformTenantMagicLinkResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *RemoveTeamMembershipRequest + JSON400 *BadRequest + JSON403 *Forbidden + JSON404 *NotFound + JSON429 *TooManyRequests + JSON500 *InternalError +} + +// Status returns HTTPResponse.Status +func (r ConsumePlatformTenantMagicLinkResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r ConsumePlatformTenantMagicLinkResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type ReportTenantPlatformDataResponse struct { Body []byte HTTPResponse *http.Response @@ -11594,6 +11761,33 @@ func (r FinalizeTeamPlatformTenantResponse) StatusCode() int { return 0 } +type RequestPlatformTenantMagicLinkResponse struct { + Body []byte + HTTPResponse *http.Response + JSON201 *RequestPlatformTenantMagicLink201Response + JSON401 *RequiresAuthentication + JSON403 *Forbidden + JSON404 *NotFound + JSON429 *TooManyRequests + JSON500 *InternalError +} + +// Status returns HTTPResponse.Status +func (r RequestPlatformTenantMagicLinkResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RequestPlatformTenantMagicLinkResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type DeletePluginsByTeamResponse struct { Body []byte HTTPResponse *http.Response @@ -12734,6 +12928,23 @@ func (c *ClientWithResponses) ReportPlatformDataWithResponse(ctx context.Context return ParseReportPlatformDataResponse(rsp) } +// ConsumePlatformTenantMagicLinkWithBodyWithResponse request with arbitrary body returning *ConsumePlatformTenantMagicLinkResponse +func (c *ClientWithResponses) ConsumePlatformTenantMagicLinkWithBodyWithResponse(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ConsumePlatformTenantMagicLinkResponse, error) { + rsp, err := c.ConsumePlatformTenantMagicLinkWithBody(ctx, tenantID, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseConsumePlatformTenantMagicLinkResponse(rsp) +} + +func (c *ClientWithResponses) ConsumePlatformTenantMagicLinkWithResponse(ctx context.Context, tenantID openapi_types.UUID, body ConsumePlatformTenantMagicLinkJSONRequestBody, reqEditors ...RequestEditorFn) (*ConsumePlatformTenantMagicLinkResponse, error) { + rsp, err := c.ConsumePlatformTenantMagicLink(ctx, tenantID, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseConsumePlatformTenantMagicLinkResponse(rsp) +} + // ReportTenantPlatformDataWithBodyWithResponse request with arbitrary body returning *ReportTenantPlatformDataResponse func (c *ClientWithResponses) ReportTenantPlatformDataWithBodyWithResponse(ctx context.Context, tenantID openapi_types.UUID, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ReportTenantPlatformDataResponse, error) { rsp, err := c.ReportTenantPlatformDataWithBody(ctx, tenantID, contentType, body, reqEditors...) @@ -13518,6 +13729,15 @@ func (c *ClientWithResponses) FinalizeTeamPlatformTenantWithResponse(ctx context return ParseFinalizeTeamPlatformTenantResponse(rsp) } +// RequestPlatformTenantMagicLinkWithResponse request returning *RequestPlatformTenantMagicLinkResponse +func (c *ClientWithResponses) RequestPlatformTenantMagicLinkWithResponse(ctx context.Context, teamName TeamName, tenantId openapi_types.UUID, reqEditors ...RequestEditorFn) (*RequestPlatformTenantMagicLinkResponse, error) { + rsp, err := c.RequestPlatformTenantMagicLink(ctx, teamName, tenantId, reqEditors...) + if err != nil { + return nil, err + } + return ParseRequestPlatformTenantMagicLinkResponse(rsp) +} + // DeletePluginsByTeamWithResponse request returning *DeletePluginsByTeamResponse func (c *ClientWithResponses) DeletePluginsByTeamWithResponse(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*DeletePluginsByTeamResponse, error) { rsp, err := c.DeletePluginsByTeam(ctx, teamName, reqEditors...) @@ -14843,6 +15063,67 @@ func ParseReportPlatformDataResponse(rsp *http.Response) (*ReportPlatformDataRes return response, nil } +// ParseConsumePlatformTenantMagicLinkResponse parses an HTTP response from a ConsumePlatformTenantMagicLinkWithResponse call +func ParseConsumePlatformTenantMagicLinkResponse(rsp *http.Response) (*ConsumePlatformTenantMagicLinkResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &ConsumePlatformTenantMagicLinkResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest RemoveTeamMembershipRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BadRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest Forbidden + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest NotFound + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParseReportTenantPlatformDataResponse parses an HTTP response from a ReportTenantPlatformDataWithResponse call func ParseReportTenantPlatformDataResponse(rsp *http.Response) (*ReportTenantPlatformDataResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -18425,6 +18706,67 @@ func ParseFinalizeTeamPlatformTenantResponse(rsp *http.Response) (*FinalizeTeamP return response, nil } +// ParseRequestPlatformTenantMagicLinkResponse parses an HTTP response from a RequestPlatformTenantMagicLinkWithResponse call +func ParseRequestPlatformTenantMagicLinkResponse(rsp *http.Response) (*RequestPlatformTenantMagicLinkResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RequestPlatformTenantMagicLinkResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: + var dest RequestPlatformTenantMagicLink201Response + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON201 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest RequiresAuthentication + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest Forbidden + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest NotFound + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParseDeletePluginsByTeamResponse parses an HTTP response from a DeletePluginsByTeamWithResponse call func ParseDeletePluginsByTeamResponse(rsp *http.Response) (*DeletePluginsByTeamResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/models.gen.go b/models.gen.go index 5a8ad09..9e0740b 100644 --- a/models.gen.go +++ b/models.gen.go @@ -630,6 +630,12 @@ type CheckUserAuthStatus200Response struct { Authenticated bool `json:"authenticated"` } +// ConsumePlatformTenantMagicLinkRequest defines model for ConsumePlatformTenantMagicLink_request. +type ConsumePlatformTenantMagicLinkRequest struct { + Token interface{} `json:"token"` + AdditionalProperties map[string]interface{} `json:"-"` +} + // ContentType The HTTP Content-Type of the image or asset type ContentType string @@ -655,6 +661,9 @@ type CreateAddonVersionRequest struct { // CreatePlatformSignup201Response defines model for CreatePlatformSignup_201_response. type CreatePlatformSignup201Response struct { + // MagicLoginEnabled Whether magic-link sign-in is available for this tenant. + MagicLoginEnabled *bool `json:"magic_login_enabled,omitempty"` + // Status Provisioning status of a platform tenant. Status PlatformTenantStatus `json:"status"` Subdomain string `json:"subdomain"` @@ -1178,6 +1187,9 @@ type PlatformTenantStatus string // PlatformTenantSummary Summary view of a Platform tenant returned by the self-serve list / status endpoints. Same shape as `POST /platform-signup` and `GET /teams/{team_name}/platform/tenant/{tenant_id}` responses. type PlatformTenantSummary struct { + // MagicLoginEnabled Whether magic-link sign-in is available for this tenant. + MagicLoginEnabled *bool `json:"magic_login_enabled,omitempty"` + // Status Provisioning status of a platform tenant. Status PlatformTenantStatus `json:"status"` Subdomain string `json:"subdomain"` @@ -1844,6 +1856,15 @@ type ReportTenantPlatformDataRequest struct { AdditionalProperties map[string]interface{} `json:"-"` } +// RequestPlatformTenantMagicLink201Response defines model for RequestPlatformTenantMagicLink_201_response. +type RequestPlatformTenantMagicLink201Response struct { + // ExpiresInSeconds Seconds until the embedded token expires. + ExpiresInSeconds int `json:"expires_in_seconds"` + + // MagicUrl Absolute URL to navigate to. Contains the token as a query parameter. + MagicUrl string `json:"magic_url"` +} + // ResetUserPasswordRequest defines model for ResetUserPassword_request. type ResetUserPasswordRequest struct { // Email Email address to reset @@ -2637,6 +2658,9 @@ type RenewPlatformActivationJSONRequestBody = RenewPlatformActivationRequest // ReportPlatformDataJSONRequestBody defines body for ReportPlatformData for application/json ContentType. type ReportPlatformDataJSONRequestBody = ReportPlatformDataRequest +// ConsumePlatformTenantMagicLinkJSONRequestBody defines body for ConsumePlatformTenantMagicLink for application/json ContentType. +type ConsumePlatformTenantMagicLinkJSONRequestBody = ConsumePlatformTenantMagicLinkRequest + // ReportTenantPlatformDataJSONRequestBody defines body for ReportTenantPlatformData for application/json ContentType. type ReportTenantPlatformDataJSONRequestBody = ReportTenantPlatformDataRequest @@ -3447,6 +3471,72 @@ func (a ActivatePlatformRequest) MarshalJSON() ([]byte, error) { return json.Marshal(object) } +// Getter for additional properties for ConsumePlatformTenantMagicLinkRequest. Returns the specified +// element and whether it was found +func (a ConsumePlatformTenantMagicLinkRequest) Get(fieldName string) (value interface{}, found bool) { + if a.AdditionalProperties != nil { + value, found = a.AdditionalProperties[fieldName] + } + return +} + +// Setter for additional properties for ConsumePlatformTenantMagicLinkRequest +func (a *ConsumePlatformTenantMagicLinkRequest) Set(fieldName string, value interface{}) { + if a.AdditionalProperties == nil { + a.AdditionalProperties = make(map[string]interface{}) + } + a.AdditionalProperties[fieldName] = value +} + +// Override default JSON handling for ConsumePlatformTenantMagicLinkRequest to handle AdditionalProperties +func (a *ConsumePlatformTenantMagicLinkRequest) UnmarshalJSON(b []byte) error { + object := make(map[string]json.RawMessage) + err := json.Unmarshal(b, &object) + if err != nil { + return err + } + + if raw, found := object["token"]; found { + err = json.Unmarshal(raw, &a.Token) + if err != nil { + return fmt.Errorf("error reading 'token': %w", err) + } + delete(object, "token") + } + + if len(object) != 0 { + a.AdditionalProperties = make(map[string]interface{}) + for fieldName, fieldBuf := range object { + var fieldVal interface{} + err := json.Unmarshal(fieldBuf, &fieldVal) + if err != nil { + return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) + } + a.AdditionalProperties[fieldName] = fieldVal + } + } + return nil +} + +// Override default JSON handling for ConsumePlatformTenantMagicLinkRequest to handle AdditionalProperties +func (a ConsumePlatformTenantMagicLinkRequest) MarshalJSON() ([]byte, error) { + var err error + object := make(map[string]json.RawMessage) + + object["token"], err = json.Marshal(a.Token) + if err != nil { + return nil, fmt.Errorf("error marshaling 'token': %w", err) + } + + for fieldName, field := range a.AdditionalProperties { + object[fieldName], err = json.Marshal(field) + if err != nil { + return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) + } + } + return json.Marshal(object) +} + // Getter for additional properties for CreatePlatformSignupRequest. Returns the specified // element and whether it was found func (a CreatePlatformSignupRequest) Get(fieldName string) (value interface{}, found bool) { diff --git a/spec.json b/spec.json index 4086c51..ea98eec 100644 --- a/spec.json +++ b/spec.json @@ -4307,6 +4307,54 @@ "x-internal" : true } }, + "/teams/{team_name}/platform/tenant/{tenant_id}/magic-link" : { + "post" : { + "description" : "Mint a one-shot magic-link URL for the calling Cloud user to bounce into their Platform tenant subdomain already authenticated. The caller's Cloud account email is used as the Platform user identity (no email parameter accepted, to deter abuse). The Platform tenant page at the returned URL posts the embedded token to `POST /user/magic-login` which round-trips through `POST /platform/{tenant_id}/magic-link/consume` to validate.\nNo email is sent server-side — the caller (frontend) handles delivery or direct navigation.\nThe token is single-use and short-lived. Cloud does not check whether the email exists on the tenant; the consume side returns 404 if the Platform tenant has no matching user.\n", + "operationId" : "RequestPlatformTenantMagicLink", + "parameters" : [ { + "$ref" : "#/components/parameters/team_name" + }, { + "explode" : false, + "in" : "path", + "name" : "tenant_id", + "required" : true, + "schema" : { + "format" : "uuid", + "type" : "string" + }, + "style" : "simple" + } ], + "responses" : { + "201" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/RequestPlatformTenantMagicLink_201_response" + } + } + }, + "description" : "Magic link minted." + }, + "401" : { + "$ref" : "#/components/responses/RequiresAuthentication" + }, + "403" : { + "$ref" : "#/components/responses/Forbidden" + }, + "404" : { + "$ref" : "#/components/responses/NotFound" + }, + "429" : { + "$ref" : "#/components/responses/TooManyRequests" + }, + "500" : { + "$ref" : "#/components/responses/InternalError" + } + }, + "tags" : [ "platform", "teams" ], + "x-internal" : true + } + }, "/user/platform/tenants" : { "get" : { "description" : "List Platform tenants the authenticated user can access via Cloud team membership. Used by the signup wizard to decide whether to show the tenant-creation form (empty list) or route the user to an existing tenant. Returns tenants in any status (pending/created/active).\n", @@ -4917,6 +4965,63 @@ "x-internal" : true } }, + "/platform/{tenant_id}/magic-link/consume" : { + "post" : { + "description" : "Validate and consume a magic-link token previously minted via `POST /teams/{team_name}/platform/tenant/{tenant_id}/magic-link`. Called by the Platform tenant's `POST /user/magic-login` handler, which authenticates here using the per-tenant API key Cloud provisioned at signup.\nConsume is atomic: the first successful call deletes the token. The response carries the email Cloud bound to the token at mint time; Platform uses it to look up its local user and issue an ID token.\nReturns 404 (uniform, no state-leak) when the token is unknown, expired, already used, or bound to a different tenant than the caller.\n", + "operationId" : "ConsumePlatformTenantMagicLink", + "parameters" : [ { + "explode" : false, + "in" : "path", + "name" : "tenant_id", + "required" : true, + "schema" : { + "format" : "uuid", + "type" : "string" + }, + "style" : "simple", + "x-go-name" : "TenantID" + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ConsumePlatformTenantMagicLink_request" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/RemoveTeamMembership_request" + } + } + }, + "description" : "Token consumed." + }, + "400" : { + "$ref" : "#/components/responses/BadRequest" + }, + "403" : { + "$ref" : "#/components/responses/Forbidden" + }, + "404" : { + "$ref" : "#/components/responses/NotFound" + }, + "429" : { + "$ref" : "#/components/responses/TooManyRequests" + }, + "500" : { + "$ref" : "#/components/responses/InternalError" + } + }, + "tags" : [ "platform" ], + "x-internal" : true + } + }, "/teams/{team_name}/ai-onboarding/chat" : { "post" : { "description" : "Send a chat message to the AI onboarding assistant", @@ -7473,6 +7578,10 @@ }, "team_name" : { "$ref" : "#/components/schemas/TeamName" + }, + "magic_login_enabled" : { + "description" : "Whether magic-link sign-in is available for this tenant.", + "type" : "boolean" } }, "required" : [ "status", "subdomain", "team_name", "tenant_id" ] @@ -8518,10 +8627,28 @@ }, "team_name" : { "$ref" : "#/components/schemas/TeamName" + }, + "magic_login_enabled" : { + "description" : "Whether magic-link sign-in is available for this tenant.", + "type" : "boolean" } }, "required" : [ "status", "subdomain", "team_name", "tenant_id" ] }, + "RequestPlatformTenantMagicLink_201_response" : { + "properties" : { + "magic_url" : { + "description" : "Absolute URL to navigate to. Contains the token as a query parameter.", + "format" : "uri", + "type" : "string" + }, + "expires_in_seconds" : { + "description" : "Seconds until the embedded token expires.", + "type" : "integer" + } + }, + "required" : [ "expires_in_seconds", "magic_url" ] + }, "ListUserPlatformTenants_200_response" : { "properties" : { "items" : { @@ -8689,6 +8816,16 @@ }, "required" : [ "host" ] }, + "ConsumePlatformTenantMagicLink_request" : { + "additionalProperties" : { }, + "properties" : { + "token" : { + "maxLength" : 128, + "minLength" : 16 + } + }, + "required" : [ "token" ] + }, "AIOnboardingChat_request" : { "additionalProperties" : { }, "properties" : {