github.com/jancarloviray/community@v0.41.1-0.20170124221257-33a66c87cf2f/core/api/endpoint/sections_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  	"encoding/json"
    16  	"io/ioutil"
    17  	"net/http"
    18  
    19  	"github.com/documize/community/core/api/entity"
    20  	"github.com/documize/community/core/api/request"
    21  	"github.com/documize/community/core/api/util"
    22  	"github.com/documize/community/core/log"
    23  	"github.com/documize/community/core/section/provider"
    24  	"github.com/documize/community/core/utility"
    25  	"github.com/gorilla/mux"
    26  )
    27  
    28  // GetSections returns available smart sections.
    29  func GetSections(w http.ResponseWriter, r *http.Request) {
    30  	method := "GetSections"
    31  
    32  	json, err := json.Marshal(provider.GetSectionMeta())
    33  
    34  	if err != nil {
    35  		writeJSONMarshalError(w, method, "section", err)
    36  		return
    37  	}
    38  
    39  	writeSuccessBytes(w, json)
    40  }
    41  
    42  // RunSectionCommand passes UI request to section handler.
    43  func RunSectionCommand(w http.ResponseWriter, r *http.Request) {
    44  	method := "WebCommand"
    45  	p := request.GetPersister(r)
    46  
    47  	query := r.URL.Query()
    48  	documentID := query.Get("documentID")
    49  	sectionName := query.Get("section")
    50  
    51  	// Missing value checks
    52  	if len(documentID) == 0 {
    53  		writeMissingDataError(w, method, "documentID")
    54  		return
    55  	}
    56  
    57  	if len(sectionName) == 0 {
    58  		writeMissingDataError(w, method, "section")
    59  		return
    60  	}
    61  
    62  	// Note that targetMethod query item can be empty --
    63  	// it's up to the section handler to parse if required.
    64  
    65  	// Permission checks
    66  	if !p.CanChangeDocument(documentID) {
    67  		writeForbiddenError(w)
    68  		return
    69  	}
    70  
    71  	if !p.Context.Editor {
    72  		writeForbiddenError(w)
    73  		return
    74  	}
    75  
    76  	if !provider.Command(sectionName, provider.NewContext(p.Context.OrgID, p.Context.UserID), w, r) {
    77  		log.ErrorString("Unable to run provider.Command() for: " + sectionName)
    78  		writeNotFoundError(w, "RunSectionCommand", sectionName)
    79  	}
    80  }
    81  
    82  // RefreshSections updates document sections where the data is externally sourced.
    83  func RefreshSections(w http.ResponseWriter, r *http.Request) {
    84  	method := "RefreshSections"
    85  	p := request.GetPersister(r)
    86  
    87  	query := r.URL.Query()
    88  	documentID := query.Get("documentID")
    89  
    90  	if len(documentID) == 0 {
    91  		writeMissingDataError(w, method, "documentID")
    92  		return
    93  	}
    94  
    95  	if !p.CanViewDocument(documentID) {
    96  		writeForbiddenError(w)
    97  		return
    98  	}
    99  
   100  	// Return payload
   101  	var pages []entity.Page
   102  
   103  	// Let's see what sections are reliant on external sources
   104  	meta, err := p.GetDocumentPageMeta(documentID, true)
   105  
   106  	if err != nil {
   107  		writeGeneralSQLError(w, method, err)
   108  		return
   109  	}
   110  
   111  	tx, err := request.Db.Beginx()
   112  
   113  	if err != nil {
   114  		writeTransactionError(w, method, err)
   115  		return
   116  	}
   117  
   118  	p.Context.Transaction = tx
   119  
   120  	for _, pm := range meta {
   121  		// Grab the page because we need content type and
   122  		page, err2 := p.GetPage(pm.PageID)
   123  
   124  		if err2 != nil {
   125  			writeGeneralSQLError(w, method, err2)
   126  			log.IfErr(tx.Rollback())
   127  			return
   128  		}
   129  
   130  		pcontext := provider.NewContext(pm.OrgID, pm.UserID)
   131  
   132  		// Ask for data refresh
   133  		data, ok := provider.Refresh(page.ContentType, pcontext, pm.Config, pm.RawBody)
   134  		if !ok {
   135  			log.ErrorString("provider.Refresh could not find: " + page.ContentType)
   136  		}
   137  
   138  		// Render again
   139  		body, ok := provider.Render(page.ContentType, pcontext, pm.Config, data)
   140  		if !ok {
   141  			log.ErrorString("provider.Render could not find: " + page.ContentType)
   142  		}
   143  
   144  		// Compare to stored render
   145  		if body != page.Body {
   146  
   147  			// Persist latest data
   148  			page.Body = body
   149  			pages = append(pages, page)
   150  
   151  			refID := util.UniqueID()
   152  			err = p.UpdatePage(page, refID, p.Context.UserID, false)
   153  
   154  			if err != nil {
   155  				writeGeneralSQLError(w, method, err)
   156  				log.IfErr(tx.Rollback())
   157  				return
   158  			}
   159  
   160  			err = p.UpdatePageMeta(pm, false) // do not change the UserID on this PageMeta
   161  
   162  			if err != nil {
   163  				writeGeneralSQLError(w, method, err)
   164  				log.IfErr(tx.Rollback())
   165  				return
   166  			}
   167  		}
   168  	}
   169  
   170  	log.IfErr(tx.Commit())
   171  
   172  	json, err := json.Marshal(pages)
   173  
   174  	if err != nil {
   175  		writeJSONMarshalError(w, method, "pages", err)
   176  		return
   177  	}
   178  
   179  	writeSuccessBytes(w, json)
   180  }
   181  
   182  /**************************************************
   183   * Reusable Content Blocks
   184   **************************************************/
   185  
   186  // AddBlock inserts new reusable content block into database.
   187  func AddBlock(w http.ResponseWriter, r *http.Request) {
   188  	method := "AddBlock"
   189  	p := request.GetPersister(r)
   190  
   191  	defer utility.Close(r.Body)
   192  	body, err := ioutil.ReadAll(r.Body)
   193  
   194  	if err != nil {
   195  		writeBadRequestError(w, method, "Bad payload")
   196  		return
   197  	}
   198  
   199  	b := entity.Block{}
   200  	err = json.Unmarshal(body, &b)
   201  	if err != nil {
   202  		writePayloadError(w, method, err)
   203  		return
   204  	}
   205  
   206  	if !p.CanUploadDocument(b.LabelID) {
   207  		writeForbiddenError(w)
   208  		return
   209  	}
   210  
   211  	b.RefID = util.UniqueID()
   212  
   213  	tx, err := request.Db.Beginx()
   214  	if err != nil {
   215  		writeTransactionError(w, method, err)
   216  		return
   217  	}
   218  	p.Context.Transaction = tx
   219  
   220  	err = p.AddBlock(b)
   221  	if err != nil {
   222  		log.IfErr(tx.Rollback())
   223  		writeGeneralSQLError(w, method, err)
   224  		return
   225  	}
   226  
   227  	log.IfErr(tx.Commit())
   228  
   229  	b, err = p.GetBlock(b.RefID)
   230  	if err != nil {
   231  		writeGeneralSQLError(w, method, err)
   232  		return
   233  	}
   234  
   235  	json, err := json.Marshal(b)
   236  	if err != nil {
   237  		writeJSONMarshalError(w, method, "block", err)
   238  		return
   239  	}
   240  
   241  	writeSuccessBytes(w, json)
   242  }
   243  
   244  // GetBlock returns requested reusable content block.
   245  func GetBlock(w http.ResponseWriter, r *http.Request) {
   246  	method := "GetBlock"
   247  	p := request.GetPersister(r)
   248  
   249  	params := mux.Vars(r)
   250  	blockID := params["blockID"]
   251  
   252  	if len(blockID) == 0 {
   253  		writeMissingDataError(w, method, "blockID")
   254  		return
   255  	}
   256  
   257  	b, err := p.GetBlock(blockID)
   258  	if err != nil {
   259  		writeGeneralSQLError(w, method, err)
   260  		return
   261  	}
   262  
   263  	json, err := json.Marshal(b)
   264  	if err != nil {
   265  		writeJSONMarshalError(w, method, "block", err)
   266  		return
   267  	}
   268  
   269  	writeSuccessBytes(w, json)
   270  }
   271  
   272  // GetBlocksForSpace returns available reusable content blocks for the space.
   273  func GetBlocksForSpace(w http.ResponseWriter, r *http.Request) {
   274  	method := "GetBlocksForSpace"
   275  	p := request.GetPersister(r)
   276  
   277  	params := mux.Vars(r)
   278  	folderID := params["folderID"]
   279  
   280  	if len(folderID) == 0 {
   281  		writeMissingDataError(w, method, "folderID")
   282  		return
   283  	}
   284  
   285  	var b []entity.Block
   286  	var err error
   287  
   288  	b, err = p.GetBlocksForSpace(folderID)
   289  
   290  	if len(b) == 0 {
   291  		b = []entity.Block{}
   292  	}
   293  
   294  	if err != nil {
   295  		writeGeneralSQLError(w, method, err)
   296  		return
   297  	}
   298  
   299  	json, err := json.Marshal(b)
   300  	if err != nil {
   301  		writeJSONMarshalError(w, method, "block", err)
   302  		return
   303  	}
   304  
   305  	writeSuccessBytes(w, json)
   306  }
   307  
   308  // UpdateBlock inserts new reusable content block into database.
   309  func UpdateBlock(w http.ResponseWriter, r *http.Request) {
   310  	method := "UpdateBlock"
   311  	p := request.GetPersister(r)
   312  
   313  	defer utility.Close(r.Body)
   314  	body, err := ioutil.ReadAll(r.Body)
   315  
   316  	if err != nil {
   317  		writeBadRequestError(w, method, "Bad payload")
   318  		return
   319  	}
   320  
   321  	b := entity.Block{}
   322  	err = json.Unmarshal(body, &b)
   323  	if err != nil {
   324  		writePayloadError(w, method, err)
   325  		return
   326  	}
   327  
   328  	if !p.CanUploadDocument(b.LabelID) {
   329  		writeForbiddenError(w)
   330  		return
   331  	}
   332  
   333  	tx, err := request.Db.Beginx()
   334  	if err != nil {
   335  		writeTransactionError(w, method, err)
   336  		return
   337  	}
   338  
   339  	p.Context.Transaction = tx
   340  
   341  	err = p.UpdateBlock(b)
   342  	if err != nil {
   343  		log.IfErr(tx.Rollback())
   344  		writeGeneralSQLError(w, method, err)
   345  		return
   346  	}
   347  
   348  	log.IfErr(tx.Commit())
   349  
   350  	writeSuccessEmptyJSON(w)
   351  }
   352  
   353  // DeleteBlock removes requested reusable content block.
   354  func DeleteBlock(w http.ResponseWriter, r *http.Request) {
   355  	method := "DeleteBlock"
   356  	p := request.GetPersister(r)
   357  
   358  	params := mux.Vars(r)
   359  	blockID := params["blockID"]
   360  
   361  	if len(blockID) == 0 {
   362  		writeMissingDataError(w, method, "blockID")
   363  		return
   364  	}
   365  
   366  	tx, err := request.Db.Beginx()
   367  	if err != nil {
   368  		writeTransactionError(w, method, err)
   369  		return
   370  	}
   371  
   372  	p.Context.Transaction = tx
   373  
   374  	_, err = p.DeleteBlock(blockID)
   375  	if err != nil {
   376  		log.IfErr(tx.Rollback())
   377  		writeGeneralSQLError(w, method, err)
   378  		return
   379  	}
   380  
   381  	err = p.RemoveBlockReference(blockID)
   382  	if err != nil {
   383  		log.IfErr(tx.Rollback())
   384  		writeGeneralSQLError(w, method, err)
   385  		return
   386  	}
   387  
   388  	log.IfErr(tx.Commit())
   389  
   390  	writeSuccessEmptyJSON(w)
   391  }