diff --git a/openapi.yaml b/openapi.yaml index 236a222..f1e3853 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -6,9 +6,123 @@ info: description: Checkin API paths: + /verify-email: + post: + summary: isct メールアドレスの確認メールを送信 + tags: + - Auth + operationId: postVerifyEmail + parameters: + - $ref: '#/components/parameters/VerifyEmailRedirect' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/VerifyEmailRequest' + responses: + '202': + description: Accepted + content: + application/json: + schema: + $ref: '#/components/schemas/VerifyEmailStartResponse' + '400': + $ref: '#/components/responses/BadRequest' + '500': + $ref: '#/components/responses/InternalServerError' + /verify-email/confirm: + get: + summary: メール確認トークンの確認ページを表示 + tags: + - Auth + operationId: getVerifyEmailConfirm + parameters: + - name: token + in: query + required: true + description: 確認メールに含まれるワンタイムトークン + schema: + type: string + minLength: 32 + responses: + '200': + description: OK + headers: + Cache-Control: + description: ブラウザや中継に保存させない + schema: + type: string + example: no-store + content: + text/html: + schema: + type: string + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalServerError' + post: + summary: メール確認トークンを消費してログインを完了 + tags: + - Auth + operationId: postVerifyEmailConfirm + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/VerifyEmailConfirmRequest' + responses: + '303': + description: See Other + headers: + Location: + description: 検証完了後に遷移する相対パス + schema: + $ref: '#/components/schemas/RelativeRedirectPath' + Cache-Control: + description: ブラウザや中継に保存させない + schema: + type: string + example: no-store + Set-Cookie: + description: > + `__Host-checkin_session` と `__Host-checkin_csrf` cookie を発行する。 + `__Host-checkin_csrf` の値は以後の state-changing request で + `X-CSRF-Token` header にそのままコピーして送る。 + schema: + type: string + example: __Host-checkin_session=session-token; Path=/; HttpOnly; Secure; SameSite=Lax + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalServerError' + /csrf: + get: + summary: CSRF トークン用 cookie を発行 + tags: + - Auth + operationId: getCsrf + responses: + '204': + description: No Content + headers: + Set-Cookie: + description: > + `__Host-checkin_csrf` cookie を発行する。state-changing request では、この cookie の値を + `X-CSRF-Token` header にそのままコピーして送る。 + schema: + type: string + example: __Host-checkin_csrf=csrf-token-value; Path=/; Secure; SameSite=Lax /customer: get: summary: Customer を取得 + description: session cookie または信頼済み proxy auth が必要 tags: - Customer operationId: getCustomer @@ -31,34 +145,58 @@ paths: application/json: schema: $ref: '#/components/schemas/Customer' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' post: summary: Customer を作成 + description: session cookie または信頼済み proxy auth が必要。`X-CSRF-Token` も必須 tags: - Customer operationId: postCustomer + parameters: + - $ref: '#/components/parameters/CsrfToken' requestBody: content: application/json: schema: $ref: '#/components/schemas/PostCustomerRequest' responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Customer' '201': description: Created content: application/json: schema: $ref: '#/components/schemas/Customer' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' '500': $ref: '#/components/responses/InternalServerError' patch: summary: Customer を更新 + description: session cookie または信頼済み proxy auth が必要。`X-CSRF-Token` も必須 tags: - Customer operationId: patchCustomer + parameters: + - $ref: '#/components/parameters/CsrfToken' requestBody: content: application/json: @@ -71,14 +209,23 @@ paths: application/json: schema: $ref: '#/components/schemas/Customer' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' '500': $ref: '#/components/responses/InternalServerError' /invoice: post: summary: Invoice を作成 + description: session cookie または信頼済み proxy auth が必要。`X-CSRF-Token` も必須 tags: - Invoice operationId: postInvoice + parameters: + - $ref: '#/components/parameters/CsrfToken' requestBody: content: application/json: @@ -90,7 +237,13 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Invoice' + $ref: '#/components/schemas/CreateInvoiceResponse' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' '500': $ref: '#/components/responses/InternalServerError' /webhook/invoice-paid: @@ -107,15 +260,16 @@ paths: schema: type: string requestBody: + required: true content: application/json: schema: - $ref: '#/components/schemas/Invoice' + $ref: '#/components/schemas/StripeEvent' responses: '204': description: No content - '403': - $ref: '#/components/responses/Forbidden' + '400': + $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalServerError' /list/invoices: @@ -217,49 +371,24 @@ paths: $ref: '#/components/responses/Forbidden' '500': $ref: '#/components/responses/InternalServerError' - post: - summary: 管理者を作成 - tags: - - Admin - operationId: postAdmin - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Admin' - responses: - '201': - description: Created - content: - application/json: - schema: - $ref: '#/components/schemas/Admin' - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - delete: - summary: 管理者を削除 - tags: - - Admin - operationId: deleteAdmin - parameters: - - name: id - in: query - description: 管理者の traQ ID - required: true - schema: - type: string - responses: - '204': - description: No content - '403': - $ref: '#/components/responses/Forbidden' - '500': - $ref: '#/components/responses/InternalServerError' - components: parameters: + CsrfToken: + name: X-CSRF-Token + in: header + description: > + Double-submit CSRF token。`/csrf` または `POST /verify-email/confirm` が発行した + `__Host-checkin_csrf` cookie の値をそのまま送る。 + required: true + schema: + type: string + minLength: 16 + VerifyEmailRedirect: + name: redirect + in: query + description: 検証後に遷移する相対パス + schema: + $ref: '#/components/schemas/RelativeRedirectPath' CustomerId: name: customer_id in: query @@ -296,6 +425,10 @@ components: schema: type: string responses: + BadRequest: + description: Bad request + Unauthorized: + description: Unauthorized Forbidden: description: Forbidden NotFound: @@ -303,6 +436,48 @@ components: InternalServerError: description: Internal server error schemas: + RelativeRedirectPath: + description: "`//` で始まらないアプリ内の相対パス" + type: string + pattern: ^/(|[^/].*)$ + example: /membership + VerifyEmailRequest: + description: Verify email request + type: object + additionalProperties: false + properties: + email: + type: string + description: isct email + format: email + maxLength: 255 + pattern: ^[^@\s]+@[iI][sS][cC][tT]\.[aA][cC]\.[jJ][pP]$ + required: + - email + VerifyEmailConfirmRequest: + description: Verify email confirm request + type: object + additionalProperties: false + properties: + token: + type: string + minLength: 32 + required: + - token + VerifyEmailStartResponse: + description: Verify email start response + type: object + additionalProperties: false + properties: + email: + type: string + description: normalized email + redirect: + description: validated redirect path + $ref: '#/components/schemas/RelativeRedirectPath' + required: + - email + - redirect Admin: description: 管理者の情報 type: object @@ -362,6 +537,21 @@ components: required: - customer_id - product_id + CreateInvoiceResponse: + description: Invoice creation result + type: object + properties: + invoice_id: + type: string + description: Invoice ID + example: in_1MtHbELkdIwHu7ixl4OzzPMv + payment_url: + type: string + description: Hosted invoice payment URL + example: https://invoice.stripe.com/... + required: + - invoice_id + - payment_url Invoice: description: Invoice の情報 type: object @@ -380,18 +570,22 @@ components: example: in_1MtHbELkdIwHu7ixl4OzzPMv amount_due: type: integer + format: int64 description: 最終的に支払う金額 example: 0 amount_paid: type: integer + format: int64 description: 支払い済み金額 example: 0 amount_remaining: type: integer + format: int64 description: 支払い残高 example: 0 created: type: integer + format: int64 description: 作成日時 (Unix 時間) example: 1680644467 customer: @@ -433,14 +627,17 @@ components: example: cs_test_1234567890 amount_total: type: integer + format: int64 description: 支払い金額 example: 2198 amount_subtotal: type: integer + format: int64 description: 割引・税金を含まない支払い金額 example: 1998 created: type: integer + format: int64 description: 作成日時 (Unix 時間) example: 1679600215 customer: @@ -462,8 +659,14 @@ components: type: string description: Product ID example: prod_NWjs8kKbJWmuuc + StripeEvent: + description: Generic Stripe event payload + type: object + additionalProperties: true tags: + - name: Auth + description: Auth API - name: Customer description: Customer API - name: Invoice diff --git a/server/gen.go b/server/gen.go index 623da29..fd617a8 100644 --- a/server/gen.go +++ b/server/gen.go @@ -1,6 +1,6 @@ // Package api provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT. package api import ( @@ -16,6 +16,7 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/labstack/echo/v4" "github.com/oapi-codegen/runtime" + openapi_types "github.com/oapi-codegen/runtime/types" ) // Defines values for GetCheckoutSessionsResponseDataStatus. @@ -62,6 +63,15 @@ type Admin struct { Id string `json:"id"` } +// CreateInvoiceResponse Invoice creation result +type CreateInvoiceResponse struct { + // InvoiceId Invoice ID + InvoiceId string `json:"invoice_id"` + + // PaymentUrl Hosted invoice payment URL + PaymentUrl string `json:"payment_url"` +} + // Customer Customer の情報 type Customer struct { // Email Email @@ -81,13 +91,13 @@ type Customer struct { type GetCheckoutSessionsResponse struct { Data *[]struct { // AmountSubtotal 割引・税金を含まない支払い金額 - AmountSubtotal *int `json:"amount_subtotal,omitempty"` + AmountSubtotal *int64 `json:"amount_subtotal,omitempty"` // AmountTotal 支払い金額 - AmountTotal *int `json:"amount_total,omitempty"` + AmountTotal *int64 `json:"amount_total,omitempty"` // Created 作成日時 (Unix 時間) - Created *int `json:"created,omitempty"` + Created *int64 `json:"created,omitempty"` // Customer Customer の情報 Customer *Customer `json:"customer,omitempty"` @@ -116,16 +126,16 @@ type GetCheckoutSessionsResponseDataStatus string type Invoice struct { Data *[]struct { // AmountDue 最終的に支払う金額 - AmountDue *int `json:"amount_due,omitempty"` + AmountDue *int64 `json:"amount_due,omitempty"` // AmountPaid 支払い済み金額 - AmountPaid *int `json:"amount_paid,omitempty"` + AmountPaid *int64 `json:"amount_paid,omitempty"` // AmountRemaining 支払い残高 - AmountRemaining *int `json:"amount_remaining,omitempty"` + AmountRemaining *int64 `json:"amount_remaining,omitempty"` // Created 作成日時 (Unix 時間) - Created *int `json:"created,omitempty"` + Created *int64 `json:"created,omitempty"` // Customer Customer の情報 Customer *Customer `json:"customer,omitempty"` @@ -171,6 +181,35 @@ type PostInvoiceRequest struct { ProductId string `json:"product_id"` } +// RelativeRedirectPath `//` で始まらないアプリ内の相対パス +type RelativeRedirectPath = string + +// StripeEvent Generic Stripe event payload +type StripeEvent map[string]interface{} + +// VerifyEmailConfirmRequest Verify email confirm request +type VerifyEmailConfirmRequest struct { + Token string `json:"token"` +} + +// VerifyEmailRequest Verify email request +type VerifyEmailRequest struct { + // Email isct email + Email openapi_types.Email `json:"email"` +} + +// VerifyEmailStartResponse Verify email start response +type VerifyEmailStartResponse struct { + // Email normalized email + Email string `json:"email"` + + // Redirect `//` で始まらないアプリ内の相対パス + Redirect RelativeRedirectPath `json:"redirect"` +} + +// CsrfToken defines model for CsrfToken. +type CsrfToken = string + // CustomerId defines model for CustomerId. type CustomerId = string @@ -186,11 +225,8 @@ type StartingAfter = string // SubscriptionId defines model for SubscriptionId. type SubscriptionId = string -// DeleteAdminParams defines parameters for DeleteAdmin. -type DeleteAdminParams struct { - // Id 管理者の traQ ID - Id string `form:"id" json:"id"` -} +// VerifyEmailRedirect `//` で始まらないアプリ内の相対パス +type VerifyEmailRedirect = RelativeRedirectPath // GetCustomerParams defines parameters for GetCustomer. type GetCustomerParams struct { @@ -204,6 +240,24 @@ type GetCustomerParams struct { Email *string `form:"email,omitempty" json:"email,omitempty"` } +// PatchCustomerParams defines parameters for PatchCustomer. +type PatchCustomerParams struct { + // XCSRFToken Double-submit CSRF token。`/csrf` または `POST /verify-email/confirm` が発行した `__Host-checkin_csrf` cookie の値をそのまま送る。 + XCSRFToken CsrfToken `json:"X-CSRF-Token"` +} + +// PostCustomerParams defines parameters for PostCustomer. +type PostCustomerParams struct { + // XCSRFToken Double-submit CSRF token。`/csrf` または `POST /verify-email/confirm` が発行した `__Host-checkin_csrf` cookie の値をそのまま送る。 + XCSRFToken CsrfToken `json:"X-CSRF-Token"` +} + +// PostInvoiceParams defines parameters for PostInvoice. +type PostInvoiceParams struct { + // XCSRFToken Double-submit CSRF token。`/csrf` または `POST /verify-email/confirm` が発行した `__Host-checkin_csrf` cookie の値をそのまま送る。 + XCSRFToken CsrfToken `json:"X-CSRF-Token"` +} + // GetCheckoutSessionsParams defines parameters for GetCheckoutSessions. type GetCheckoutSessionsParams struct { // CustomerId Customer ID @@ -261,15 +315,24 @@ type GetInvoicesParamsStatus string // GetInvoicesParamsCollectionMethod defines parameters for GetInvoices. type GetInvoicesParamsCollectionMethod string +// PostVerifyEmailParams defines parameters for PostVerifyEmail. +type PostVerifyEmailParams struct { + // Redirect 検証後に遷移する相対パス + Redirect *VerifyEmailRedirect `form:"redirect,omitempty" json:"redirect,omitempty"` +} + +// GetVerifyEmailConfirmParams defines parameters for GetVerifyEmailConfirm. +type GetVerifyEmailConfirmParams struct { + // Token 確認メールに含まれるワンタイムトークン + Token string `form:"token" json:"token"` +} + // PostWebhookInvoicePaidParams defines parameters for PostWebhookInvoicePaid. type PostWebhookInvoicePaidParams struct { // StripeSignature Stripe が送信する認証情報 StripeSignature string `json:"Stripe-Signature"` } -// PostAdminJSONRequestBody defines body for PostAdmin for application/json ContentType. -type PostAdminJSONRequestBody = Admin - // PatchCustomerJSONRequestBody defines body for PatchCustomer for application/json ContentType. type PatchCustomerJSONRequestBody = PostCustomerRequest @@ -279,38 +342,50 @@ type PostCustomerJSONRequestBody = PostCustomerRequest // PostInvoiceJSONRequestBody defines body for PostInvoice for application/json ContentType. type PostInvoiceJSONRequestBody = PostInvoiceRequest +// PostVerifyEmailJSONRequestBody defines body for PostVerifyEmail for application/json ContentType. +type PostVerifyEmailJSONRequestBody = VerifyEmailRequest + +// PostVerifyEmailConfirmFormdataRequestBody defines body for PostVerifyEmailConfirm for application/x-www-form-urlencoded ContentType. +type PostVerifyEmailConfirmFormdataRequestBody = VerifyEmailConfirmRequest + // PostWebhookInvoicePaidJSONRequestBody defines body for PostWebhookInvoicePaid for application/json ContentType. -type PostWebhookInvoicePaidJSONRequestBody = Invoice +type PostWebhookInvoicePaidJSONRequestBody = StripeEvent // ServerInterface represents all server handlers. type ServerInterface interface { - // 管理者を削除 - // (DELETE /admin) - DeleteAdmin(ctx echo.Context, params DeleteAdminParams) error // 管理者の一覧を取得 // (GET /admin) GetAdmins(ctx echo.Context) error - // 管理者を作成 - // (POST /admin) - PostAdmin(ctx echo.Context) error + // CSRF トークン用 cookie を発行 + // (GET /csrf) + GetCsrf(ctx echo.Context) error // Customer を取得 // (GET /customer) GetCustomer(ctx echo.Context, params GetCustomerParams) error // Customer を更新 // (PATCH /customer) - PatchCustomer(ctx echo.Context) error + PatchCustomer(ctx echo.Context, params PatchCustomerParams) error // Customer を作成 // (POST /customer) - PostCustomer(ctx echo.Context) error + PostCustomer(ctx echo.Context, params PostCustomerParams) error // Invoice を作成 // (POST /invoice) - PostInvoice(ctx echo.Context) error + PostInvoice(ctx echo.Context, params PostInvoiceParams) error // オンライン決済ページ由来の入金一覧を取得 // (GET /list/checkout-sessions) GetCheckoutSessions(ctx echo.Context, params GetCheckoutSessionsParams) error // 請求書由来の入金一覧を取得 // (GET /list/invoices) GetInvoices(ctx echo.Context, params GetInvoicesParams) error + // isct メールアドレスの確認メールを送信 + // (POST /verify-email) + PostVerifyEmail(ctx echo.Context, params PostVerifyEmailParams) error + // メール確認トークンの確認ページを表示 + // (GET /verify-email/confirm) + GetVerifyEmailConfirm(ctx echo.Context, params GetVerifyEmailConfirmParams) error + // メール確認トークンを消費してログインを完了 + // (POST /verify-email/confirm) + PostVerifyEmailConfirm(ctx echo.Context) error // Webhook の invoice.paid イベントを受け取る // (POST /webhook/invoice-paid) PostWebhookInvoicePaid(ctx echo.Context, params PostWebhookInvoicePaidParams) error @@ -321,24 +396,6 @@ type ServerInterfaceWrapper struct { Handler ServerInterface } -// DeleteAdmin converts echo context to params. -func (w *ServerInterfaceWrapper) DeleteAdmin(ctx echo.Context) error { - var err error - - // Parameter object where we will unmarshal all parameters from the context - var params DeleteAdminParams - // ------------- Required query parameter "id" ------------- - - err = runtime.BindQueryParameter("form", true, true, "id", ctx.QueryParams(), ¶ms.Id) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) - } - - // Invoke the callback with all the unmarshaled arguments - err = w.Handler.DeleteAdmin(ctx, params) - return err -} - // GetAdmins converts echo context to params. func (w *ServerInterfaceWrapper) GetAdmins(ctx echo.Context) error { var err error @@ -348,12 +405,12 @@ func (w *ServerInterfaceWrapper) GetAdmins(ctx echo.Context) error { return err } -// PostAdmin converts echo context to params. -func (w *ServerInterfaceWrapper) PostAdmin(ctx echo.Context) error { +// GetCsrf converts echo context to params. +func (w *ServerInterfaceWrapper) GetCsrf(ctx echo.Context) error { var err error // Invoke the callback with all the unmarshaled arguments - err = w.Handler.PostAdmin(ctx) + err = w.Handler.GetCsrf(ctx) return err } @@ -393,8 +450,30 @@ func (w *ServerInterfaceWrapper) GetCustomer(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PatchCustomer(ctx echo.Context) error { var err error + // Parameter object where we will unmarshal all parameters from the context + var params PatchCustomerParams + + headers := ctx.Request().Header + // ------------- Required header parameter "X-CSRF-Token" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-CSRF-Token")]; found { + var XCSRFToken CsrfToken + n := len(valueList) + if n != 1 { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-CSRF-Token, got %d", n)) + } + + err = runtime.BindStyledParameterWithOptions("simple", "X-CSRF-Token", valueList[0], &XCSRFToken, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: true}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-CSRF-Token: %s", err)) + } + + params.XCSRFToken = XCSRFToken + } else { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter X-CSRF-Token is required, but not found")) + } + // Invoke the callback with all the unmarshaled arguments - err = w.Handler.PatchCustomer(ctx) + err = w.Handler.PatchCustomer(ctx, params) return err } @@ -402,8 +481,30 @@ func (w *ServerInterfaceWrapper) PatchCustomer(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostCustomer(ctx echo.Context) error { var err error + // Parameter object where we will unmarshal all parameters from the context + var params PostCustomerParams + + headers := ctx.Request().Header + // ------------- Required header parameter "X-CSRF-Token" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-CSRF-Token")]; found { + var XCSRFToken CsrfToken + n := len(valueList) + if n != 1 { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-CSRF-Token, got %d", n)) + } + + err = runtime.BindStyledParameterWithOptions("simple", "X-CSRF-Token", valueList[0], &XCSRFToken, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: true}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-CSRF-Token: %s", err)) + } + + params.XCSRFToken = XCSRFToken + } else { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter X-CSRF-Token is required, but not found")) + } + // Invoke the callback with all the unmarshaled arguments - err = w.Handler.PostCustomer(ctx) + err = w.Handler.PostCustomer(ctx, params) return err } @@ -411,8 +512,30 @@ func (w *ServerInterfaceWrapper) PostCustomer(ctx echo.Context) error { func (w *ServerInterfaceWrapper) PostInvoice(ctx echo.Context) error { var err error + // Parameter object where we will unmarshal all parameters from the context + var params PostInvoiceParams + + headers := ctx.Request().Header + // ------------- Required header parameter "X-CSRF-Token" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-CSRF-Token")]; found { + var XCSRFToken CsrfToken + n := len(valueList) + if n != 1 { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-CSRF-Token, got %d", n)) + } + + err = runtime.BindStyledParameterWithOptions("simple", "X-CSRF-Token", valueList[0], &XCSRFToken, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: true}) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter X-CSRF-Token: %s", err)) + } + + params.XCSRFToken = XCSRFToken + } else { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Header parameter X-CSRF-Token is required, but not found")) + } + // Invoke the callback with all the unmarshaled arguments - err = w.Handler.PostInvoice(ctx) + err = w.Handler.PostInvoice(ctx, params) return err } @@ -536,6 +659,51 @@ func (w *ServerInterfaceWrapper) GetInvoices(ctx echo.Context) error { return err } +// PostVerifyEmail converts echo context to params. +func (w *ServerInterfaceWrapper) PostVerifyEmail(ctx echo.Context) error { + var err error + + // Parameter object where we will unmarshal all parameters from the context + var params PostVerifyEmailParams + // ------------- Optional query parameter "redirect" ------------- + + err = runtime.BindQueryParameter("form", true, false, "redirect", ctx.QueryParams(), ¶ms.Redirect) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter redirect: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostVerifyEmail(ctx, params) + return err +} + +// GetVerifyEmailConfirm converts echo context to params. +func (w *ServerInterfaceWrapper) GetVerifyEmailConfirm(ctx echo.Context) error { + var err error + + // Parameter object where we will unmarshal all parameters from the context + var params GetVerifyEmailConfirmParams + // ------------- Required query parameter "token" ------------- + + err = runtime.BindQueryParameter("form", true, true, "token", ctx.QueryParams(), ¶ms.Token) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter token: %s", err)) + } + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.GetVerifyEmailConfirm(ctx, params) + return err +} + +// PostVerifyEmailConfirm converts echo context to params. +func (w *ServerInterfaceWrapper) PostVerifyEmailConfirm(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.PostVerifyEmailConfirm(ctx) + return err +} + // PostWebhookInvoicePaid converts echo context to params. func (w *ServerInterfaceWrapper) PostWebhookInvoicePaid(ctx echo.Context) error { var err error @@ -595,15 +763,17 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL Handler: si, } - router.DELETE(baseURL+"/admin", wrapper.DeleteAdmin) router.GET(baseURL+"/admin", wrapper.GetAdmins) - router.POST(baseURL+"/admin", wrapper.PostAdmin) + router.GET(baseURL+"/csrf", wrapper.GetCsrf) router.GET(baseURL+"/customer", wrapper.GetCustomer) router.PATCH(baseURL+"/customer", wrapper.PatchCustomer) router.POST(baseURL+"/customer", wrapper.PostCustomer) router.POST(baseURL+"/invoice", wrapper.PostInvoice) router.GET(baseURL+"/list/checkout-sessions", wrapper.GetCheckoutSessions) router.GET(baseURL+"/list/invoices", wrapper.GetInvoices) + router.POST(baseURL+"/verify-email", wrapper.PostVerifyEmail) + router.GET(baseURL+"/verify-email/confirm", wrapper.GetVerifyEmailConfirm) + router.POST(baseURL+"/verify-email/confirm", wrapper.PostVerifyEmailConfirm) router.POST(baseURL+"/webhook/invoice-paid", wrapper.PostWebhookInvoicePaid) } @@ -611,40 +781,61 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "AP///p1g3+k7AAA=", } // GetSwagger returns the content of the embedded swagger specification file