github.com/decred/politeia@v1.4.0/politeiawww/legacy/wwwcms.go (about) 1 // Copyright (c) 2017-2020 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package legacy 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "errors" 11 "net/http" 12 13 cms "github.com/decred/politeia/politeiawww/api/cms/v1" 14 www "github.com/decred/politeia/politeiawww/api/www/v1" 15 "github.com/decred/politeia/politeiawww/legacy/sessions" 16 "github.com/decred/politeia/util" 17 "github.com/google/uuid" 18 "github.com/gorilla/mux" 19 ) 20 21 // handleInviteNewUser handles the invitation of a new contractor by an 22 // administrator for the Contractor Management System. 23 func (p *Politeiawww) handleInviteNewUser(w http.ResponseWriter, r *http.Request) { 24 log.Tracef("handleInviteNewUser") 25 26 // Get the new user command. 27 var u cms.InviteNewUser 28 decoder := json.NewDecoder(r.Body) 29 if err := decoder.Decode(&u); err != nil { 30 RespondWithError(w, r, 0, "handleInviteNewUser: unmarshal", www.UserError{ 31 ErrorCode: www.ErrorStatusInvalidInput, 32 }) 33 return 34 } 35 36 reply, err := p.processInviteNewUser(u) 37 if err != nil { 38 RespondWithError(w, r, 0, "handleInviteNewUser: ProcessInviteNewUser %v", err) 39 return 40 } 41 42 // Reply with the verification token. 43 util.RespondWithJSON(w, http.StatusOK, reply) 44 } 45 46 // handleRegisterUser handles the completion of registration by invited users of 47 // the Contractor Management System. 48 func (p *Politeiawww) handleRegisterUser(w http.ResponseWriter, r *http.Request) { 49 log.Tracef("handleRegisterUser") 50 51 // Get the new user command. 52 var u cms.RegisterUser 53 decoder := json.NewDecoder(r.Body) 54 if err := decoder.Decode(&u); err != nil { 55 RespondWithError(w, r, 0, "handleRegisterUser: unmarshal", www.UserError{ 56 ErrorCode: www.ErrorStatusInvalidInput, 57 }) 58 return 59 } 60 61 reply, err := p.processRegisterUser(u) 62 if err != nil { 63 RespondWithError(w, r, 0, "handleRegisterUser: ProcessRegisterUser %v", err) 64 return 65 } 66 67 // Reply with the verification token. 68 util.RespondWithJSON(w, http.StatusOK, reply) 69 } 70 71 // handleCMSUsers handles fetching a list of cms users. 72 func (p *Politeiawww) handleCMSUsers(w http.ResponseWriter, r *http.Request) { 73 log.Tracef("handleCMSUsers") 74 75 var cu cms.CMSUsers 76 err := util.ParseGetParams(r, &cu) 77 if err != nil { 78 RespondWithError(w, r, 0, "handleCMSUsers: ParseGetParams", 79 www.UserError{ 80 ErrorCode: www.ErrorStatusInvalidInput, 81 }) 82 return 83 } 84 85 cur, err := p.processCMSUsers(&cu) 86 if err != nil { 87 RespondWithError(w, r, 0, 88 "handleCMSUsers: processCMSUsers %v", err) 89 return 90 } 91 92 util.RespondWithJSON(w, http.StatusOK, cur) 93 } 94 95 // handleNewInvoice handles the incoming new invoice command. 96 func (p *Politeiawww) handleNewInvoice(w http.ResponseWriter, r *http.Request) { 97 log.Tracef("handleNewInvoice") 98 99 // Get the new invoice command. 100 var ni cms.NewInvoice 101 decoder := json.NewDecoder(r.Body) 102 if err := decoder.Decode(&ni); err != nil { 103 RespondWithError(w, r, 0, "handleNewInvoice: unmarshal", www.UserError{ 104 ErrorCode: www.ErrorStatusInvalidInput, 105 }) 106 return 107 } 108 109 user, err := p.sessions.GetSessionUser(w, r) 110 if err != nil { 111 RespondWithError(w, r, 0, 112 "handleNewInvoice: getSessionUser %v", err) 113 return 114 } 115 116 reply, err := p.processNewInvoice(r.Context(), ni, user) 117 if err != nil { 118 RespondWithError(w, r, 0, 119 "handleNewInvoice: processNewInvoice %v", err) 120 return 121 } 122 123 // Reply with the challenge response and censorship token. 124 util.RespondWithJSON(w, http.StatusOK, reply) 125 } 126 127 // handleInvoiceDetails handles the incoming invoice details command. It fetches 128 // the complete details for an existing invoice. 129 func (p *Politeiawww) handleInvoiceDetails(w http.ResponseWriter, r *http.Request) { 130 log.Tracef("handleInvoiceDetails") 131 132 // Get the invoice details command 133 var pd cms.InvoiceDetails 134 // get version from query string parameters 135 err := util.ParseGetParams(r, &pd) 136 if err != nil { 137 RespondWithError(w, r, 0, "handleInvoiceDetails: ParseGetParams", 138 www.UserError{ 139 ErrorCode: www.ErrorStatusInvalidInput, 140 }) 141 return 142 } 143 144 // Get invoice token from path parameters 145 pathParams := mux.Vars(r) 146 pd.Token = pathParams["token"] 147 148 user, err := p.sessions.GetSessionUser(w, r) 149 if err != nil { 150 if !errors.Is(err, sessions.ErrSessionNotFound) { 151 RespondWithError(w, r, 0, 152 "handleInvoiceDetails: getSessionUser %v", err) 153 return 154 } 155 } 156 reply, err := p.processInvoiceDetails(pd, user) 157 if err != nil { 158 RespondWithError(w, r, 0, 159 "handleInvoiceDetails: processInvoiceDetails %v", err) 160 return 161 } 162 163 // Reply with the proposal details. 164 util.RespondWithJSON(w, http.StatusOK, reply) 165 } 166 167 // handleUserInvoices handles the request to get all of the invoices from the 168 // currently logged in user. 169 func (p *Politeiawww) handleUserInvoices(w http.ResponseWriter, r *http.Request) { 170 log.Tracef("handleUserInvoices") 171 172 user, err := p.sessions.GetSessionUser(w, r) 173 if err != nil { 174 RespondWithError(w, r, 0, 175 "handleUserInvoices: getSessionUser %v", err) 176 return 177 } 178 179 reply, err := p.processUserInvoices(user) 180 if err != nil { 181 RespondWithError(w, r, 0, "handleUserInvoices: processUserInvoices %v", err) 182 return 183 } 184 185 // Reply with the verification token. 186 util.RespondWithJSON(w, http.StatusOK, reply) 187 } 188 189 // handleAdminUserInvoices handles the request to get all of the invoices of a 190 // user by an administrator for the Contractor Management System. 191 func (p *Politeiawww) handleAdminUserInvoices(w http.ResponseWriter, r *http.Request) { 192 log.Tracef("handleAdminUserInvoices") 193 194 var aui cms.AdminUserInvoices 195 // get version from query string parameters 196 err := util.ParseGetParams(r, &aui) 197 if err != nil { 198 RespondWithError(w, r, 0, "handleAdminUserInvoices: ParseGetParams", 199 www.UserError{ 200 ErrorCode: www.ErrorStatusInvalidInput, 201 }) 202 return 203 } 204 205 _, err = uuid.Parse(aui.UserID) 206 if err != nil { 207 RespondWithError(w, r, 0, "handleAdminUserInvoices: ParseUint", 208 www.UserError{ 209 ErrorCode: www.ErrorStatusInvalidInput, 210 }) 211 return 212 } 213 214 reply, err := p.processAdminUserInvoices(aui) 215 if err != nil { 216 RespondWithError(w, r, 0, "handleAdminUserInvoices: processAdminUserInvoices %v", err) 217 return 218 } 219 220 util.RespondWithJSON(w, http.StatusOK, reply) 221 } 222 223 // handleSetInvoiceStatus handles the incoming set invoice status command. 224 func (p *Politeiawww) handleSetInvoiceStatus(w http.ResponseWriter, r *http.Request) { 225 log.Tracef("handleSetInvoiceStatus") 226 227 // Get set invoice command 228 var sis cms.SetInvoiceStatus 229 decoder := json.NewDecoder(r.Body) 230 if err := decoder.Decode(&sis); err != nil { 231 RespondWithError(w, r, 0, "handleSetInvoiceStatus: unmarshal", www.UserError{ 232 ErrorCode: www.ErrorStatusInvalidInput, 233 }) 234 return 235 } 236 237 user, err := p.sessions.GetSessionUser(w, r) 238 if err != nil { 239 RespondWithError(w, r, 0, 240 "handleSetInvoiceStatus: getSessionUser %v", err) 241 return 242 } 243 244 reply, err := p.processSetInvoiceStatus(r.Context(), sis, user) 245 if err != nil { 246 RespondWithError(w, r, 0, 247 "handleSetInvoiceStatus: processSetInvoiceStatus %v", err) 248 return 249 } 250 251 // Reply with the challenge response and censorship token. 252 util.RespondWithJSON(w, http.StatusOK, reply) 253 } 254 255 // handleInvoices handles the request to get all of the of a new contractor by an 256 // administrator for the Contractor Management System. 257 func (p *Politeiawww) handleInvoices(w http.ResponseWriter, r *http.Request) { 258 log.Tracef("handleInvoices") 259 var ai cms.Invoices 260 decoder := json.NewDecoder(r.Body) 261 if err := decoder.Decode(&ai); err != nil { 262 RespondWithError(w, r, 0, "handleInvoices: unmarshal", www.UserError{ 263 ErrorCode: www.ErrorStatusInvalidInput, 264 }) 265 return 266 } 267 268 user, err := p.sessions.GetSessionUser(w, r) 269 if err != nil { 270 RespondWithError(w, r, 0, 271 "handleInvoices: getSessionUser %v", err) 272 return 273 } 274 275 reply, err := p.processInvoices(ai, user) 276 if err != nil { 277 RespondWithError(w, r, 0, "handleInvoices: processInvoices %v", err) 278 return 279 } 280 281 // Reply with the verification token. 282 util.RespondWithJSON(w, http.StatusOK, reply) 283 } 284 285 // handleEditInvoice attempts to edit an invoice 286 func (p *Politeiawww) handleEditInvoice(w http.ResponseWriter, r *http.Request) { 287 log.Tracef("handleEditInvoice") 288 289 // Get edit invoice command 290 var ei cms.EditInvoice 291 decoder := json.NewDecoder(r.Body) 292 if err := decoder.Decode(&ei); err != nil { 293 RespondWithError(w, r, 0, "handleEditInvoice: unmarshal", 294 www.UserError{ 295 ErrorCode: www.ErrorStatusInvalidInput, 296 }) 297 return 298 } 299 300 user, err := p.sessions.GetSessionUser(w, r) 301 if err != nil { 302 RespondWithError(w, r, 0, 303 "handleEditInvoice: getSessionUser %v", err) 304 return 305 } 306 307 log.Debugf("handleEditInvoice: %v", ei.Token) 308 309 epr, err := p.processEditInvoice(r.Context(), ei, user) 310 if err != nil { 311 RespondWithError(w, r, 0, 312 "handleEditInvoice: processEditInvoice %v", err) 313 return 314 } 315 316 util.RespondWithJSON(w, http.StatusOK, epr) 317 } 318 319 // handleGeneratePayouts handles the request to generate all of the payouts for any 320 // currently approved invoice. 321 func (p *Politeiawww) handleGeneratePayouts(w http.ResponseWriter, r *http.Request) { 322 log.Tracef("handleGeneratePayouts") 323 324 // Get generate payouts command 325 var gp cms.GeneratePayouts 326 decoder := json.NewDecoder(r.Body) 327 if err := decoder.Decode(&gp); err != nil { 328 RespondWithError(w, r, 0, "handleGeneratePayouts: unmarshal", 329 www.UserError{ 330 ErrorCode: www.ErrorStatusInvalidInput, 331 }) 332 return 333 } 334 335 user, err := p.sessions.GetSessionUser(w, r) 336 if err != nil { 337 RespondWithError(w, r, 0, 338 "handleGeneratePayouts: getSessionUser %v", err) 339 return 340 } 341 342 reply, err := p.processGeneratePayouts(gp, user) 343 if err != nil { 344 RespondWithError(w, r, 0, "handleGeneratePayouts: processGeneratePayouts %v", err) 345 return 346 } 347 348 // Reply with the generated payouts 349 util.RespondWithJSON(w, http.StatusOK, reply) 350 } 351 352 // handleNewCommentInvoice handles incomming comments for invoices. 353 func (p *Politeiawww) handleNewCommentInvoice(w http.ResponseWriter, r *http.Request) { 354 log.Tracef("handleNewCommentInvoice") 355 356 var sc www.NewComment 357 decoder := json.NewDecoder(r.Body) 358 if err := decoder.Decode(&sc); err != nil { 359 RespondWithError(w, r, 0, "handleNewCommentInvoice: unmarshal", 360 www.UserError{ 361 ErrorCode: www.ErrorStatusInvalidInput, 362 }) 363 return 364 } 365 366 user, err := p.sessions.GetSessionUser(w, r) 367 if err != nil { 368 RespondWithError(w, r, 0, 369 "handleNewCommentInvoice: getSessionUser %v", err) 370 return 371 } 372 373 cr, err := p.processNewCommentInvoice(r.Context(), sc, user) 374 if err != nil { 375 RespondWithError(w, r, 0, 376 "handleNewCommentInvoice: processNewCommentInvoice: %v", err) 377 return 378 } 379 380 util.RespondWithJSON(w, http.StatusOK, cr) 381 } 382 383 // handleInvoiceComments handles batched invoice comments get. 384 func (p *Politeiawww) handleInvoiceComments(w http.ResponseWriter, r *http.Request) { 385 log.Tracef("handleInvoiceComments") 386 387 pathParams := mux.Vars(r) 388 token := pathParams["token"] 389 390 user, err := p.sessions.GetSessionUser(w, r) 391 if err != nil { 392 if !errors.Is(err, sessions.ErrSessionNotFound) { 393 RespondWithError(w, r, 0, 394 "handleInvoiceComments: getSessionUser %v", err) 395 return 396 } 397 } 398 gcr, err := p.processInvoiceComments(r.Context(), token, user) 399 if err != nil { 400 RespondWithError(w, r, 0, 401 "handleInvoiceComments: processInvoiceComments %v", err) 402 return 403 } 404 util.RespondWithJSON(w, http.StatusOK, gcr) 405 } 406 407 // handleInvoiceExchangeRate handles incoming requests for monthly exchange rate 408 func (p *Politeiawww) handleInvoiceExchangeRate(w http.ResponseWriter, r *http.Request) { 409 log.Tracef("handleInvoiceExchangeRate") 410 411 var ier cms.InvoiceExchangeRate 412 decoder := json.NewDecoder(r.Body) 413 if err := decoder.Decode(&ier); err != nil { 414 RespondWithError(w, r, 0, "handleInvoiceExchangeRate: unmarshal", 415 www.UserError{ 416 ErrorCode: www.ErrorStatusInvalidInput, 417 }) 418 return 419 } 420 421 ierr, err := p.processInvoiceExchangeRate(r.Context(), ier) 422 if err != nil { 423 RespondWithError(w, r, 0, 424 "handleInvoiceExchangeRate: processNewCommentInvoice: %v", err) 425 return 426 } 427 428 util.RespondWithJSON(w, http.StatusOK, ierr) 429 } 430 431 func (p *Politeiawww) handleCMSPolicy(w http.ResponseWriter, r *http.Request) { 432 // Get the policy command. 433 log.Tracef("handlePolicy") 434 reply := &cms.PolicyReply{ 435 MinPasswordLength: www.PolicyMinPasswordLength, 436 MinUsernameLength: www.PolicyMinUsernameLength, 437 MaxUsernameLength: www.PolicyMaxUsernameLength, 438 MaxImages: cms.PolicyMaxImages, 439 MaxImageSize: www.PolicyMaxImageSize, 440 MaxMDs: www.PolicyMaxMDs, 441 MaxMDSize: www.PolicyMaxMDSize, 442 ValidMIMETypes: cms.PolicyValidMimeTypes, 443 MinLineItemColLength: cms.PolicyMinLineItemColLength, 444 MaxLineItemColLength: cms.PolicyMaxLineItemColLength, 445 MaxNameLength: cms.PolicyMaxNameLength, 446 MinNameLength: cms.PolicyMinNameLength, 447 MaxLocationLength: cms.PolicyMaxLocationLength, 448 MinLocationLength: cms.PolicyMinLocationLength, 449 MaxContactLength: cms.PolicyMaxContactLength, 450 MinContactLength: cms.PolicyMinContactLength, 451 InvoiceFieldSupportedChars: cms.PolicyInvoiceFieldSupportedChars, 452 UsernameSupportedChars: www.PolicyUsernameSupportedChars, 453 CMSNameLocationSupportedChars: cms.PolicyCMSNameLocationSupportedChars, 454 CMSContactSupportedChars: cms.PolicyCMSContactSupportedChars, 455 CMSStatementSupportedChars: cms.PolicySponsorStatementSupportedChars, 456 CMSSupportedDomains: cms.PolicySupportedCMSDomains, 457 CMSSupportedLineItemTypes: cms.PolicyCMSSupportedLineItemTypes, 458 } 459 460 util.RespondWithJSON(w, http.StatusOK, reply) 461 } 462 463 // handlePayInvoices handles the request to generate all of the payouts for any 464 // currently approved invoice. 465 func (p *Politeiawww) handlePayInvoices(w http.ResponseWriter, r *http.Request) { 466 log.Tracef("handlePayInvoices") 467 468 user, err := p.sessions.GetSessionUser(w, r) 469 if err != nil { 470 RespondWithError(w, r, 0, 471 "handlePayInvoices: getSessionUser %v", err) 472 return 473 } 474 475 reply, err := p.processPayInvoices(r.Context(), user) 476 if err != nil { 477 RespondWithError(w, r, 0, "handlePayInvoices: processPayInvoices %v", 478 err) 479 return 480 } 481 482 util.RespondWithJSON(w, http.StatusOK, reply) 483 } 484 485 // handleEditCMSUser handles the request to edit a given user's 486 // additional user information. 487 func (p *Politeiawww) handleEditCMSUser(w http.ResponseWriter, r *http.Request) { 488 log.Tracef("handleEditCMSUser") 489 490 var eu cms.EditUser 491 decoder := json.NewDecoder(r.Body) 492 if err := decoder.Decode(&eu); err != nil { 493 RespondWithError(w, r, 0, "handleEditCMSUser: unmarshal", 494 www.UserError{ 495 ErrorCode: www.ErrorStatusInvalidInput, 496 }) 497 return 498 } 499 500 user, err := p.sessions.GetSessionUser(w, r) 501 if err != nil { 502 RespondWithError(w, r, 0, 503 "handleEditCMSUser: getSessionUser %v", err) 504 return 505 } 506 507 reply, err := p.processEditCMSUser(eu, user) 508 if err != nil { 509 RespondWithError(w, r, 0, "handleEditCMSUser: "+ 510 "processUpdateUserInformation %v", err) 511 return 512 } 513 514 util.RespondWithJSON(w, http.StatusOK, reply) 515 } 516 517 // handleManageCMSUser handles the request to edit a given user's 518 // additional user information. 519 func (p *Politeiawww) handleManageCMSUser(w http.ResponseWriter, r *http.Request) { 520 log.Tracef("handleManageCMSUser") 521 522 var mu cms.CMSManageUser 523 decoder := json.NewDecoder(r.Body) 524 if err := decoder.Decode(&mu); err != nil { 525 RespondWithError(w, r, 0, "handleManageCMSUser: unmarshal", 526 www.UserError{ 527 ErrorCode: www.ErrorStatusInvalidInput, 528 }) 529 return 530 } 531 532 reply, err := p.processManageCMSUser(mu) 533 if err != nil { 534 RespondWithError(w, r, 0, "handleManageCMSUser: "+ 535 "processManageCMSUser %v", err) 536 return 537 } 538 539 util.RespondWithJSON(w, http.StatusOK, reply) 540 } 541 542 func (p *Politeiawww) handleCMSUserDetails(w http.ResponseWriter, r *http.Request) { 543 // Add the path param to the struct. 544 log.Tracef("handleCMSUserDetails") 545 pathParams := mux.Vars(r) 546 var ud cms.UserDetails 547 ud.UserID = pathParams["userid"] 548 549 userID, err := uuid.Parse(ud.UserID) 550 if err != nil { 551 RespondWithError(w, r, 0, "handleCMSUserDetails: ParseUint", 552 www.UserError{ 553 ErrorCode: www.ErrorStatusInvalidInput, 554 }) 555 return 556 } 557 558 user, err := p.sessions.GetSessionUser(w, r) 559 if err != nil { 560 RespondWithError(w, r, 0, 561 "handleCMSUserDetails: getSessionUser %v", err) 562 return 563 } 564 565 reply, err := p.processCMSUserDetails(&ud, 566 user != nil && user.ID == userID, 567 user != nil && user.Admin, 568 ) 569 570 if err != nil { 571 RespondWithError(w, r, 0, "handleCMSUserDetails: "+ 572 "processCMSUserDetails %v", err) 573 return 574 } 575 576 util.RespondWithJSON(w, http.StatusOK, reply) 577 } 578 579 // handleInvoicePayouts handles incoming requests for invoice payout information 580 func (p *Politeiawww) handleInvoicePayouts(w http.ResponseWriter, r *http.Request) { 581 log.Tracef("handleInvoicePayouts") 582 583 var lip cms.InvoicePayouts 584 decoder := json.NewDecoder(r.Body) 585 if err := decoder.Decode(&lip); err != nil { 586 RespondWithError(w, r, 0, "handleInvoicePayouts: unmarshal", 587 www.UserError{ 588 ErrorCode: www.ErrorStatusInvalidInput, 589 }) 590 return 591 } 592 593 lipr, err := p.processInvoicePayouts(lip) 594 if err != nil { 595 RespondWithError(w, r, 0, 596 "handleInvoicePayouts: processInvoicePayouts: %v", err) 597 return 598 } 599 600 util.RespondWithJSON(w, http.StatusOK, lipr) 601 } 602 603 func (p *Politeiawww) handleNewDCC(w http.ResponseWriter, r *http.Request) { 604 log.Tracef("handleNewDCC") 605 606 var nd cms.NewDCC 607 decoder := json.NewDecoder(r.Body) 608 if err := decoder.Decode(&nd); err != nil { 609 RespondWithError(w, r, 0, "handleNewDCC: unmarshal", 610 www.UserError{ 611 ErrorCode: www.ErrorStatusInvalidInput, 612 }) 613 return 614 } 615 u, err := p.sessions.GetSessionUser(w, r) 616 if err != nil { 617 RespondWithError(w, r, 0, 618 "handleNewDCC: getSessionUser %v", err) 619 return 620 } 621 622 ndr, err := p.processNewDCC(r.Context(), nd, u) 623 if err != nil { 624 RespondWithError(w, r, 0, 625 "handleNewDCC: processNewDCC: %v", err) 626 return 627 } 628 629 util.RespondWithJSON(w, http.StatusOK, ndr) 630 } 631 632 func (p *Politeiawww) handleDCCDetails(w http.ResponseWriter, r *http.Request) { 633 log.Tracef("handleDCCDetails") 634 635 var gd cms.DCCDetails 636 // get version from query string parameters 637 err := util.ParseGetParams(r, &gd) 638 if err != nil { 639 RespondWithError(w, r, 0, "handleDCCDetails: ParseGetParams", 640 www.UserError{ 641 ErrorCode: www.ErrorStatusInvalidInput, 642 }) 643 return 644 } 645 // Get dcc token from path parameters 646 pathParams := mux.Vars(r) 647 gd.Token = pathParams["token"] 648 649 gdr, err := p.processDCCDetails(r.Context(), gd) 650 if err != nil { 651 RespondWithError(w, r, 0, 652 "handleDCCDetails: processDCCDetails: %v", err) 653 return 654 } 655 656 util.RespondWithJSON(w, http.StatusOK, gdr) 657 } 658 659 func (p *Politeiawww) handleGetDCCs(w http.ResponseWriter, r *http.Request) { 660 log.Tracef("handleGetDCCs") 661 662 var gds cms.GetDCCs 663 decoder := json.NewDecoder(r.Body) 664 if err := decoder.Decode(&gds); err != nil { 665 RespondWithError(w, r, 0, "handleGetDCCs: unmarshal", 666 www.UserError{ 667 ErrorCode: www.ErrorStatusInvalidInput, 668 }) 669 return 670 } 671 _, err := p.sessions.GetSessionUser(w, r) 672 if err != nil { 673 RespondWithError(w, r, 0, 674 "handleGetDCCs: getSessionUser %v", err) 675 return 676 } 677 678 gdsr, err := p.processGetDCCs(gds) 679 if err != nil { 680 RespondWithError(w, r, 0, 681 "handleGetDCCs: processGetDCCs: %v", err) 682 return 683 } 684 685 util.RespondWithJSON(w, http.StatusOK, gdsr) 686 } 687 688 func (p *Politeiawww) handleSupportOpposeDCC(w http.ResponseWriter, r *http.Request) { 689 log.Tracef("handleSupportOpposeDCC") 690 691 var sd cms.SupportOpposeDCC 692 decoder := json.NewDecoder(r.Body) 693 if err := decoder.Decode(&sd); err != nil { 694 RespondWithError(w, r, 0, "handleSupportOpposeDCC: unmarshal", 695 www.UserError{ 696 ErrorCode: www.ErrorStatusInvalidInput, 697 }) 698 return 699 } 700 u, err := p.sessions.GetSessionUser(w, r) 701 if err != nil { 702 RespondWithError(w, r, 0, 703 "handleSupportOpposeDCC: getSessionUser %v", err) 704 return 705 } 706 707 sdr, err := p.processSupportOpposeDCC(r.Context(), sd, u) 708 if err != nil { 709 RespondWithError(w, r, 0, 710 "handleSupportOpposeDCC: processSupportOpposeDCC: %v", err) 711 return 712 } 713 714 util.RespondWithJSON(w, http.StatusOK, sdr) 715 } 716 717 // handleNewCommentDCC handles incomming comments for DCC. 718 func (p *Politeiawww) handleNewCommentDCC(w http.ResponseWriter, r *http.Request) { 719 log.Tracef("handleNewCommentDCC") 720 721 var sc www.NewComment 722 decoder := json.NewDecoder(r.Body) 723 if err := decoder.Decode(&sc); err != nil { 724 RespondWithError(w, r, 0, "handleNewCommentDCC: unmarshal", 725 www.UserError{ 726 ErrorCode: www.ErrorStatusInvalidInput, 727 }) 728 return 729 } 730 731 user, err := p.sessions.GetSessionUser(w, r) 732 if err != nil { 733 RespondWithError(w, r, 0, 734 "handleNewCommentDCC: getSessionUser %v", err) 735 return 736 } 737 738 cr, err := p.processNewCommentDCC(r.Context(), sc, user) 739 if err != nil { 740 RespondWithError(w, r, 0, 741 "handleNewCommentDCC: processNewCommentDCC: %v", err) 742 return 743 } 744 745 util.RespondWithJSON(w, http.StatusOK, cr) 746 } 747 748 // handleDCCComments handles batched comments get. 749 func (p *Politeiawww) handleDCCComments(w http.ResponseWriter, r *http.Request) { 750 log.Tracef("handleDCCComments") 751 752 pathParams := mux.Vars(r) 753 token := pathParams["token"] 754 755 user, err := p.sessions.GetSessionUser(w, r) 756 if err != nil { 757 if !errors.Is(err, sessions.ErrSessionNotFound) { 758 RespondWithError(w, r, 0, 759 "handleDCCComments: getSessionUser %v", err) 760 return 761 } 762 } 763 gcr, err := p.processDCCComments(r.Context(), token, user) 764 if err != nil { 765 RespondWithError(w, r, 0, 766 "handleDCCComments: processDCCComments %v", err) 767 return 768 } 769 util.RespondWithJSON(w, http.StatusOK, gcr) 770 } 771 772 func (p *Politeiawww) handleSetDCCStatus(w http.ResponseWriter, r *http.Request) { 773 log.Tracef("handleSetDCCStatus") 774 775 var ad cms.SetDCCStatus 776 decoder := json.NewDecoder(r.Body) 777 if err := decoder.Decode(&ad); err != nil { 778 RespondWithError(w, r, 0, "handleSetDCCStatus: unmarshal", 779 www.UserError{ 780 ErrorCode: www.ErrorStatusInvalidInput, 781 }) 782 return 783 } 784 u, err := p.sessions.GetSessionUser(w, r) 785 if err != nil { 786 RespondWithError(w, r, 0, 787 "handleSetDCCStatus: getSessionUser %v", err) 788 return 789 } 790 791 adr, err := p.processSetDCCStatus(r.Context(), ad, u) 792 if err != nil { 793 RespondWithError(w, r, 0, 794 "handleSetDCCStatus: processSetDCCStatus: %v", err) 795 return 796 } 797 798 util.RespondWithJSON(w, http.StatusOK, adr) 799 } 800 801 func (p *Politeiawww) handleUserSubContractors(w http.ResponseWriter, r *http.Request) { 802 log.Tracef("handleUserSubContractors") 803 804 u, err := p.sessions.GetSessionUser(w, r) 805 if err != nil { 806 RespondWithError(w, r, 0, 807 "handleUserSubContractors: getSessionUser %v", err) 808 return 809 } 810 811 uscr, err := p.processUserSubContractors(u) 812 if err != nil { 813 RespondWithError(w, r, 0, 814 "handleUserSubContractors: processUserSubContractors: %v", err) 815 return 816 } 817 818 util.RespondWithJSON(w, http.StatusOK, uscr) 819 } 820 821 func (p *Politeiawww) handleProposalOwner(w http.ResponseWriter, r *http.Request) { 822 log.Tracef("handleProposalOwner") 823 824 var po cms.ProposalOwner 825 err := util.ParseGetParams(r, &po) 826 if err != nil { 827 RespondWithError(w, r, 0, "handleProposalOwner: ParseGetParams", 828 www.UserError{ 829 ErrorCode: www.ErrorStatusInvalidInput, 830 }) 831 return 832 } 833 por, err := p.processProposalOwner(po) 834 if err != nil { 835 RespondWithError(w, r, 0, 836 "handleProposalOwner: processProposalOwner: %v", err) 837 return 838 } 839 840 util.RespondWithJSON(w, http.StatusOK, por) 841 } 842 843 func (p *Politeiawww) handleProposalBilling(w http.ResponseWriter, r *http.Request) { 844 log.Tracef("handleProposalBilling") 845 846 var pb cms.ProposalBilling 847 decoder := json.NewDecoder(r.Body) 848 if err := decoder.Decode(&pb); err != nil { 849 RespondWithError(w, r, 0, "handleProposalBilling: unmarshal", 850 www.UserError{ 851 ErrorCode: www.ErrorStatusInvalidInput, 852 }) 853 return 854 } 855 856 u, err := p.sessions.GetSessionUser(w, r) 857 if err != nil { 858 RespondWithError(w, r, 0, 859 "handleProposalBilling: getSessionUser %v", err) 860 return 861 } 862 863 pbr, err := p.processProposalBilling(pb, u) 864 if err != nil { 865 RespondWithError(w, r, 0, 866 "handleProposalBilling: processProposalBilling: %v", err) 867 return 868 } 869 870 util.RespondWithJSON(w, http.StatusOK, pbr) 871 } 872 873 func (p *Politeiawww) handleCastVoteDCC(w http.ResponseWriter, r *http.Request) { 874 log.Tracef("handleCastVoteDCC") 875 876 var cv cms.CastVote 877 decoder := json.NewDecoder(r.Body) 878 if err := decoder.Decode(&cv); err != nil { 879 RespondWithError(w, r, 0, "handleCastVoteDCC: unmarshal", www.UserError{ 880 ErrorCode: www.ErrorStatusInvalidInput, 881 }) 882 return 883 } 884 885 u, err := p.sessions.GetSessionUser(w, r) 886 if err != nil { 887 RespondWithError(w, r, 0, 888 "handleCastVoteDCC: getSessionUser %v", err) 889 return 890 } 891 892 cvr, err := p.processCastVoteDCC(r.Context(), cv, u) 893 if err != nil { 894 RespondWithError(w, r, 0, 895 "handleCastVoteDCC: processCastVoteDCC: %v", err) 896 return 897 } 898 899 util.RespondWithJSON(w, http.StatusOK, cvr) 900 } 901 902 func (p *Politeiawww) handleVoteDetailsDCC(w http.ResponseWriter, r *http.Request) { 903 log.Tracef("handleVoteDetailsDCC") 904 905 var vd cms.VoteDetails 906 decoder := json.NewDecoder(r.Body) 907 if err := decoder.Decode(&vd); err != nil { 908 RespondWithError(w, r, 0, "handleVoteDetailsDCC: unmarshal", www.UserError{ 909 ErrorCode: www.ErrorStatusInvalidInput, 910 }) 911 return 912 } 913 914 vdr, err := p.processVoteDetailsDCC(r.Context(), vd.Token) 915 if err != nil { 916 RespondWithError(w, r, 0, 917 "handleVoteDetailsDCC: processVoteDetailsDCC: %v", err) 918 return 919 } 920 921 util.RespondWithJSON(w, http.StatusOK, vdr) 922 } 923 924 // handleActiveVoteDCC returns all active dccs that have an active vote. 925 func (p *Politeiawww) handleActiveVoteDCC(w http.ResponseWriter, r *http.Request) { 926 log.Tracef("handleActiveVoteDCC") 927 928 avr, err := p.processActiveVoteDCC(r.Context()) 929 if err != nil { 930 RespondWithError(w, r, 0, 931 "handleActiveVoteDCC: processActiveVoteDCC %v", err) 932 return 933 } 934 935 util.RespondWithJSON(w, http.StatusOK, avr) 936 } 937 938 // handleStartVoteDCC handles the dcc StartVote route. 939 func (p *Politeiawww) handleStartVoteDCC(w http.ResponseWriter, r *http.Request) { 940 log.Tracef("handleStartVoteDCC") 941 942 var sv cms.StartVote 943 decoder := json.NewDecoder(r.Body) 944 if err := decoder.Decode(&sv); err != nil { 945 RespondWithError(w, r, 0, "handleStartVoteDCC: unmarshal", 946 www.UserError{ 947 ErrorCode: www.ErrorStatusInvalidInput, 948 }) 949 return 950 } 951 user, err := p.sessions.GetSessionUser(w, r) 952 if err != nil { 953 RespondWithError(w, r, 0, 954 "handleStartVoteDCC: getSessionUser %v", err) 955 return 956 } 957 958 // Sanity 959 if !user.Admin { 960 RespondWithError(w, r, 0, 961 "handleStartVoteDCC: admin %v", user.Admin) 962 return 963 } 964 965 svr, err := p.processStartVoteDCC(r.Context(), sv, user) 966 if err != nil { 967 RespondWithError(w, r, 0, 968 "handleStartVoteDCC: processStartVoteDCC %v", err) 969 return 970 } 971 972 util.RespondWithJSON(w, http.StatusOK, svr) 973 } 974 975 func (p *Politeiawww) handlePassThroughTokenInventory(w http.ResponseWriter, r *http.Request) { 976 log.Tracef("handlePassThroughTokenInventory") 977 978 data, err := p.makeProposalsRequest(http.MethodGet, www.RouteTokenInventory, nil) 979 if err != nil { 980 RespondWithError(w, r, 0, 981 "handlePassThroughTokenInventory: makeProposalsRequest: %v", err) 982 return 983 } 984 util.RespondRaw(w, http.StatusOK, data) 985 } 986 987 func (p *Politeiawww) handlePassThroughBatchProposals(w http.ResponseWriter, r *http.Request) { 988 log.Tracef("handlePassThroughBatchProposals") 989 990 var bp www.BatchProposals 991 decoder := json.NewDecoder(r.Body) 992 if err := decoder.Decode(&bp); err != nil { 993 RespondWithError(w, r, 0, "handlePassThroughBatchProposals: unmarshal", 994 www.UserError{ 995 ErrorCode: www.ErrorStatusInvalidInput, 996 }) 997 return 998 } 999 1000 data, err := p.makeProposalsRequest(http.MethodPost, www.RouteBatchProposals, bp) 1001 if err != nil { 1002 RespondWithError(w, r, 0, 1003 "handlePassThroughBatchProposals: makeProposalsRequest: %v", err) 1004 return 1005 } 1006 util.RespondRaw(w, http.StatusOK, data) 1007 } 1008 1009 func (p *Politeiawww) handleProposalBillingSummary(w http.ResponseWriter, r *http.Request) { 1010 log.Tracef("handleProposalBillingSummary") 1011 1012 var pbs cms.ProposalBillingSummary 1013 // get version from query string parameters 1014 err := util.ParseGetParams(r, &pbs) 1015 if err != nil { 1016 RespondWithError(w, r, 0, "handleProposalBillingSummary: ParseGetParams", 1017 www.UserError{ 1018 ErrorCode: www.ErrorStatusInvalidInput, 1019 }) 1020 return 1021 } 1022 1023 pbsr, err := p.processProposalBillingSummary(pbs) 1024 if err != nil { 1025 RespondWithError(w, r, 0, 1026 "handleProposalBillingSummary: processProposalBillingSummary %v", err) 1027 return 1028 } 1029 1030 util.RespondWithJSON(w, http.StatusOK, pbsr) 1031 } 1032 1033 func (p *Politeiawww) handleProposalBillingDetails(w http.ResponseWriter, r *http.Request) { 1034 log.Tracef("handleProposalBillingDetails") 1035 1036 var pbd cms.ProposalBillingDetails 1037 decoder := json.NewDecoder(r.Body) 1038 if err := decoder.Decode(&pbd); err != nil { 1039 RespondWithError(w, r, 0, "handleProposalBillingDetails: unmarshal", 1040 www.UserError{ 1041 ErrorCode: www.ErrorStatusInvalidInput, 1042 }) 1043 return 1044 } 1045 1046 svr, err := p.processProposalBillingDetails(pbd) 1047 if err != nil { 1048 RespondWithError(w, r, 0, 1049 "handleProposalBillingDetails: processProposalBillingDetails %v", err) 1050 return 1051 } 1052 1053 util.RespondWithJSON(w, http.StatusOK, svr) 1054 } 1055 1056 // makeProposalsRequest submits pass through requests to the proposals sites 1057 // (testnet or mainnet). It takes a http method type, proposals route and a 1058 // request interface as arguments. It returns the response body as byte array 1059 // (which can then be decoded as though a response directly from proposals). 1060 func (p *Politeiawww) makeProposalsRequest(method string, route string, v interface{}) ([]byte, error) { 1061 var ( 1062 requestBody []byte 1063 responseBody []byte 1064 err error 1065 ) 1066 if v != nil { 1067 requestBody, err = json.Marshal(v) 1068 if err != nil { 1069 return nil, err 1070 } 1071 } 1072 1073 client, err := util.NewHTTPClient(false, "") 1074 if err != nil { 1075 return nil, err 1076 } 1077 1078 dest := cms.ProposalsMainnet 1079 if p.cfg.TestNet { 1080 dest = cms.ProposalsTestnet 1081 } 1082 1083 route = dest + "/api/v1" + route 1084 1085 req, err := http.NewRequest(method, route, 1086 bytes.NewReader(requestBody)) 1087 if err != nil { 1088 return nil, err 1089 } 1090 1091 r, err := client.Do(req) 1092 if err != nil { 1093 return nil, err 1094 } 1095 defer r.Body.Close() 1096 1097 if r.StatusCode != http.StatusOK { 1098 return nil, www.UserError{ 1099 ErrorCode: www.ErrorStatusT(r.StatusCode), 1100 } 1101 } 1102 1103 responseBody = util.ConvertBodyToByteArray(r.Body, false) 1104 return responseBody, nil 1105 } 1106 1107 func (p *Politeiawww) handleUserCodeStats(w http.ResponseWriter, r *http.Request) { 1108 log.Tracef("handleUserCodeStats") 1109 1110 var ucs cms.UserCodeStats 1111 decoder := json.NewDecoder(r.Body) 1112 if err := decoder.Decode(&ucs); err != nil { 1113 RespondWithError(w, r, 0, "handleUserCodeStats: unmarshal", 1114 www.UserError{ 1115 ErrorCode: www.ErrorStatusInvalidInput, 1116 }) 1117 return 1118 } 1119 1120 u, err := p.sessions.GetSessionUser(w, r) 1121 if err != nil { 1122 RespondWithError(w, r, 0, 1123 "handleUserCodeStats: getSessionUser %v", err) 1124 return 1125 } 1126 1127 uscr, err := p.processUserCodeStats(ucs, u) 1128 if err != nil { 1129 RespondWithError(w, r, 0, 1130 "handleUserCodeStats: processUserCodeStats: %v", err) 1131 return 1132 } 1133 1134 util.RespondWithJSON(w, http.StatusOK, uscr) 1135 }