|
|
|
@ -21,27 +21,50 @@ var DB = db.DB
|
|
|
|
|
const (
|
|
|
|
|
//TODO: sync upload status from redis
|
|
|
|
|
// TODO: status is currently handled in cache not here
|
|
|
|
|
DBUploadSchema = `
|
|
|
|
|
CREATE TABLE IF NOT EXISTS upload (
|
|
|
|
|
id serial PRIMARY KEY,
|
|
|
|
|
upload_id varchar(9) NOT NULL,
|
|
|
|
|
//
|
|
|
|
|
// stored: if file was stored
|
|
|
|
|
DBFileUploadsSchema = `
|
|
|
|
|
CREATE TABLE IF NOT EXISTS file_uploads (
|
|
|
|
|
file_upload_id serial PRIMARY KEY,
|
|
|
|
|
upload_id text NOT NULL references uploads(upload_id),
|
|
|
|
|
sha256 varchar(64) NOT NULL,
|
|
|
|
|
file_name varchar(255) NOT NULL,
|
|
|
|
|
file_type varchar(255) DEFAULT '',
|
|
|
|
|
file_size integer NOT NULL,
|
|
|
|
|
file_ext varchar(255) DEFAULT '',
|
|
|
|
|
ask_fee integer NOT NULL DEFAULT 0,
|
|
|
|
|
stored boolean DEFAULT '0',
|
|
|
|
|
stored boolean DEFAULT 'false',
|
|
|
|
|
UNIQUE (upload_id, sha256)
|
|
|
|
|
);
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
QNewUpload = `INSERT INTO upload
|
|
|
|
|
(upload_id, sha256, file_name, file_type, file_size, file_ext, stored, ask_fee)
|
|
|
|
|
VALUES
|
|
|
|
|
(:upload_id, :sha256, :file_name, :file_type, :file_size, :file_ext, :stored, :ask_fee)`
|
|
|
|
|
// Unique entry per upload
|
|
|
|
|
//
|
|
|
|
|
// store: all files for upload where stored
|
|
|
|
|
DBUploadsSchema = `
|
|
|
|
|
CREATE TABLE IF NOT EXISTS uploads (
|
|
|
|
|
upload_id text PRIMARY KEY,
|
|
|
|
|
download_id text DEFAULT '',
|
|
|
|
|
created timestamp,
|
|
|
|
|
ask_fee boolean NOT NULL DEFAULT 'false',
|
|
|
|
|
ask_currency varchar(3) DEFAULT '',
|
|
|
|
|
ask_amount real DEFAULT 0,
|
|
|
|
|
status integer NOT NULL DEFAULT 0,
|
|
|
|
|
settled boolean DEFAULT 'false',
|
|
|
|
|
admin_token text DEFAULT '',
|
|
|
|
|
invoice_rhash varchar(64) references invoices(rhash)
|
|
|
|
|
);
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
DBInvoicesSchema = `
|
|
|
|
|
CREATE TABLE IF NOT EXISTS invoices (
|
|
|
|
|
rhash varchar(64) PRIMARY KEY,
|
|
|
|
|
payload text DEFAULT ''
|
|
|
|
|
);
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
QSetStored = `UPDATE upload SET stored = :stored WHERE upload_id = :upload_id `
|
|
|
|
|
QSetFileStored = `UPDATE file_uploads
|
|
|
|
|
SET stored = :stored
|
|
|
|
|
WHERE upload_id = :upload_id AND sha256 = :sha256`
|
|
|
|
|
|
|
|
|
|
QGetByHashID = `SELECT upload_id,
|
|
|
|
|
sha256,
|
|
|
|
@ -49,9 +72,8 @@ const (
|
|
|
|
|
file_type,
|
|
|
|
|
file_size,
|
|
|
|
|
file_ext,
|
|
|
|
|
ask_fee,
|
|
|
|
|
stored
|
|
|
|
|
FROM upload WHERE sha256 = $1 AND upload_id = $2`
|
|
|
|
|
FROM file_uploads WHERE sha256 = $1 AND upload_id = $2`
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type UpStatus uint32
|
|
|
|
@ -189,16 +211,27 @@ var (
|
|
|
|
|
ErrAlreadyExists = errors.New("already exists")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Upload struct {
|
|
|
|
|
ID string `db:"upload_id"`
|
|
|
|
|
Free bool `db:"-"` // is this a free upload
|
|
|
|
|
type FileUpload struct {
|
|
|
|
|
ID string `db:"file_upload_id"`
|
|
|
|
|
UploadId string `db:"upload_id"`
|
|
|
|
|
SHA256 string `db:"sha256"`
|
|
|
|
|
FileName string `db:"file_name"`
|
|
|
|
|
FileType string `db:"file_type"`
|
|
|
|
|
FileSize int64 `db:"file_size"`
|
|
|
|
|
FileExt string `db:"file_ext"`
|
|
|
|
|
Stored bool `db:"stored"`
|
|
|
|
|
AskFee int `db:"ask_fee"` // fee asked for download
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Upload struct {
|
|
|
|
|
UploadId string `db:"upload_id"`
|
|
|
|
|
DownloadID string `db:"download_id"`
|
|
|
|
|
AskFee bool `db:"ask_fee"`
|
|
|
|
|
AskCurrency string `db:"ask_currency"`
|
|
|
|
|
AskAmount float64 `db:"ask_amount"`
|
|
|
|
|
InvoiceRhash string `db:"invoice_rhash"` // used as id
|
|
|
|
|
Settled bool `db:"settled"`
|
|
|
|
|
UploadStatus uint32 `db:"status"` // upload flag status
|
|
|
|
|
AdminToekn string `db:"admin_token"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: sync from redis to db
|
|
|
|
@ -206,6 +239,41 @@ type Upload struct {
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
func GetDownloadId(uploadId string) (string, error) {
|
|
|
|
|
key := fmt.Sprintf("download_for_upload_%s", uploadId)
|
|
|
|
|
|
|
|
|
|
// Try redis
|
|
|
|
|
var downloadId string
|
|
|
|
|
|
|
|
|
|
var exists bool
|
|
|
|
|
|
|
|
|
|
// Check if exists
|
|
|
|
|
err := DB.Redis.Do(radix.FlatCmd(&exists, "EXISTS", key))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if !exists get from sql and store in redis
|
|
|
|
|
if !exists {
|
|
|
|
|
log.Printf("download id not found for %s, trying form db")
|
|
|
|
|
query := `SELECT download_id from uploads WHERE upload_id = $1`
|
|
|
|
|
err = DB.Sql.Get(&downloadId, query)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(downloadId) == 0 {
|
|
|
|
|
return "", fmt.Errorf("download id missing in %s", uploadId)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Store it back on redis cache
|
|
|
|
|
err = DB.Redis.Do(radix.FlatCmd(nil, "SET", key, downloadId))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return downloadId, err
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetUploadInvoice(uploadId string) (*ln.Invoice, error) {
|
|
|
|
|
var invoice ln.Invoice
|
|
|
|
|
|
|
|
|
@ -247,7 +315,12 @@ func SetUploadStatus(id string, status UpStatus) error {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Println("done set bit")
|
|
|
|
|
// Store on sql db
|
|
|
|
|
query := `UPDATE uploads SET status = $1 WHERE upload_id = $2`
|
|
|
|
|
_, err := DB.Sql.Exec(query, uint32(status), id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
@ -264,7 +337,14 @@ func GetUploadStatus(id string) (status UpStatus, err error) {
|
|
|
|
|
|
|
|
|
|
func SetUploadAdminToken(uploadId, token string) error {
|
|
|
|
|
key := fmt.Sprintf("upload_admin_%s", uploadId)
|
|
|
|
|
return DB.Redis.Do(radix.FlatCmd(nil, "SET", key, token))
|
|
|
|
|
err := DB.Redis.Do(radix.FlatCmd(nil, "SET", key, token))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
query := `UPDATE uploads SET admin_token = $1 WHERE upload_id = $2`
|
|
|
|
|
_, err = DB.Sql.Exec(query, token, uploadId)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetUploadAdminToken(uploadId string) (string, error) {
|
|
|
|
@ -272,7 +352,6 @@ func GetUploadAdminToken(uploadId string) (string, error) {
|
|
|
|
|
key := fmt.Sprintf("upload_admin_%s", uploadId)
|
|
|
|
|
err := DB.Redis.Do(radix.FlatCmd(&token, "GET", key))
|
|
|
|
|
return token, err
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SetUploadInvoice(uploadId string, invoice *ln.Invoice) error {
|
|
|
|
@ -290,7 +369,35 @@ func SetUploadInvoice(uploadId string, invoice *ln.Invoice) error {
|
|
|
|
|
|
|
|
|
|
// Set inverse relation
|
|
|
|
|
invoiceUploadKey := fmt.Sprintf("invoice_%s_upload", invoice.RHash)
|
|
|
|
|
return DB.Redis.Do(radix.FlatCmd(nil, "SET", invoiceUploadKey, uploadId))
|
|
|
|
|
err = DB.Redis.Do(radix.FlatCmd(nil, "SET", invoiceUploadKey, uploadId))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SQL insert
|
|
|
|
|
tx, err := DB.Sql.Beginx()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add invoice to invoices table
|
|
|
|
|
query := `INSERT INTO invoices(rhash, payload)
|
|
|
|
|
VALUES($1,$2)
|
|
|
|
|
ON CONFLICT DO NOTHING
|
|
|
|
|
`
|
|
|
|
|
_, err = tx.Exec(query, invoice.RHash, invoiceJson)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set invoice to upload
|
|
|
|
|
query = `UPDATE uploads SET invoice_rhash = $1 WHERE upload_id = $2`
|
|
|
|
|
_, err = tx.Exec(query, invoice.RHash, uploadId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tx.Commit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetUploadIdForInvoice(invoiceId string) (string, error) {
|
|
|
|
@ -309,8 +416,8 @@ func IdExists(id string) (exists bool, err error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get a file by upload id and hash
|
|
|
|
|
func GetByHashID(sha256 string, id string) (*Upload, error) {
|
|
|
|
|
var up Upload
|
|
|
|
|
func GetByHashID(sha256 string, id string) (*FileUpload, error) {
|
|
|
|
|
var up FileUpload
|
|
|
|
|
|
|
|
|
|
err := DB.Sql.Get(&up, QGetByHashID, sha256, id)
|
|
|
|
|
|
|
|
|
@ -325,9 +432,32 @@ func GetByHashID(sha256 string, id string) (*Upload, error) {
|
|
|
|
|
return &up, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Upload) TxSetFileStored(tx *sqlx.Tx) error {
|
|
|
|
|
func (u *FileUpload) TxSetFileStored(tx *sqlx.Tx) error {
|
|
|
|
|
u.Stored = true
|
|
|
|
|
_, err := tx.NamedExec(QSetStored, u)
|
|
|
|
|
_, err := tx.NamedExec(QSetFileStored, u)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *FileUpload) TxWrite(tx *sqlx.Tx) error {
|
|
|
|
|
query := `INSERT INTO file_uploads
|
|
|
|
|
(upload_id, sha256, file_name, file_type, file_size, file_ext)
|
|
|
|
|
VALUES
|
|
|
|
|
(:upload_id, :sha256, :file_name, :file_type, :file_size, :file_ext)
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
_, err := tx.NamedExec(query, u)
|
|
|
|
|
|
|
|
|
|
if pqError, ok := err.(*pq.Error); ok {
|
|
|
|
|
// unique constraint
|
|
|
|
|
if pqError.Code == "23505" {
|
|
|
|
|
return ErrAlreadyExists
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
@ -337,8 +467,12 @@ func (u *Upload) TxSetFileStored(tx *sqlx.Tx) error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Upload) TxWrite(tx *sqlx.Tx) error {
|
|
|
|
|
query := `INSERT INTO uploads
|
|
|
|
|
(upload_id, download_id, ask_fee, ask_currency, settled)
|
|
|
|
|
VALUES
|
|
|
|
|
(:upload_id, :download_id, :ask_fee, :ask_currency, :settled)`
|
|
|
|
|
|
|
|
|
|
_, err := tx.NamedExec(QNewUpload, u)
|
|
|
|
|
_, err := tx.NamedExec(query, u)
|
|
|
|
|
|
|
|
|
|
if pqError, ok := err.(*pq.Error); ok {
|
|
|
|
|
// unique constraint
|
|
|
|
@ -355,7 +489,11 @@ func (u *Upload) TxWrite(tx *sqlx.Tx) error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Upload) Write() error {
|
|
|
|
|
_, err := DB.Sql.NamedExec(QNewUpload, u)
|
|
|
|
|
query := `INSERT INTO uploads
|
|
|
|
|
(upload_id, download_id, ask_fee, ask_currency, settled)
|
|
|
|
|
VALUES
|
|
|
|
|
(:upload_id, :download_id, :ask_fee, :ask_currency, :settled)`
|
|
|
|
|
_, err := DB.Sql.NamedExec(query, u)
|
|
|
|
|
|
|
|
|
|
if pqError, ok := err.(*pq.Error); ok {
|
|
|
|
|
// unique constraint
|
|
|
|
@ -372,8 +510,19 @@ func (u *Upload) Write() error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
_, err := DB.Sql.Exec(DBUploadSchema)
|
|
|
|
|
_, err := DB.Sql.Exec(DBInvoicesSchema)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err = DB.Sql.Exec(DBUploadsSchema)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err = DB.Sql.Exec(DBFileUploadsSchema)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|