github.com/jancarloviray/community@v0.41.1-0.20170124221257-33a66c87cf2f/core/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/core/api/entity" 24 "github.com/documize/community/core/api/request" 25 "github.com/documize/community/core/api/util" 26 "github.com/documize/community/core/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.GetAttachment(params["orgID"], params["attachmentID"]) 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 if len(a) == 0 { 95 a = []entity.Attachment{} 96 } 97 98 json, err := json.Marshal(a) 99 100 if err != nil { 101 writeJSONMarshalError(w, method, "attachments", err) 102 return 103 } 104 105 writeSuccessBytes(w, json) 106 } 107 108 // DeleteAttachment is an endpoint that deletes a particular document attachment. 109 func DeleteAttachment(w http.ResponseWriter, r *http.Request) { 110 method := "DeleteAttachment" 111 p := request.GetPersister(r) 112 113 params := mux.Vars(r) 114 documentID := params["documentID"] 115 attachmentID := params["attachmentID"] 116 117 if len(documentID) == 0 || len(attachmentID) == 0 { 118 writeMissingDataError(w, method, "documentID, attachmentID") 119 return 120 } 121 122 if !p.CanChangeDocument(documentID) { 123 writeForbiddenError(w) 124 return 125 } 126 127 tx, err := request.Db.Beginx() 128 129 if err != nil { 130 writeTransactionError(w, method, err) 131 return 132 } 133 134 p.Context.Transaction = tx 135 136 _, err = p.DeleteAttachment(attachmentID) 137 138 if err != nil { 139 log.IfErr(tx.Rollback()) 140 writeGeneralSQLError(w, method, err) 141 return 142 } 143 144 log.IfErr(tx.Commit()) 145 146 writeSuccessEmptyJSON(w) 147 } 148 149 // AddAttachments stores files against a document. 150 func AddAttachments(w http.ResponseWriter, r *http.Request) { 151 method := "AddAttachments" 152 p := request.GetPersister(r) 153 154 params := mux.Vars(r) 155 documentID := params["documentID"] 156 157 if len(documentID) == 0 { 158 writeMissingDataError(w, method, "documentID") 159 return 160 } 161 162 if !p.CanChangeDocument(documentID) { 163 w.WriteHeader(http.StatusForbidden) 164 return 165 } 166 167 filedata, filename, err := r.FormFile("attachment") 168 169 if err != nil { 170 writeMissingDataError(w, method, "attachment") 171 return 172 } 173 174 b := new(bytes.Buffer) 175 _, err = io.Copy(b, filedata) 176 177 if err != nil { 178 writeServerError(w, method, err) 179 return 180 } 181 182 var job = "some-uuid" 183 184 newUUID, err := uuid.NewV4() 185 186 if err != nil { 187 writeServerError(w, method, err) 188 return 189 } 190 191 job = newUUID.String() 192 193 var a entity.Attachment 194 refID := util.UniqueID() 195 a.RefID = refID 196 a.DocumentID = documentID 197 a.Job = job 198 random := util.GenerateSalt() 199 a.FileID = random[0:9] 200 a.Filename = filename.Filename 201 a.Data = b.Bytes() 202 203 tx, err := request.Db.Beginx() 204 205 if err != nil { 206 writeTransactionError(w, method, err) 207 return 208 } 209 210 p.Context.Transaction = tx 211 212 err = p.AddAttachment(a) 213 214 if err != nil { 215 log.IfErr(tx.Rollback()) 216 writeGeneralSQLError(w, method, err) 217 return 218 } 219 220 log.IfErr(tx.Commit()) 221 222 writeSuccessEmptyJSON(w) 223 }