mirror of
https://github.com/mattermost/mattermost.git
synced 2026-02-03 20:40:00 -05:00
* Fix 500 errors on check-cws-connection in non-Cloud environments The check-cws-connection endpoint was returning 500 errors in self-hosted enterprise environments because: 1. The client only checked BuildEnterpriseReady before making the request, which is true for all enterprise builds 2. The server handler didn't check for a Cloud license before attempting to connect to CWS 3. The CWS URL is not configured in non-Cloud environments, causing the connection check to fail This fix: - Server: Add IsCloud() license check to match other cloud endpoints, returning 403 instead of 500 for non-Cloud licenses - Client: Add Cloud license check to skip the request entirely in non-Cloud environments * Add unit tests for check-cws-connection license check * Return JSON status from check-cws-connection endpoint Change the check-cws-connection endpoint to return 200 with a JSON body containing status (available/unavailable) instead of using HTTP error codes. This allows the endpoint to be used for air-gap detection on self-hosted instances, not just Cloud deployments. * i18n --------- Co-authored-by: Mattermost Build <build@mattermost.com>
636 lines
22 KiB
Go
636 lines
22 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
"github.com/mattermost/mattermost/server/v8/platform/shared/web"
|
|
)
|
|
|
|
func (api *API) InitCloud() {
|
|
// GET /api/v4/cloud/products
|
|
api.BaseRoutes.Cloud.Handle("/products", api.APISessionRequired(getCloudProducts)).Methods(http.MethodGet)
|
|
// GET /api/v4/cloud/limits
|
|
api.BaseRoutes.Cloud.Handle("/limits", api.APISessionRequired(getCloudLimits)).Methods(http.MethodGet)
|
|
|
|
// GET /api/v4/cloud/customer
|
|
// PUT /api/v4/cloud/customer
|
|
// PUT /api/v4/cloud/customer/address
|
|
api.BaseRoutes.Cloud.Handle("/customer", api.APISessionRequired(getCloudCustomer)).Methods(http.MethodGet)
|
|
api.BaseRoutes.Cloud.Handle("/customer", api.APISessionRequired(updateCloudCustomer)).Methods(http.MethodPut)
|
|
api.BaseRoutes.Cloud.Handle("/customer/address", api.APISessionRequired(updateCloudCustomerAddress)).Methods(http.MethodPut)
|
|
|
|
// GET /api/v4/cloud/subscription
|
|
api.BaseRoutes.Cloud.Handle("/subscription", api.APISessionRequired(getSubscription)).Methods(http.MethodGet)
|
|
api.BaseRoutes.Cloud.Handle("/subscription/invoices", api.APISessionRequired(getInvoicesForSubscription)).Methods(http.MethodGet)
|
|
api.BaseRoutes.Cloud.Handle("/subscription/invoices/{invoice_id:[_A-Za-z0-9]+}/pdf", api.APISessionRequired(getSubscriptionInvoicePDF)).Methods(http.MethodGet)
|
|
|
|
// GET /api/v4/cloud/validate-business-email
|
|
api.BaseRoutes.Cloud.Handle("/validate-business-email", api.APISessionRequired(validateBusinessEmail)).Methods(http.MethodPost)
|
|
api.BaseRoutes.Cloud.Handle("/validate-workspace-business-email", api.APISessionRequired(validateWorkspaceBusinessEmail)).Methods(http.MethodPost)
|
|
|
|
// POST /api/v4/cloud/webhook
|
|
api.BaseRoutes.Cloud.Handle("/webhook", api.CloudAPIKeyRequired(handleCWSWebhook)).Methods(http.MethodPost)
|
|
|
|
// GET /api/v4/cloud/installation
|
|
api.BaseRoutes.Cloud.Handle("/installation", api.APISessionRequired(getInstallation)).Methods(http.MethodGet)
|
|
|
|
// GET /api/v4/cloud/check-cws-connection
|
|
api.BaseRoutes.Cloud.Handle("/check-cws-connection", api.APIHandler(handleCheckCWSConnection)).Methods(http.MethodGet)
|
|
|
|
// GET /api/v4/cloud/preview/modal_data
|
|
api.BaseRoutes.Cloud.Handle("/preview/modal_data", api.APISessionRequired(getPreviewModalData)).Methods(http.MethodGet)
|
|
}
|
|
|
|
func ensureCloudInterface(c *Context, where string) bool {
|
|
cloud := c.App.Cloud()
|
|
disabled := c.App.Config().CloudSettings.Disable != nil && *c.App.Config().CloudSettings.Disable
|
|
if cloud == nil {
|
|
c.Err = model.NewAppError(where, "api.server.cws.needs_enterprise_edition", nil, "", http.StatusBadRequest)
|
|
return false
|
|
}
|
|
if disabled {
|
|
c.Err = model.NewAppError(where, "api.server.cws.disabled", nil, "", http.StatusUnprocessableEntity)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func getPreviewSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
license := c.App.Channels().License()
|
|
subscription := &model.Subscription{
|
|
ID: "cloud-preview",
|
|
ProductID: license.SkuName,
|
|
StartAt: license.StartsAt,
|
|
TrialEndAt: license.ExpiresAt,
|
|
EndAt: license.ExpiresAt,
|
|
IsFreeTrial: "true",
|
|
IsCloudPreview: true,
|
|
}
|
|
|
|
json, err := json.Marshal(subscription)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(json); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
// Preview subscription is a special case for cloud preview licenses.
|
|
if c.App.Channels().License().IsCloudPreview() {
|
|
getPreviewSubscription(c, w, r)
|
|
return
|
|
}
|
|
|
|
ensured := ensureCloudInterface(c, "Api4.getSubscription")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
subscription, err := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
// if it is an end user, return basic subscription data without sensitive information
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadBilling) {
|
|
subscription = &model.Subscription{
|
|
ID: subscription.ID,
|
|
ProductID: subscription.ProductID,
|
|
IsFreeTrial: subscription.IsFreeTrial,
|
|
TrialEndAt: subscription.TrialEndAt,
|
|
EndAt: subscription.EndAt,
|
|
CancelAt: subscription.CancelAt,
|
|
DelinquentSince: subscription.DelinquentSince,
|
|
CustomerID: "",
|
|
AddOns: []string{},
|
|
StartAt: 0,
|
|
CreateAt: 0,
|
|
Seats: 0,
|
|
Status: "",
|
|
DNS: "",
|
|
LastInvoice: &model.Invoice{},
|
|
BillingType: "",
|
|
}
|
|
}
|
|
|
|
if model.GetServiceEnvironment() != model.ServiceEnvironmentTest {
|
|
subscription.SimulatedCurrentTimeMs = nil
|
|
}
|
|
|
|
if !c.App.Config().FeatureFlags.CloudAnnualRenewals {
|
|
subscription.WillRenew = ""
|
|
subscription.CancelAt = nil
|
|
}
|
|
|
|
json, err := json.Marshal(subscription)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(json); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func validateBusinessEmail(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.validateBusinessEmail")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
user, appErr := c.App.GetUser(c.AppContext.Session().UserId)
|
|
if appErr != nil {
|
|
c.Err = model.NewAppError("Api4.validateBusinessEmail", "api.cloud.request_error", nil, "", http.StatusForbidden).Wrap(appErr)
|
|
return
|
|
}
|
|
|
|
bodyBytes, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
|
return
|
|
}
|
|
|
|
var emailToValidate *model.ValidateBusinessEmailRequest
|
|
err = json.Unmarshal(bodyBytes, &emailToValidate)
|
|
if err != nil || emailToValidate == nil {
|
|
c.Err = model.NewAppError("Api4.requestCloudTrial", "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
|
return
|
|
}
|
|
|
|
err = c.App.Cloud().ValidateBusinessEmail(user.Id, emailToValidate.Email)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.validateBusinessEmail", "api.cloud.request_error", nil, "", http.StatusForbidden).Wrap(err)
|
|
emailResp := model.ValidateBusinessEmailResponse{IsValid: false}
|
|
if err := json.NewEncoder(w).Encode(emailResp); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
return
|
|
}
|
|
emailResp := model.ValidateBusinessEmailResponse{IsValid: true}
|
|
if err := json.NewEncoder(w).Encode(emailResp); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func validateWorkspaceBusinessEmail(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.validateWorkspaceBusinessEmail")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.validateWorkspaceBusinessEmail", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteBilling) {
|
|
c.SetPermissionError(model.PermissionSysconsoleWriteBilling)
|
|
return
|
|
}
|
|
|
|
user, userErr := c.App.GetUser(c.AppContext.Session().UserId)
|
|
if userErr != nil {
|
|
c.Err = userErr
|
|
return
|
|
}
|
|
|
|
// get the cloud customer email to validate if is a valid business email
|
|
cloudCustomer, err := c.App.Cloud().GetCloudCustomer(user.Id)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.validateWorkspaceBusinessEmail", "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err)
|
|
return
|
|
}
|
|
emailErr := c.App.Cloud().ValidateBusinessEmail(user.Id, cloudCustomer.Email)
|
|
|
|
// if the current workspace email is not a valid business email
|
|
if emailErr != nil {
|
|
// grab the current admin email and validate it
|
|
errValidatingAdminEmail := c.App.Cloud().ValidateBusinessEmail(user.Id, user.Email)
|
|
if errValidatingAdminEmail != nil {
|
|
c.Err = model.NewAppError("Api4.validateWorkspaceBusinessEmail", "api.cloud.request_error", nil, "", http.StatusForbidden).Wrap(errValidatingAdminEmail)
|
|
emailResp := model.ValidateBusinessEmailResponse{IsValid: false}
|
|
if err := json.NewEncoder(w).Encode(emailResp); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
// if any of the emails is valid, return ok
|
|
emailResp := model.ValidateBusinessEmailResponse{IsValid: true}
|
|
if err := json.NewEncoder(w).Encode(emailResp); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.getCloudProducts")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
includeLegacyProducts := r.URL.Query().Get("include_legacy") == "true"
|
|
|
|
products, err := c.App.Cloud().GetCloudProducts(c.AppContext.Session().UserId, includeLegacyProducts)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
byteProductsData, err := json.Marshal(products)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadBilling) {
|
|
sanitizedProducts := []model.UserFacingProduct{}
|
|
err = json.Unmarshal(byteProductsData, &sanitizedProducts)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
byteSanitizedProductsData, err := json.Marshal(sanitizedProducts)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(byteSanitizedProductsData); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(byteProductsData); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func getCloudLimits(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.getCloudLimits")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
limits, err := c.App.Cloud().GetCloudLimits(c.AppContext.Session().UserId)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
json, err := json.Marshal(limits)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudLimits", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(json); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func getCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.getCloudCustomer")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadBilling) {
|
|
c.SetPermissionError(model.PermissionSysconsoleReadBilling)
|
|
return
|
|
}
|
|
|
|
customer, err := c.App.Cloud().GetCloudCustomer(c.AppContext.Session().UserId)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
json, err := json.Marshal(customer)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(json); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func getInstallation(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.getInstallation")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadIPFilters) {
|
|
c.SetPermissionError(model.PermissionSysconsoleReadIPFilters)
|
|
return
|
|
}
|
|
|
|
installation, err := c.App.Cloud().GetInstallation(c.AppContext.Session().UserId)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getInstallation", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if err := json.NewEncoder(w).Encode(installation); err != nil {
|
|
c.Err = model.NewAppError("Api4.getInstallation", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func updateCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.updateCloudCustomer")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteBilling) {
|
|
c.SetPermissionError(model.PermissionSysconsoleWriteBilling)
|
|
return
|
|
}
|
|
|
|
bodyBytes, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
var customerInfo *model.CloudCustomerInfo
|
|
if err = json.Unmarshal(bodyBytes, &customerInfo); err != nil || customerInfo == nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
customer, appErr := c.App.Cloud().UpdateCloudCustomer(c.AppContext.Session().UserId, customerInfo)
|
|
if appErr != nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr)
|
|
return
|
|
}
|
|
|
|
json, err := json.Marshal(customer)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(json); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func updateCloudCustomerAddress(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.updateCloudCustomerAddress")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteBilling) {
|
|
c.SetPermissionError(model.PermissionSysconsoleWriteBilling)
|
|
return
|
|
}
|
|
|
|
bodyBytes, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
var address *model.Address
|
|
if err = json.Unmarshal(bodyBytes, &address); err != nil || address == nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
customer, appErr := c.App.Cloud().UpdateCloudCustomerAddress(c.AppContext.Session().UserId, address)
|
|
if appErr != nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr)
|
|
return
|
|
}
|
|
|
|
json, err := json.Marshal(customer)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(json); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func getInvoicesForSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.getInvoicesForSubscription")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadBilling) {
|
|
c.SetPermissionError(model.PermissionSysconsoleReadBilling)
|
|
return
|
|
}
|
|
|
|
invoices, appErr := c.App.Cloud().GetInvoicesForSubscription(c.AppContext.Session().UserId)
|
|
if appErr != nil {
|
|
c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr)
|
|
return
|
|
}
|
|
|
|
json, err := json.Marshal(invoices)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if _, err := w.Write(json); err != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func getSubscriptionInvoicePDF(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.getSubscriptionInvoicePDF")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.getSubscriptionInvoicePDF", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
c.RequireInvoiceId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadBilling) {
|
|
c.SetPermissionError(model.PermissionSysconsoleReadBilling)
|
|
return
|
|
}
|
|
|
|
pdfData, filename, appErr := c.App.Cloud().GetInvoicePDF(c.AppContext.Session().UserId, c.Params.InvoiceId)
|
|
if appErr != nil {
|
|
c.Err = model.NewAppError("Api4.getSubscriptionInvoicePDF", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(appErr)
|
|
return
|
|
}
|
|
|
|
web.WriteFileResponse(
|
|
filename,
|
|
"application/pdf",
|
|
int64(binary.Size(pdfData)),
|
|
time.Now(),
|
|
*c.App.Config().ServiceSettings.WebserverMode,
|
|
bytes.NewReader(pdfData),
|
|
false,
|
|
w,
|
|
r,
|
|
)
|
|
}
|
|
|
|
func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.handleCWSWebhook")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
if !c.App.Channels().License().IsCloud() {
|
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.license_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
bodyBytes, err := io.ReadAll(r.Body)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
defer r.Body.Close()
|
|
|
|
var event *model.CWSWebhookPayload
|
|
if err = json.Unmarshal(bodyBytes, &event); err != nil || event == nil {
|
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
switch event.Event {
|
|
case model.EventTypeSendAdminWelcomeEmail:
|
|
user, appErr := c.App.GetUserByUsername(event.CloudWorkspaceOwner.UserName)
|
|
if appErr != nil {
|
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", appErr.Id, nil, "", appErr.StatusCode).Wrap(appErr)
|
|
return
|
|
}
|
|
|
|
teams, appErr := c.App.GetAllTeams()
|
|
if appErr != nil {
|
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", appErr.Id, nil, "", appErr.StatusCode).Wrap(appErr)
|
|
return
|
|
}
|
|
|
|
team := teams[0]
|
|
|
|
subscription, err := c.App.Cloud().GetSubscription(user.Id)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
if err := c.App.Srv().EmailService.SendCloudWelcomeEmail(user.Email, user.Locale, team.InviteId, subscription.GetWorkSpaceNameFromDNS(), subscription.DNS, *c.App.Config().ServiceSettings.SiteURL); err != nil {
|
|
c.Err = model.NewAppError("SendCloudWelcomeEmail", "api.user.send_cloud_welcome_email.error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
default:
|
|
c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.cws_webhook_event_missing_error", nil, "", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
ReturnStatusOK(w)
|
|
}
|
|
|
|
func handleCheckCWSConnection(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
ensured := ensureCloudInterface(c, "Api4.handleCheckCWSConnection")
|
|
if !ensured {
|
|
return
|
|
}
|
|
|
|
status := "available"
|
|
if err := c.App.Cloud().CheckCWSConnection(c.AppContext.Session().UserId); err != nil {
|
|
status = "unavailable"
|
|
}
|
|
|
|
response := map[string]string{"status": status}
|
|
if err := json.NewEncoder(w).Encode(response); err != nil {
|
|
c.Err = model.NewAppError("Api4.handleCheckCWSConnection", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func getPreviewModalData(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
modalData, err := c.App.GetPreviewModalData()
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
responseData, jsonErr := json.Marshal(modalData)
|
|
if jsonErr != nil {
|
|
c.Err = model.NewAppError("Api4.getPreviewModalData", "api.cloud.app_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
|
|
return
|
|
}
|
|
|
|
if _, writeErr := w.Write(responseData); writeErr != nil {
|
|
c.Logger.Warn("Error while writing response", mlog.Err(writeErr))
|
|
}
|
|
}
|