github.com/elliott5/community@v0.14.1-0.20160709191136-823126fb026a/documize/api/endpoint/page_endpoint.go (about) 1 // Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved. 2 // 3 // This software (Documize Community Edition) is licensed under 4 // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html 5 // 6 // You can operate outside the AGPL restrictions by purchasing 7 // Documize Enterprise Edition and obtaining a commercial license 8 // by contacting <sales@documize.com>. 9 // 10 // https://documize.com 11 12 package endpoint 13 14 import ( 15 "database/sql" 16 "encoding/json" 17 // "html/template" 18 "io/ioutil" 19 "net/http" 20 "strconv" 21 22 "github.com/documize/community/documize/api/endpoint/models" 23 "github.com/documize/community/documize/api/entity" 24 "github.com/documize/community/documize/api/request" 25 "github.com/documize/community/documize/api/util" 26 "github.com/documize/community/documize/section/provider" 27 "github.com/documize/community/wordsmith/log" 28 "github.com/documize/community/wordsmith/utility" 29 30 "github.com/gorilla/mux" 31 ) 32 33 // AddDocumentPage inserts new section into document. 34 func AddDocumentPage(w http.ResponseWriter, r *http.Request) { 35 method := "AddDocumentPage" 36 p := request.GetPersister(r) 37 38 params := mux.Vars(r) 39 documentID := params["documentID"] 40 41 if len(documentID) == 0 { 42 writeMissingDataError(w, method, "documentID") 43 return 44 } 45 46 if !p.CanChangeDocument(documentID) { 47 writeForbiddenError(w) 48 return 49 } 50 51 defer utility.Close(r.Body) 52 body, err := ioutil.ReadAll(r.Body) 53 54 if err != nil { 55 writeBadRequestError(w, method, "Bad payload") 56 return 57 } 58 59 model := new(models.PageModel) 60 err = json.Unmarshal(body, &model) 61 62 if err != nil { 63 writePayloadError(w, method, err) 64 return 65 } 66 67 if model.Page.DocumentID != documentID { 68 writeBadRequestError(w, method, "documentID mismatch") 69 return 70 } 71 72 if model.Meta.DocumentID != documentID { 73 writeBadRequestError(w, method, "documentID mismatch") 74 return 75 } 76 77 pageID := util.UniqueID() 78 model.Page.RefID = pageID 79 model.Meta.PageID = pageID 80 model.Page.SetDefaults() 81 model.Meta.SetDefaults() 82 model.Meta.OrgID = p.Context.OrgID 83 model.Meta.UserID = p.Context.UserID 84 // page.Title = template.HTMLEscapeString(page.Title) 85 86 tx, err := request.Db.Beginx() 87 88 if err != nil { 89 writeTransactionError(w, method, err) 90 return 91 } 92 93 p.Context.Transaction = tx 94 95 output, ok := provider.Render(model.Page.ContentType, 96 provider.NewContext(model.Meta.OrgID, model.Meta.UserID), model.Meta.Config, model.Meta.RawBody) 97 if !ok { 98 log.ErrorString("provider.Render could not find: " + model.Page.ContentType) 99 } 100 101 model.Page.Body = output 102 103 err = p.AddPage(*model) 104 105 if err != nil { 106 log.IfErr(tx.Rollback()) 107 writeGeneralSQLError(w, method, err) 108 return 109 } 110 111 log.IfErr(tx.Commit()) 112 113 newPage, err := p.GetPage(pageID) 114 115 json, err := json.Marshal(newPage) 116 117 if err != nil { 118 writeJSONMarshalError(w, method, "page", err) 119 return 120 } 121 122 writeSuccessBytes(w, json) 123 } 124 125 // GetDocumentPage gets specified page for document. 126 func GetDocumentPage(w http.ResponseWriter, r *http.Request) { 127 method := "GetDocumentPage" 128 p := request.GetPersister(r) 129 130 params := mux.Vars(r) 131 documentID := params["documentID"] 132 pageID := params["pageID"] 133 134 if len(documentID) == 0 { 135 writeMissingDataError(w, method, "documentID") 136 return 137 } 138 139 if len(pageID) == 0 { 140 writeMissingDataError(w, method, "pageID") 141 return 142 } 143 144 if !p.CanViewDocument(documentID) { 145 writeForbiddenError(w) 146 return 147 } 148 149 page, err := p.GetPage(pageID) 150 151 if err == sql.ErrNoRows { 152 writeNotFoundError(w, method, documentID) 153 return 154 } 155 156 if err != nil { 157 writeGeneralSQLError(w, method, err) 158 return 159 } 160 161 if page.DocumentID != documentID { 162 writeBadRequestError(w, method, "documentID mismatch") 163 return 164 } 165 166 json, err := json.Marshal(page) 167 168 if err != nil { 169 writeJSONMarshalError(w, method, "document", err) 170 return 171 } 172 173 writeSuccessBytes(w, json) 174 } 175 176 // GetDocumentPages gets all pages for document. 177 func GetDocumentPages(w http.ResponseWriter, r *http.Request) { 178 method := "GetDocumentPages" 179 p := request.GetPersister(r) 180 181 params := mux.Vars(r) 182 documentID := params["documentID"] 183 184 if len(documentID) == 0 { 185 writeMissingDataError(w, method, "documentID") 186 return 187 } 188 189 if !p.CanViewDocument(documentID) { 190 writeForbiddenError(w) 191 return 192 } 193 194 query := r.URL.Query() 195 content := query.Get("content") 196 197 var pages []entity.Page 198 var err error 199 200 if len(content) > 0 { 201 pages, err = p.GetPagesWithoutContent(documentID) 202 } else { 203 pages, err = p.GetPages(documentID) 204 } 205 206 if len(pages) == 0 { 207 pages = []entity.Page{} 208 } 209 210 if err != nil { 211 writeGeneralSQLError(w, method, err) 212 return 213 } 214 215 json, err := json.Marshal(pages) 216 217 if err != nil { 218 writeJSONMarshalError(w, method, "document", err) 219 return 220 } 221 222 writeSuccessBytes(w, json) 223 } 224 225 // GetDocumentPagesBatch gets specified pages for document. 226 func GetDocumentPagesBatch(w http.ResponseWriter, r *http.Request) { 227 method := "GetDocumentPagesBatch" 228 p := request.GetPersister(r) 229 230 params := mux.Vars(r) 231 documentID := params["documentID"] 232 233 if len(documentID) == 0 { 234 writeMissingDataError(w, method, "documentID") 235 return 236 } 237 238 if !p.CanViewDocument(documentID) { 239 writeForbiddenError(w) 240 return 241 } 242 243 defer utility.Close(r.Body) 244 body, err := ioutil.ReadAll(r.Body) 245 246 if err != nil { 247 writePayloadError(w, method, err) 248 return 249 } 250 251 requestedPages := string(body) 252 253 pages, err := p.GetPagesWhereIn(documentID, requestedPages) 254 255 if err == sql.ErrNoRows { 256 writeNotFoundError(w, method, documentID) 257 return 258 } 259 260 if err != nil { 261 writeGeneralSQLError(w, method, err) 262 return 263 } 264 265 json, err := json.Marshal(pages) 266 267 if err != nil { 268 writeJSONMarshalError(w, method, "document", err) 269 return 270 } 271 272 writeSuccessBytes(w, json) 273 } 274 275 // DeleteDocumentPage deletes a page. 276 func DeleteDocumentPage(w http.ResponseWriter, r *http.Request) { 277 method := "DeleteDocumentPage" 278 p := request.GetPersister(r) 279 280 params := mux.Vars(r) 281 documentID := params["documentID"] 282 283 if len(documentID) == 0 { 284 writeMissingDataError(w, method, "documentID") 285 return 286 } 287 288 pageID := params["pageID"] 289 290 if len(documentID) == 0 { 291 writeMissingDataError(w, method, "pageID") 292 return 293 } 294 295 if !p.CanChangeDocument(documentID) { 296 writeForbiddenError(w) 297 return 298 } 299 300 tx, err := request.Db.Beginx() 301 302 if err != nil { 303 writeTransactionError(w, method, err) 304 return 305 } 306 307 p.Context.Transaction = tx 308 309 _, err = p.DeletePage(documentID, pageID) 310 311 if err != nil { 312 log.IfErr(tx.Rollback()) 313 writeGeneralSQLError(w, method, err) 314 return 315 } 316 317 log.IfErr(tx.Commit()) 318 319 writeSuccessEmptyJSON(w) 320 } 321 322 // DeleteDocumentPages batch deletes pages. 323 func DeleteDocumentPages(w http.ResponseWriter, r *http.Request) { 324 method := "DeleteDocumentPages" 325 p := request.GetPersister(r) 326 327 params := mux.Vars(r) 328 documentID := params["documentID"] 329 330 if len(documentID) == 0 { 331 writeMissingDataError(w, method, "documentID") 332 return 333 } 334 335 if !p.CanChangeDocument(documentID) { 336 writeForbiddenError(w) 337 return 338 } 339 340 defer utility.Close(r.Body) 341 body, err := ioutil.ReadAll(r.Body) 342 343 if err != nil { 344 writeBadRequestError(w, method, "Bad body") 345 return 346 } 347 348 model := new([]models.PageLevelRequestModel) 349 err = json.Unmarshal(body, &model) 350 351 if err != nil { 352 writePayloadError(w, method, err) 353 return 354 } 355 356 tx, err := request.Db.Beginx() 357 358 if err != nil { 359 writeTransactionError(w, method, err) 360 return 361 } 362 363 p.Context.Transaction = tx 364 365 for _, page := range *model { 366 _, err = p.DeletePage(documentID, page.PageID) 367 368 if err != nil { 369 log.IfErr(tx.Rollback()) 370 writeGeneralSQLError(w, method, err) 371 return 372 } 373 } 374 375 log.IfErr(tx.Commit()) 376 377 writeSuccessEmptyJSON(w) 378 } 379 380 // UpdateDocumentPage will persist changed page and note the fact 381 // that this is a new revision. If the page is the first in a document 382 // then the corresponding document title will also be changed. 383 func UpdateDocumentPage(w http.ResponseWriter, r *http.Request) { 384 method := "UpdateDocumentPage" 385 p := request.GetPersister(r) 386 387 if !p.Context.Editor { 388 writeForbiddenError(w) 389 return 390 } 391 392 params := mux.Vars(r) 393 documentID := params["documentID"] 394 395 if len(documentID) == 0 { 396 writeMissingDataError(w, method, "documentID") 397 return 398 } 399 400 pageID := params["pageID"] 401 402 if len(pageID) == 0 { 403 writeMissingDataError(w, method, "pageID") 404 return 405 } 406 407 defer utility.Close(r.Body) 408 body, err := ioutil.ReadAll(r.Body) 409 410 if err != nil { 411 writeBadRequestError(w, method, "Bad request body") 412 return 413 } 414 415 model := new(models.PageModel) 416 err = json.Unmarshal(body, &model) 417 418 if err != nil { 419 writePayloadError(w, method, err) 420 return 421 } 422 423 if model.Page.RefID != pageID || model.Page.DocumentID != documentID { 424 writeBadRequestError(w, method, "id mismatch") 425 return 426 } 427 428 tx, err := request.Db.Beginx() 429 430 if err != nil { 431 writeTransactionError(w, method, err) 432 return 433 } 434 435 model.Page.SetDefaults() 436 model.Meta.SetDefaults() 437 438 oldPageMeta, err := p.GetPageMeta(pageID) 439 440 if err != nil { 441 log.Error("unable to fetch old pagemeta record", err) 442 writeBadRequestError(w, method, err.Error()) 443 return 444 } 445 446 output, ok := provider.Render(model.Page.ContentType, provider.NewContext(model.Meta.OrgID, oldPageMeta.UserID), model.Meta.Config, model.Meta.RawBody) 447 if !ok { 448 log.ErrorString("provider.Render could not find: " + model.Page.ContentType) 449 } 450 model.Page.Body = output 451 452 p.Context.Transaction = tx 453 454 var skipRevision bool 455 skipRevision, err = strconv.ParseBool(r.URL.Query().Get("r")) 456 457 refID := util.UniqueID() 458 err = p.UpdatePage(model.Page, refID, p.Context.UserID, skipRevision) 459 460 if err != nil { 461 writeGeneralSQLError(w, method, err) 462 log.IfErr(tx.Rollback()) 463 return 464 } 465 466 err = p.UpdatePageMeta(model.Meta, true) // change the UserID to the current one 467 468 log.IfErr(tx.Commit()) 469 470 updatedPage, err := p.GetPage(pageID) 471 472 json, err := json.Marshal(updatedPage) 473 474 if err != nil { 475 writeJSONMarshalError(w, method, "page", err) 476 return 477 } 478 479 writeSuccessBytes(w, json) 480 } 481 482 // ChangeDocumentPageSequence will swap page sequence for a given number of pages. 483 func ChangeDocumentPageSequence(w http.ResponseWriter, r *http.Request) { 484 method := "ChangeDocumentPageSequence" 485 p := request.GetPersister(r) 486 487 params := mux.Vars(r) 488 documentID := params["documentID"] 489 490 if len(documentID) == 0 { 491 writeMissingDataError(w, method, "documentID") 492 return 493 } 494 495 if !p.CanChangeDocument(documentID) { 496 writeForbiddenError(w) 497 return 498 } 499 500 defer utility.Close(r.Body) 501 body, err := ioutil.ReadAll(r.Body) 502 503 if err != nil { 504 writePayloadError(w, method, err) 505 return 506 } 507 508 model := new([]models.PageSequenceRequestModel) 509 err = json.Unmarshal(body, &model) 510 511 if err != nil { 512 writeBadRequestError(w, method, "bad payload") 513 return 514 } 515 516 tx, err := request.Db.Beginx() 517 518 if err != nil { 519 writeTransactionError(w, method, err) 520 return 521 } 522 523 p.Context.Transaction = tx 524 525 for _, page := range *model { 526 err = p.UpdatePageSequence(documentID, page.PageID, page.Sequence) 527 528 if err != nil { 529 log.IfErr(tx.Rollback()) 530 writeGeneralSQLError(w, method, err) 531 return 532 } 533 } 534 535 log.IfErr(tx.Commit()) 536 537 writeSuccessEmptyJSON(w) 538 } 539 540 // ChangeDocumentPageLevel handles page indent/outdent changes. 541 func ChangeDocumentPageLevel(w http.ResponseWriter, r *http.Request) { 542 method := "ChangeDocumentPageLevel" 543 p := request.GetPersister(r) 544 545 params := mux.Vars(r) 546 documentID := params["documentID"] 547 548 if len(documentID) == 0 { 549 writeMissingDataError(w, method, "documentID") 550 return 551 } 552 553 if !p.CanChangeDocument(documentID) { 554 w.WriteHeader(http.StatusForbidden) 555 return 556 } 557 558 defer utility.Close(r.Body) 559 body, err := ioutil.ReadAll(r.Body) 560 561 if err != nil { 562 writePayloadError(w, method, err) 563 return 564 } 565 566 model := new([]models.PageLevelRequestModel) 567 err = json.Unmarshal(body, &model) 568 569 if err != nil { 570 writeBadRequestError(w, method, "bad payload") 571 return 572 } 573 574 tx, err := request.Db.Beginx() 575 576 if err != nil { 577 writeTransactionError(w, method, err) 578 return 579 } 580 581 p.Context.Transaction = tx 582 583 for _, page := range *model { 584 err = p.UpdatePageLevel(documentID, page.PageID, page.Level) 585 586 if err != nil { 587 log.IfErr(tx.Rollback()) 588 writeGeneralSQLError(w, method, err) 589 return 590 } 591 } 592 593 log.IfErr(tx.Commit()) 594 595 writeSuccessEmptyJSON(w) 596 } 597 598 // GetDocumentPageMeta gets page meta data for specified document page. 599 func GetDocumentPageMeta(w http.ResponseWriter, r *http.Request) { 600 method := "GetDocumentPageMeta" 601 p := request.GetPersister(r) 602 603 params := mux.Vars(r) 604 documentID := params["documentID"] 605 pageID := params["pageID"] 606 607 if len(documentID) == 0 { 608 writeMissingDataError(w, method, "documentID") 609 return 610 } 611 612 if len(pageID) == 0 { 613 writeMissingDataError(w, method, "pageID") 614 return 615 } 616 617 if !p.CanViewDocument(documentID) { 618 writeForbiddenError(w) 619 return 620 } 621 622 meta, err := p.GetPageMeta(pageID) 623 624 if err == sql.ErrNoRows { 625 writeNotFoundError(w, method, pageID) 626 return 627 } 628 629 if err != nil { 630 writeGeneralSQLError(w, method, err) 631 return 632 } 633 634 if meta.DocumentID != documentID { 635 writeBadRequestError(w, method, "documentID mismatch") 636 return 637 } 638 639 json, err := json.Marshal(meta) 640 641 if err != nil { 642 writeJSONMarshalError(w, method, "pagemeta", err) 643 return 644 } 645 646 writeSuccessBytes(w, json) 647 }