github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/cloud.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package api4 5 6 import ( 7 "bytes" 8 "encoding/binary" 9 "encoding/json" 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 "time" 14 15 "github.com/masterhung0112/hk_server/v5/audit" 16 "github.com/masterhung0112/hk_server/v5/model" 17 ) 18 19 func (api *API) InitCloud() { 20 // GET /api/v4/cloud/products 21 api.BaseRoutes.Cloud.Handle("/products", api.ApiSessionRequired(getCloudProducts)).Methods("GET") 22 23 // POST /api/v4/cloud/payment 24 // POST /api/v4/cloud/payment/confirm 25 api.BaseRoutes.Cloud.Handle("/payment", api.ApiSessionRequired(createCustomerPayment)).Methods("POST") 26 api.BaseRoutes.Cloud.Handle("/payment/confirm", api.ApiSessionRequired(confirmCustomerPayment)).Methods("POST") 27 28 // GET /api/v4/cloud/customer 29 // PUT /api/v4/cloud/customer 30 // PUT /api/v4/cloud/customer/address 31 api.BaseRoutes.Cloud.Handle("/customer", api.ApiSessionRequired(getCloudCustomer)).Methods("GET") 32 api.BaseRoutes.Cloud.Handle("/customer", api.ApiSessionRequired(updateCloudCustomer)).Methods("PUT") 33 api.BaseRoutes.Cloud.Handle("/customer/address", api.ApiSessionRequired(updateCloudCustomerAddress)).Methods("PUT") 34 35 // GET /api/v4/cloud/subscription 36 api.BaseRoutes.Cloud.Handle("/subscription", api.ApiSessionRequired(getSubscription)).Methods("GET") 37 api.BaseRoutes.Cloud.Handle("/subscription/invoices", api.ApiSessionRequired(getInvoicesForSubscription)).Methods("GET") 38 api.BaseRoutes.Cloud.Handle("/subscription/invoices/{invoice_id:in_[A-Za-z0-9]+}/pdf", api.ApiSessionRequired(getSubscriptionInvoicePDF)).Methods("GET") 39 api.BaseRoutes.Cloud.Handle("/subscription/limitreached/invite", api.ApiSessionRequired(sendAdminUpgradeRequestEmail)).Methods("POST") 40 api.BaseRoutes.Cloud.Handle("/subscription/limitreached/join", api.ApiHandler(sendAdminUpgradeRequestEmailOnJoin)).Methods("POST") 41 api.BaseRoutes.Cloud.Handle("/subscription/stats", api.ApiHandler(getSubscriptionStats)).Methods("GET") 42 api.BaseRoutes.Cloud.Handle("/subscription", api.ApiSessionRequired(changeSubscription)).Methods("PUT") 43 44 // POST /api/v4/cloud/webhook 45 api.BaseRoutes.Cloud.Handle("/webhook", api.CloudApiKeyRequired(handleCWSWebhook)).Methods("POST") 46 } 47 48 func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) { 49 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 50 c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 51 return 52 } 53 54 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_BILLING) { 55 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_BILLING) 56 return 57 } 58 59 subscription, err := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId) 60 if err != nil { 61 c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 62 return 63 } 64 65 json, err := json.Marshal(subscription) 66 if err != nil { 67 c.Err = model.NewAppError("Api4.getSubscription", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 68 return 69 } 70 71 w.Write(json) 72 } 73 74 func changeSubscription(c *Context, w http.ResponseWriter, r *http.Request) { 75 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 76 c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.license_error", nil, "", http.StatusInternalServerError) 77 return 78 } 79 80 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_BILLING) { 81 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_BILLING) 82 return 83 } 84 85 bodyBytes, err := ioutil.ReadAll(r.Body) 86 if err != nil { 87 c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusBadRequest) 88 return 89 } 90 91 var subscriptionChange *model.SubscriptionChange 92 if err = json.Unmarshal(bodyBytes, &subscriptionChange); err != nil { 93 c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusBadRequest) 94 } 95 96 currentSubscription, appErr := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId) 97 if appErr != nil { 98 c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, appErr.Error(), http.StatusInternalServerError) 99 return 100 } 101 102 changedSub, err := c.App.Cloud().ChangeSubscription(c.AppContext.Session().UserId, currentSubscription.ID, subscriptionChange) 103 if err != nil { 104 c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 105 } 106 107 json, err := json.Marshal(changedSub) 108 if err != nil { 109 c.Err = model.NewAppError("Api4.changeSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 110 } 111 112 w.Write(json) 113 } 114 115 func getSubscriptionStats(c *Context, w http.ResponseWriter, r *http.Request) { 116 s, err := c.App.GetSubscriptionStats() 117 if err != nil { 118 c.Err = err 119 return 120 } 121 122 stats, _ := json.Marshal(s) 123 124 w.Write([]byte(string(stats))) 125 } 126 127 func getCloudProducts(c *Context, w http.ResponseWriter, r *http.Request) { 128 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 129 c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 130 return 131 } 132 133 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_BILLING) { 134 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_BILLING) 135 return 136 } 137 138 products, err := c.App.Cloud().GetCloudProducts(c.AppContext.Session().UserId) 139 if err != nil { 140 c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 141 return 142 } 143 144 json, err := json.Marshal(products) 145 if err != nil { 146 c.Err = model.NewAppError("Api4.getCloudProducts", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 147 return 148 } 149 150 w.Write(json) 151 } 152 153 func getCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { 154 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 155 c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 156 return 157 } 158 159 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_BILLING) { 160 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_BILLING) 161 return 162 } 163 164 customer, err := c.App.Cloud().GetCloudCustomer(c.AppContext.Session().UserId) 165 if err != nil { 166 c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 167 return 168 } 169 170 json, err := json.Marshal(customer) 171 if err != nil { 172 c.Err = model.NewAppError("Api4.getCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 173 return 174 } 175 176 w.Write(json) 177 } 178 179 func updateCloudCustomer(c *Context, w http.ResponseWriter, r *http.Request) { 180 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 181 c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 182 return 183 } 184 185 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_BILLING) { 186 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_BILLING) 187 return 188 } 189 190 bodyBytes, err := ioutil.ReadAll(r.Body) 191 if err != nil { 192 c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 193 return 194 } 195 196 var customerInfo *model.CloudCustomerInfo 197 if err = json.Unmarshal(bodyBytes, &customerInfo); err != nil { 198 c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 199 return 200 } 201 202 customer, appErr := c.App.Cloud().UpdateCloudCustomer(c.AppContext.Session().UserId, customerInfo) 203 if appErr != nil { 204 c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError) 205 return 206 } 207 208 json, err := json.Marshal(customer) 209 if err != nil { 210 c.Err = model.NewAppError("Api4.updateCloudCustomer", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 211 return 212 } 213 214 w.Write(json) 215 } 216 217 func updateCloudCustomerAddress(c *Context, w http.ResponseWriter, r *http.Request) { 218 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 219 c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 220 return 221 } 222 223 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_BILLING) { 224 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_BILLING) 225 return 226 } 227 228 bodyBytes, err := ioutil.ReadAll(r.Body) 229 if err != nil { 230 c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 231 return 232 } 233 234 var address *model.Address 235 if err = json.Unmarshal(bodyBytes, &address); err != nil { 236 c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 237 return 238 } 239 240 customer, appErr := c.App.Cloud().UpdateCloudCustomerAddress(c.AppContext.Session().UserId, address) 241 if appErr != nil { 242 c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError) 243 return 244 } 245 246 json, err := json.Marshal(customer) 247 if err != nil { 248 c.Err = model.NewAppError("Api4.updateCloudCustomerAddress", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 249 return 250 } 251 252 w.Write(json) 253 } 254 255 func createCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) { 256 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 257 c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 258 return 259 } 260 261 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_BILLING) { 262 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_BILLING) 263 return 264 } 265 266 auditRec := c.MakeAuditRecord("createCustomerPayment", audit.Fail) 267 defer c.LogAuditRec(auditRec) 268 269 intent, err := c.App.Cloud().CreateCustomerPayment(c.AppContext.Session().UserId) 270 if err != nil { 271 c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 272 return 273 } 274 275 json, err := json.Marshal(intent) 276 if err != nil { 277 c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 278 return 279 } 280 281 auditRec.Success() 282 283 w.Write(json) 284 } 285 286 func confirmCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request) { 287 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 288 c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 289 return 290 } 291 292 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_WRITE_BILLING) { 293 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_BILLING) 294 return 295 } 296 297 auditRec := c.MakeAuditRecord("confirmCustomerPayment", audit.Fail) 298 defer c.LogAuditRec(auditRec) 299 300 bodyBytes, err := ioutil.ReadAll(r.Body) 301 if err != nil { 302 c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 303 return 304 } 305 306 var confirmRequest *model.ConfirmPaymentMethodRequest 307 if err = json.Unmarshal(bodyBytes, &confirmRequest); err != nil { 308 c.Err = model.NewAppError("Api4.confirmCustomerPayment", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 309 return 310 } 311 312 err = c.App.Cloud().ConfirmCustomerPayment(c.AppContext.Session().UserId, confirmRequest) 313 if err != nil { 314 c.Err = model.NewAppError("Api4.createCustomerPayment", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 315 return 316 } 317 318 auditRec.Success() 319 320 ReturnStatusOK(w) 321 } 322 323 func getInvoicesForSubscription(c *Context, w http.ResponseWriter, r *http.Request) { 324 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 325 c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 326 return 327 } 328 329 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_BILLING) { 330 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_BILLING) 331 return 332 } 333 334 invoices, appErr := c.App.Cloud().GetInvoicesForSubscription(c.AppContext.Session().UserId) 335 if appErr != nil { 336 c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError) 337 return 338 } 339 340 json, err := json.Marshal(invoices) 341 if err != nil { 342 c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 343 return 344 } 345 346 w.Write(json) 347 } 348 349 func getSubscriptionInvoicePDF(c *Context, w http.ResponseWriter, r *http.Request) { 350 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 351 c.Err = model.NewAppError("Api4.getSuscriptionInvoicePDF", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 352 return 353 } 354 355 c.RequireInvoiceId() 356 if c.Err != nil { 357 return 358 } 359 360 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_SYSCONSOLE_READ_BILLING) { 361 c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_BILLING) 362 return 363 } 364 365 pdfData, filename, appErr := c.App.Cloud().GetInvoicePDF(c.AppContext.Session().UserId, c.Params.InvoiceId) 366 if appErr != nil { 367 c.Err = model.NewAppError("Api4.getSuscriptionInvoicePDF", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError) 368 return 369 } 370 371 writeFileResponse( 372 filename, 373 "application/pdf", 374 int64(binary.Size(pdfData)), 375 time.Now(), 376 *c.App.Config().ServiceSettings.WebserverMode, 377 bytes.NewReader(pdfData), 378 false, 379 w, 380 r, 381 ) 382 } 383 384 func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) { 385 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 386 c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 387 return 388 } 389 390 bodyBytes, err := ioutil.ReadAll(r.Body) 391 if err != nil { 392 c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 393 return 394 } 395 defer r.Body.Close() 396 397 var event *model.CWSWebhookPayload 398 if err = json.Unmarshal(bodyBytes, &event); err != nil { 399 c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError) 400 return 401 } 402 403 switch event.Event { 404 case model.EventTypeFailedPayment: 405 if nErr := c.App.SendPaymentFailedEmail(event.FailedPayment); nErr != nil { 406 c.Err = nErr 407 return 408 } 409 case model.EventTypeFailedPaymentNoCard: 410 if nErr := c.App.SendNoCardPaymentFailedEmail(); nErr != nil { 411 c.Err = nErr 412 return 413 } 414 case model.EventTypeSendAdminWelcomeEmail: 415 user, appErr := c.App.GetUserByUsername(event.CloudWorkspaceOwner.UserName) 416 if appErr != nil { 417 c.Err = model.NewAppError("Api4.handleCWSWebhook", appErr.Id, nil, appErr.Error(), appErr.StatusCode) 418 return 419 } 420 421 teams, appErr := c.App.GetAllTeams() 422 if appErr != nil { 423 c.Err = model.NewAppError("Api4.handleCWSWebhook", appErr.Id, nil, appErr.Error(), appErr.StatusCode) 424 return 425 } 426 427 team := teams[0] 428 429 subscription, err := c.App.Cloud().GetSubscription(user.Id) 430 if err != nil { 431 c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 432 return 433 } 434 435 if appErr := c.App.Srv().EmailService.SendCloudWelcomeEmail(user.Email, user.Locale, team.InviteId, subscription.GetWorkSpaceNameFromDNS(), subscription.DNS, *c.App.Config().ServiceSettings.SiteURL); appErr != nil { 436 c.Err = appErr 437 return 438 } 439 case model.EventTypeTrialWillEnd: 440 endTimeStamp := event.SubscriptionTrialEndUnixTimeStamp 441 t := time.Unix(endTimeStamp, 0) 442 trialEndDate := fmt.Sprintf("%s %d, %d", t.Month(), t.Day(), t.Year()) 443 444 if appErr := c.App.SendCloudTrialEndWarningEmail(trialEndDate, *c.App.Config().ServiceSettings.SiteURL); appErr != nil { 445 c.Err = appErr 446 return 447 } 448 case model.EventTypeTrialEnded: 449 if appErr := c.App.SendCloudTrialEndedEmail(); appErr != nil { 450 c.Err = appErr 451 return 452 } 453 454 default: 455 c.Err = model.NewAppError("Api4.handleCWSWebhook", "api.cloud.cws_webhook_event_missing_error", nil, "", http.StatusNotFound) 456 return 457 } 458 459 ReturnStatusOK(w) 460 } 461 462 func sendAdminUpgradeRequestEmail(c *Context, w http.ResponseWriter, r *http.Request) { 463 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 464 c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 465 return 466 } 467 468 user, appErr := c.App.GetUser(c.AppContext.Session().UserId) 469 if appErr != nil { 470 c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", appErr.Id, nil, appErr.Error(), appErr.StatusCode) 471 return 472 } 473 474 sub, err := c.App.Cloud().GetSubscription(c.AppContext.Session().UserId) 475 if err != nil { 476 c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 477 return 478 } 479 480 if appErr = c.App.SendAdminUpgradeRequestEmail(user.Username, sub, model.InviteLimitation); appErr != nil { 481 c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", appErr.Id, nil, appErr.Error(), appErr.StatusCode) 482 return 483 } 484 485 ReturnStatusOK(w) 486 } 487 488 func sendAdminUpgradeRequestEmailOnJoin(c *Context, w http.ResponseWriter, r *http.Request) { 489 if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud { 490 c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmailOnJoin", "api.cloud.license_error", nil, "", http.StatusNotImplemented) 491 return 492 } 493 494 sub, err := c.App.Cloud().GetSubscription("") 495 if err != nil { 496 c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmailOnJoin", "api.cloud.request_error", nil, err.Error(), http.StatusInternalServerError) 497 return 498 } 499 500 if appErr := c.App.SendAdminUpgradeRequestEmail("", sub, model.JoinLimitation); appErr != nil { 501 c.Err = model.NewAppError("Api4.sendAdminUpgradeRequestEmail", appErr.Id, nil, appErr.Error(), appErr.StatusCode) 502 return 503 } 504 505 ReturnStatusOK(w) 506 }