github.com/elliott5/community@v0.14.1-0.20160709191136-823126fb026a/documize/api/endpoint/attachment_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 "bytes" 16 "database/sql" 17 "encoding/json" 18 "fmt" 19 "io" 20 "mime" 21 "net/http" 22 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/wordsmith/log" 27 28 uuid "github.com/nu7hatch/gouuid" 29 30 "github.com/gorilla/mux" 31 32 _ "github.com/mytrile/mime-ext" // this adds a large number of mime extensions 33 ) 34 35 // AttachmentDownload is the end-point that responds to a request for a particular attachment 36 // by sending the requested file to the client. 37 func AttachmentDownload(w http.ResponseWriter, r *http.Request) { 38 method := "AttachmentDownload" 39 p := request.GetPersister(r) 40 41 params := mux.Vars(r) 42 43 attachment, err := p.GetAttachmentByJobAndFileID(params["orgID"], params["job"], params["fileID"]) 44 45 if err == sql.ErrNoRows { 46 writeNotFoundError(w, method, params["fileID"]) 47 return 48 } 49 50 if err != nil { 51 writeGeneralSQLError(w, method, err) 52 return 53 } 54 55 typ := mime.TypeByExtension("." + attachment.Extension) 56 if typ == "" { 57 typ = "application/octet-stream" 58 } 59 60 w.Header().Set("Content-Type", typ) 61 w.Header().Set("Content-Disposition", `Attachment; filename="`+attachment.Filename+`" ; `+`filename*="`+attachment.Filename+`"`) 62 w.Header().Set("Content-Length", fmt.Sprintf("%d", len(attachment.Data))) 63 w.WriteHeader(http.StatusOK) 64 65 _, err = w.Write(attachment.Data) 66 log.IfErr(err) 67 } 68 69 // GetAttachments is an end-point that returns all of the attachments of a particular documentID. 70 func GetAttachments(w http.ResponseWriter, r *http.Request) { 71 method := "GetAttachments" 72 p := request.GetPersister(r) 73 74 params := mux.Vars(r) 75 documentID := params["documentID"] 76 77 if len(documentID) == 0 { 78 writeMissingDataError(w, method, "documentID") 79 return 80 } 81 82 if !p.CanViewDocument(documentID) { 83 writeForbiddenError(w) 84 return 85 } 86 87 a, err := p.GetAttachments(documentID) 88 89 if err != nil && err != sql.ErrNoRows { 90 writeGeneralSQLError(w, method, err) 91 return 92 } 93 94 json, err := json.Marshal(a) 95 96 if err != nil { 97 writeJSONMarshalError(w, method, "attachments", err) 98 return 99 } 100 101 writeSuccessBytes(w, json) 102 } 103 104 // DeleteAttachment is an endpoint that deletes a particular document attachment. 105 func DeleteAttachment(w http.ResponseWriter, r *http.Request) { 106 method := "DeleteAttachment" 107 p := request.GetPersister(r) 108 109 params := mux.Vars(r) 110 documentID := params["documentID"] 111 attachmentID := params["attachmentID"] 112 113 if len(documentID) == 0 || len(attachmentID) == 0 { 114 writeMissingDataError(w, method, "documentID, attachmentID") 115 return 116 } 117 118 if !p.CanChangeDocument(documentID) { 119 writeForbiddenError(w) 120 return 121 } 122 123 tx, err := request.Db.Beginx() 124 125 if err != nil { 126 writeTransactionError(w, method, err) 127 return 128 } 129 130 p.Context.Transaction = tx 131 132 _, err = p.DeleteAttachment(attachmentID) 133 134 if err != nil { 135 log.IfErr(tx.Rollback()) 136 writeGeneralSQLError(w, method, err) 137 return 138 } 139 140 log.IfErr(tx.Commit()) 141 142 writeSuccessEmptyJSON(w) 143 } 144 145 // AddAttachments stores files against a document. 146 func AddAttachments(w http.ResponseWriter, r *http.Request) { 147 method := "AddAttachments" 148 p := request.GetPersister(r) 149 150 params := mux.Vars(r) 151 documentID := params["documentID"] 152 153 if len(documentID) == 0 { 154 writeMissingDataError(w, method, "documentID") 155 return 156 } 157 158 if !p.CanChangeDocument(documentID) { 159 w.WriteHeader(http.StatusForbidden) 160 return 161 } 162 163 filedata, filename, err := r.FormFile("attachment") 164 165 if err != nil { 166 writeMissingDataError(w, method, "attachment") 167 return 168 } 169 170 b := new(bytes.Buffer) 171 _, err = io.Copy(b, filedata) 172 173 if err != nil { 174 writeServerError(w, method, err) 175 return 176 } 177 178 var job = "some-uuid" 179 180 newUUID, err := uuid.NewV4() 181 182 if err != nil { 183 writeServerError(w, method, err) 184 return 185 } 186 187 job = newUUID.String() 188 189 var a entity.Attachment 190 refID := util.UniqueID() 191 a.RefID = refID 192 a.DocumentID = documentID 193 a.Job = job 194 random := util.GenerateSalt() 195 a.FileID = random[0:9] 196 a.Filename = filename.Filename 197 a.Data = b.Bytes() 198 199 tx, err := request.Db.Beginx() 200 201 if err != nil { 202 writeTransactionError(w, method, err) 203 return 204 } 205 206 p.Context.Transaction = tx 207 208 err = p.AddAttachment(a) 209 210 if err != nil { 211 log.IfErr(tx.Rollback()) 212 writeGeneralSQLError(w, method, err) 213 return 214 } 215 216 log.IfErr(tx.Commit()) 217 218 writeSuccessEmptyJSON(w) 219 }