2019-04-06 01:45:50 +00:00
|
|
|
package api
|
2019-03-15 18:00:35 +00:00
|
|
|
|
|
|
|
import (
|
2019-03-21 17:44:40 +00:00
|
|
|
"crypto/sha256"
|
|
|
|
"encoding/hex"
|
2019-03-15 18:00:35 +00:00
|
|
|
"fmt"
|
2019-03-21 17:44:40 +00:00
|
|
|
"io"
|
|
|
|
"log"
|
2019-03-15 18:00:35 +00:00
|
|
|
"net/http"
|
2019-03-21 17:44:40 +00:00
|
|
|
"os"
|
2019-03-15 18:00:35 +00:00
|
|
|
|
2019-03-23 18:29:48 +00:00
|
|
|
"git.sp4ke.com/sp4ke/bit4sat/db"
|
2019-03-26 21:01:54 +00:00
|
|
|
"git.sp4ke.com/sp4ke/bit4sat/ln"
|
2019-04-06 01:45:50 +00:00
|
|
|
"git.sp4ke.com/sp4ke/bit4sat/storage"
|
2019-03-23 18:29:48 +00:00
|
|
|
"git.sp4ke.com/sp4ke/bit4sat/utils"
|
2019-03-15 18:00:35 +00:00
|
|
|
"github.com/gin-gonic/gin"
|
2019-04-02 13:53:52 +00:00
|
|
|
)
|
|
|
|
|
2019-03-15 18:00:35 +00:00
|
|
|
type UploadCtrl struct{}
|
|
|
|
|
2019-03-29 12:10:06 +00:00
|
|
|
//TODO: tell client to avoid sending duplicate if we already have hash
|
2019-03-15 18:00:35 +00:00
|
|
|
func (ctrl UploadCtrl) New(c *gin.Context) {
|
|
|
|
uploadForm := UploadForm{}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&uploadForm); err != nil {
|
2019-04-05 16:18:44 +00:00
|
|
|
log.Printf("error parsing form: %s", err)
|
2019-03-21 17:44:40 +00:00
|
|
|
utils.JSONErr(c, http.StatusNotAcceptable,
|
2019-04-05 16:18:44 +00:00
|
|
|
"invalid form")
|
2019-03-19 21:14:38 +00:00
|
|
|
return
|
2019-03-15 18:00:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create unique id
|
2019-04-06 01:45:50 +00:00
|
|
|
uploadId, err := storage.GetShortId()
|
2019-03-29 12:10:06 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
2019-03-15 18:00:35 +00:00
|
|
|
|
2019-03-23 18:29:48 +00:00
|
|
|
tx, err := db.DB.Sql.Beginx()
|
2019-03-21 17:44:40 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-05 16:18:44 +00:00
|
|
|
if uploadForm.RequestPayment {
|
|
|
|
if _, ok := ln.CurrencyID[uploadForm.PaymentCurrency]; !ok {
|
|
|
|
utils.JSONErr(c, http.StatusInternalServerError,
|
|
|
|
"currency not handled or recognized")
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new upload
|
2019-04-06 01:45:50 +00:00
|
|
|
up := &storage.Upload{}
|
2019-04-05 16:18:44 +00:00
|
|
|
up.UploadId = uploadId
|
|
|
|
up.AskFee = uploadForm.RequestPayment
|
|
|
|
up.AskCurrency = uploadForm.PaymentCurrency
|
|
|
|
up.AskAmount = uploadForm.RequestPaymentAmount
|
|
|
|
|
|
|
|
// Generate unique download id
|
|
|
|
//
|
2019-04-06 01:45:50 +00:00
|
|
|
dlId, err := storage.GetShortId()
|
2019-04-05 16:18:44 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
up.DownloadID = dlId
|
|
|
|
|
|
|
|
err = up.TxWrite(tx)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
db.RollbackTx(tx, nil)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-03-20 18:39:38 +00:00
|
|
|
for _, file := range uploadForm.Files {
|
2019-04-06 01:45:50 +00:00
|
|
|
fup := &storage.FileUpload{}
|
2019-04-05 16:18:44 +00:00
|
|
|
fup.UploadId = uploadId
|
2019-03-20 18:39:38 +00:00
|
|
|
|
2019-04-05 16:18:44 +00:00
|
|
|
fup.FileName, fup.FileExt = utils.CleanFileName(file.Name)
|
2019-03-20 18:39:38 +00:00
|
|
|
|
2019-04-05 16:18:44 +00:00
|
|
|
fup.FileSize = file.Size
|
|
|
|
fup.FileType = file.Type
|
|
|
|
fup.SHA256 = file.SHA256
|
2019-03-20 18:39:38 +00:00
|
|
|
|
2019-04-05 16:18:44 +00:00
|
|
|
err := fup.TxWrite(tx)
|
2019-03-20 18:39:38 +00:00
|
|
|
if err != nil {
|
2019-03-21 17:44:40 +00:00
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
db.RollbackTx(tx, nil)
|
2019-03-20 18:39:38 +00:00
|
|
|
return
|
|
|
|
}
|
2019-03-15 18:00:35 +00:00
|
|
|
}
|
|
|
|
|
2019-03-21 17:44:40 +00:00
|
|
|
err = tx.Commit()
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// Set upload status to new
|
2019-04-06 01:45:50 +00:00
|
|
|
err = storage.SetUploadStatus(uploadId, storage.UpNew)
|
2019-04-02 13:53:52 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
2019-03-31 20:53:53 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// Upload seems valid, handle new upload procedure
|
2019-04-06 01:45:50 +00:00
|
|
|
//
|
|
|
|
// Get the upload session
|
|
|
|
upSession, err := SessionStore.Get(c.Request, UpSessionKey)
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
2019-03-31 20:53:53 +00:00
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// Set the uploadId as last upload for session
|
2019-04-06 01:45:50 +00:00
|
|
|
upSession.AddFlash(uploadId)
|
|
|
|
|
|
|
|
err = upSession.Save(c.Request, c.Writer)
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
2019-03-31 20:53:53 +00:00
|
|
|
|
2019-03-29 18:50:11 +00:00
|
|
|
// If not free upload generate a an invoice
|
|
|
|
// TODO: check if upload fee is free
|
2019-04-05 16:18:44 +00:00
|
|
|
if uploadForm.RequestPayment {
|
2019-04-01 10:12:29 +00:00
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
invoiceOpts := ln.InvoiceOpts{
|
|
|
|
Amount: uploadForm.RequestPaymentAmount,
|
|
|
|
Curr: ln.CurrencyID[uploadForm.PaymentCurrency],
|
|
|
|
Memo: fmt.Sprintf("bit4sat upload: %s", uploadId),
|
|
|
|
}
|
|
|
|
invoice, err := ln.NewInvoice(invoiceOpts)
|
2019-04-04 00:27:09 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-01 10:12:29 +00:00
|
|
|
// Update Upload Invoice
|
2019-04-06 01:45:50 +00:00
|
|
|
err = storage.SetUploadInvoice(uploadId, invoice)
|
2019-03-29 18:50:11 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
2019-04-01 10:12:29 +00:00
|
|
|
|
2019-03-29 18:50:11 +00:00
|
|
|
}
|
|
|
|
|
2019-03-31 20:53:53 +00:00
|
|
|
// Start watching upload payment status for this client
|
|
|
|
|
2019-04-01 10:12:29 +00:00
|
|
|
//err = WatchUploadPayment(invoice)
|
|
|
|
//if err != nil {
|
|
|
|
//log.Println("error watching payment ", err)
|
|
|
|
//utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
//return
|
|
|
|
//}
|
2019-03-29 18:50:11 +00:00
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2019-04-06 01:45:50 +00:00
|
|
|
"status": storage.UpNew,
|
2019-04-02 13:53:52 +00:00
|
|
|
"invoice": invoice,
|
|
|
|
"upload_id": uploadId,
|
2019-03-29 18:50:11 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
2019-04-01 10:12:29 +00:00
|
|
|
// Handle free uploads
|
2019-03-29 18:50:11 +00:00
|
|
|
} else {
|
|
|
|
|
|
|
|
log.Println("new upload created")
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
"status": "ready for upload",
|
|
|
|
"result": gin.H{
|
|
|
|
"id": uploadId,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
2019-04-02 13:53:52 +00:00
|
|
|
}
|
2019-03-29 18:50:11 +00:00
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
func (ctrl UploadCtrl) CheckStatus(c *gin.Context) {
|
|
|
|
uploadId := c.Param("id")
|
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
exists, err := storage.IdExists(uploadId)
|
2019-04-02 13:53:52 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 17:40:25 +00:00
|
|
|
if !exists {
|
|
|
|
utils.JSONErr(c, http.StatusNotFound, "upload id not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get upload status
|
2019-04-06 01:45:50 +00:00
|
|
|
uploadStatus, err := storage.GetUploadStatus(uploadId)
|
2019-04-02 17:40:25 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if uploadStatus.IsNew() {
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
"status": uploadStatus,
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get invoice id for upload
|
2019-04-06 01:45:50 +00:00
|
|
|
invoiceId, err := storage.GetUploadIdInvoiceId(uploadId)
|
2019-04-02 17:40:25 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-04 18:26:43 +00:00
|
|
|
// No invoice found
|
|
|
|
if invoiceId == "" {
|
|
|
|
utils.JSONErr(c, http.StatusNotFound, "no invoice found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 17:40:25 +00:00
|
|
|
// Get invoice
|
|
|
|
invoice, err := ln.CheckInvoice(invoiceId)
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
c.JSON(ln.InvoiceHttpCode(invoice), gin.H{
|
2019-04-02 17:40:25 +00:00
|
|
|
"upload_id": uploadId,
|
|
|
|
"invoice": invoice,
|
|
|
|
"status": uploadStatus,
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctrl UploadCtrl) PollStatus(c *gin.Context) {
|
|
|
|
uploadId := c.Param("id")
|
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
exists, err := storage.IdExists(uploadId)
|
2019-04-02 17:40:25 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
if !exists {
|
|
|
|
utils.JSONErr(c, http.StatusNotFound, "id not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
uploadStatus, err := storage.GetUploadStatus(uploadId)
|
2019-04-02 13:53:52 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
if uploadStatus&storage.UpNew != 0 {
|
2019-04-02 13:53:52 +00:00
|
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
|
|
"status": uploadStatus,
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 17:40:25 +00:00
|
|
|
// we are not in UpNew state so we should have an invoice
|
2019-04-06 01:45:50 +00:00
|
|
|
invoice, err := storage.GetUploadInvoice(uploadId)
|
2019-04-02 17:40:25 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
2019-04-02 13:53:52 +00:00
|
|
|
|
2019-04-04 18:26:43 +00:00
|
|
|
if invoice == nil {
|
|
|
|
utils.JSONErr(c, http.StatusInternalServerError, "no invoice found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 17:40:25 +00:00
|
|
|
if uploadStatus.WaitPay() {
|
2019-04-02 13:53:52 +00:00
|
|
|
|
|
|
|
invoiceChan := make(chan *ln.Invoice)
|
|
|
|
errorChan := make(chan error)
|
|
|
|
|
2019-04-03 22:12:03 +00:00
|
|
|
log.Printf("starting invoice poll for %s", invoice.RHash)
|
2019-04-02 13:53:52 +00:00
|
|
|
// If waiting payment, wait until invoice is paid
|
2019-04-03 18:18:51 +00:00
|
|
|
go ln.PollPaidInvoice(invoice.RHash, invoiceChan, errorChan)
|
2019-04-02 13:53:52 +00:00
|
|
|
|
|
|
|
// Block until payment done or error
|
|
|
|
log.Println("blocking")
|
|
|
|
select {
|
2019-04-05 18:14:23 +00:00
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
case invoice := <-invoiceChan:
|
2019-04-04 18:26:43 +00:00
|
|
|
log.Printf("poll: received invoice notif %s", invoice.RHash)
|
2019-04-02 17:40:25 +00:00
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// if expired return with expired response
|
|
|
|
if invoice.Expired {
|
2019-04-06 01:45:50 +00:00
|
|
|
err := storage.SetUploadStatus(uploadId, storage.UpPayExpired)
|
2019-04-02 13:53:52 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("Redis error: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusGone, gin.H{
|
|
|
|
"status": uploadStatus,
|
|
|
|
"invoice": invoice,
|
|
|
|
})
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////
|
|
|
|
///// Invoice was paid
|
|
|
|
////////////////
|
2019-04-04 18:26:43 +00:00
|
|
|
//
|
|
|
|
log.Println("POLL: invoice was paid")
|
2019-04-02 13:53:52 +00:00
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
uploadStatus |= storage.UpPaid
|
|
|
|
err := storage.SetUploadStatus(uploadId, uploadStatus)
|
2019-04-02 13:53:52 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("Redis error: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update Upload Invoice
|
2019-04-06 01:45:50 +00:00
|
|
|
err = storage.SetUploadInvoice(uploadId, invoice)
|
2019-04-02 13:53:52 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-05 16:18:44 +00:00
|
|
|
// Generate admin token and save it
|
2019-04-06 01:45:50 +00:00
|
|
|
adminToken, err := storage.GetLongId()
|
2019-04-05 16:18:44 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
err = storage.SetUploadAdminToken(uploadId, adminToken)
|
2019-04-05 16:18:44 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the download id
|
2019-04-06 01:45:50 +00:00
|
|
|
dlId, err := storage.GetDownloadId(uploadId)
|
2019-04-04 00:27:09 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear the session
|
2019-04-06 01:45:50 +00:00
|
|
|
upSession, err := SessionStore.Get(c.Request, UpSessionKey)
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
upSession.Flashes()
|
|
|
|
err = upSession.Save(c.Request, c.Writer)
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
2019-04-04 00:27:09 +00:00
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// invoice was paid
|
|
|
|
c.JSON(http.StatusAccepted, gin.H{
|
2019-04-04 00:27:09 +00:00
|
|
|
"status": uploadStatus,
|
|
|
|
"invoice": invoice,
|
2019-04-05 16:18:44 +00:00
|
|
|
"admin_token": adminToken,
|
|
|
|
"download_id": dlId,
|
2019-04-02 13:53:52 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
case err := <-errorChan:
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2019-04-02 17:40:25 +00:00
|
|
|
"status": uploadStatus,
|
|
|
|
"invoice": invoice,
|
2019-04-02 13:53:52 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2019-03-15 18:00:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ctrl UploadCtrl) Upload(c *gin.Context) {
|
|
|
|
|
2019-03-21 17:44:40 +00:00
|
|
|
// Check that upload ID exists
|
2019-03-29 18:50:11 +00:00
|
|
|
uploadId := c.Param("id")
|
2019-03-21 17:44:40 +00:00
|
|
|
|
2019-04-06 01:45:50 +00:00
|
|
|
exists, err := storage.IdExists(uploadId)
|
2019-03-21 17:44:40 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !exists {
|
|
|
|
utils.JSONErr(c, http.StatusNotFound, "id not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// Check if payment done
|
|
|
|
// NOTE: we pre upload and remove the files if the payment was expired
|
|
|
|
//uploadStatus, err := GetUploadStatus(uploadId)
|
|
|
|
//if err != nil {
|
|
|
|
//utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
//return
|
|
|
|
//}
|
|
|
|
|
|
|
|
//if uploadStatus < UpWaitingStorage {
|
|
|
|
|
|
|
|
//utils.JSONErr(c, http.StatusPaymentRequired,
|
|
|
|
//fmt.Sprintf("invoice not paid"))
|
|
|
|
//return
|
|
|
|
//}
|
|
|
|
|
2019-03-15 18:00:35 +00:00
|
|
|
form, err := c.MultipartForm()
|
|
|
|
if err != nil {
|
2019-03-21 17:44:40 +00:00
|
|
|
utils.JSONErr(c, http.StatusNotAcceptable,
|
|
|
|
fmt.Sprintf("Could not parse form: %s", err.Error()))
|
2019-03-15 18:00:35 +00:00
|
|
|
return
|
|
|
|
}
|
2019-03-21 17:44:40 +00:00
|
|
|
|
2019-03-15 18:00:35 +00:00
|
|
|
files := form.File["upload[]"]
|
|
|
|
|
2019-03-23 18:29:48 +00:00
|
|
|
tx, err := db.DB.Sql.Beginx()
|
2019-03-21 17:44:40 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-03-15 18:00:35 +00:00
|
|
|
for _, file := range files {
|
2019-03-21 17:44:40 +00:00
|
|
|
log.Printf("Handling %s", file.Filename)
|
|
|
|
|
|
|
|
// Get the file's sha256
|
|
|
|
hasher := sha256.New()
|
|
|
|
|
|
|
|
formFd, err := file.Open()
|
|
|
|
defer formFd.Close()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErr(
|
|
|
|
c, http.StatusInternalServerError,
|
|
|
|
fmt.Sprintf("Could not read file %s", file.Filename),
|
|
|
|
)
|
|
|
|
db.RollbackTx(tx, nil)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = io.Copy(hasher, formFd)
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErr(c, http.StatusInternalServerError,
|
|
|
|
"")
|
|
|
|
db.RollbackTx(tx, nil)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
sum256 := hex.EncodeToString(hasher.Sum(nil))
|
|
|
|
|
|
|
|
// Get the file's metadata from upload table
|
2019-04-06 01:45:50 +00:00
|
|
|
up, err := storage.GetByHashID(sum256, uploadId)
|
2019-03-21 17:44:40 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusNotFound, err)
|
|
|
|
db.RollbackTx(tx, nil)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Found received file's %s metadata in local database\n", up.FileName)
|
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// If file already stored for this upload report conflict
|
|
|
|
if up.Stored {
|
2019-03-21 17:44:40 +00:00
|
|
|
utils.JSONErr(c, http.StatusConflict,
|
|
|
|
fmt.Sprintf("%s already uploaded", up.FileName))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
//
|
|
|
|
//
|
|
|
|
log.Println("Storing file")
|
2019-04-06 01:45:50 +00:00
|
|
|
err = storage.StoreFormFile(formFd, up.SHA256+up.FileExt)
|
2019-03-21 17:44:40 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
db.RollbackTx(tx, nil)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("%s stored at %s", up.FileName,
|
2019-04-06 01:45:50 +00:00
|
|
|
storage.GetStoreDestination(up.SHA256+up.FileExt))
|
2019-03-21 17:44:40 +00:00
|
|
|
|
|
|
|
// Setting status to stored
|
2019-04-02 13:53:52 +00:00
|
|
|
log.Println("Updating file upload stored status")
|
|
|
|
|
|
|
|
err = up.TxSetFileStored(tx)
|
2019-03-21 17:44:40 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
2019-04-02 13:53:52 +00:00
|
|
|
|
|
|
|
// Rollback and remove the file
|
2019-03-21 17:44:40 +00:00
|
|
|
db.RollbackTx(tx, func() {
|
2019-04-06 01:45:50 +00:00
|
|
|
err := os.Remove(storage.GetStoreDestination(up.SHA256 + up.FileExt))
|
2019-03-21 17:44:40 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = tx.Commit()
|
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
2019-03-15 18:00:35 +00:00
|
|
|
}
|
|
|
|
|
2019-04-02 13:53:52 +00:00
|
|
|
// Set the whole transaction as stored
|
2019-04-06 01:45:50 +00:00
|
|
|
err = storage.SetUploadStatus(uploadId, storage.UpStored)
|
2019-03-26 16:03:13 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-03-15 18:00:35 +00:00
|
|
|
c.JSON(http.StatusOK, gin.H{
|
2019-04-02 13:53:52 +00:00
|
|
|
"status": http.StatusOK,
|
2019-04-06 01:45:50 +00:00
|
|
|
"store_status": storage.UpStored,
|
2019-04-04 00:27:09 +00:00
|
|
|
"upload_id": uploadId,
|
2019-03-15 18:00:35 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
}
|