initial
commit
e449299304
@ -0,0 +1,14 @@
|
||||
|
||||
TARGET := bit4sat
|
||||
GOINSTALL := GO111MODULE=on go install -v
|
||||
GOBUILD := GO111MODULE=on go build -v
|
||||
|
||||
.PHONY: all build install
|
||||
|
||||
all: build
|
||||
|
||||
build:
|
||||
$(GOBUILD) -o $(TARGET)
|
||||
|
||||
install:
|
||||
$(GOINSTALL)
|
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.sp4ke.com/sp4ke/bit4sat-server.git/storage"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
UploadCtrl = storage.UploadCtrl{}
|
||||
)
|
||||
|
||||
type API struct {
|
||||
router *gin.Engine
|
||||
}
|
||||
|
||||
func (api *API) Run() {
|
||||
|
||||
uploadRoute := api.router.Group("/upload")
|
||||
{
|
||||
|
||||
uploadRoute.POST("/", UploadCtrl.New)
|
||||
uploadRoute.PUT("/:id", UploadCtrl.Upload)
|
||||
|
||||
}
|
||||
|
||||
api.router.Run(":8880")
|
||||
}
|
||||
|
||||
func NewAPI() *API {
|
||||
return &API{
|
||||
router: gin.Default(),
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"git.sp4ke.com/sp4ke/bit4sat-server.git/utils"
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
const (
|
||||
DBName = "bit4sat.sqlite"
|
||||
DBPath = "db-storage"
|
||||
DBPathEnv = "BIT4SAT_DB_PATH"
|
||||
DBPragma = ` PRAGMA foreign_keys = ON; `
|
||||
)
|
||||
|
||||
var (
|
||||
DBOptions = map[string]string{
|
||||
"_journal_mode": "WAL",
|
||||
}
|
||||
|
||||
DB *Database
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
Handle *sqlx.DB
|
||||
}
|
||||
|
||||
func (d *Database) Open() error {
|
||||
|
||||
dsnOptions := &url.Values{}
|
||||
for k, v := range DBOptions {
|
||||
dsnOptions.Set(k, v)
|
||||
}
|
||||
|
||||
// Get db base path
|
||||
path, set := os.LookupEnv(DBPathEnv)
|
||||
if !set {
|
||||
path = DBPath
|
||||
}
|
||||
|
||||
// Create path if not exists
|
||||
err := utils.Mkdir(path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
path = filepath.Join(path, DBName)
|
||||
//path = fmt.Sprintf("%s/%s", path, DBName)
|
||||
|
||||
dsn := fmt.Sprintf("file:%s?%s", path, dsnOptions.Encode())
|
||||
|
||||
log.Printf("Opening sqlite db %s\n", dsn)
|
||||
|
||||
d.Handle, err = sqlx.Open("sqlite3", dsn)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Execute Pragmas
|
||||
d.Handle.MustExec(DBPragma)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
DB = &Database{}
|
||||
DB.Open()
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
module git.sp4ke.com/sp4ke/bit4sat-server.git
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 // indirect
|
||||
github.com/gin-gonic/gin v1.3.0
|
||||
github.com/golang/protobuf v1.3.1 // indirect
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/mattn/go-isatty v0.0.7 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.10.0
|
||||
github.com/segmentio/ksuid v1.0.2
|
||||
github.com/ugorji/go/codec v0.0.0-20190315113641-a70535d8491c // indirect
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||
)
|
@ -0,0 +1,28 @@
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g=
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||
github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs=
|
||||
github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/segmentio/ksuid v1.0.2 h1:9yBfKyw4ECGTdALaF09Snw3sLJmYIX6AbPJrAy6MrDc=
|
||||
github.com/segmentio/ksuid v1.0.2/go.mod h1:BXuJDr2byAiHuQaQtSKoXh1J0YmUDurywOXgB2w+OSU=
|
||||
github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs=
|
||||
github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/ugorji/go/codec v0.0.0-20190315113641-a70535d8491c h1:20Yyqg0mvFOyG3m7ejVqHEa03CBa3hTttx9jiYLkjYU=
|
||||
github.com/ugorji/go/codec v0.0.0-20190315113641-a70535d8491c/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "git.sp4ke.com/sp4ke/bit4sat-server.git/db"
|
||||
|
||||
func main() {
|
||||
defer db.DB.Handle.Close()
|
||||
api := NewAPI()
|
||||
|
||||
api.Run()
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"git.sp4ke.com/sp4ke/bit4sat-server.git/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
StoragePath = "storage"
|
||||
StoragePathEnv = "BIT4SAT_STORAGE_PATH"
|
||||
)
|
||||
|
||||
func init() {
|
||||
path, set := os.LookupEnv(StoragePathEnv)
|
||||
if !set {
|
||||
path = StoragePath
|
||||
}
|
||||
|
||||
err := utils.Mkdir(path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/segmentio/ksuid"
|
||||
)
|
||||
|
||||
type UploadCtrl struct{}
|
||||
|
||||
func (ctrl UploadCtrl) New(c *gin.Context) {
|
||||
uploadForm := UploadForm{}
|
||||
up := &Upload{}
|
||||
|
||||
if err := c.ShouldBindJSON(&uploadForm); err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"status": http.StatusNotAcceptable,
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
|
||||
// Create unique id
|
||||
id := ksuid.New()
|
||||
up.ID = id.String()
|
||||
|
||||
// Save new upload
|
||||
err := up.Write()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"status": http.StatusInternalServerError,
|
||||
"error": "could not start new upload",
|
||||
"msg": err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"status": http.StatusOK,
|
||||
"result": gin.H{
|
||||
"id": up.ID,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (ctrl UploadCtrl) Upload(c *gin.Context) {
|
||||
|
||||
form, err := c.MultipartForm()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"status": http.StatusNotAcceptable,
|
||||
"error": err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
files := form.File["upload[]"]
|
||||
|
||||
for _, file := range files {
|
||||
fmt.Println(file.Filename)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"status": http.StatusOK,
|
||||
"result": fmt.Sprintf("%d files uploaded uploaded !", len(files)),
|
||||
})
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package storage
|
||||
|
||||
import "time"
|
||||
|
||||
type File struct {
|
||||
Name string
|
||||
SHA256 string
|
||||
Size int64
|
||||
}
|
||||
|
||||
type UploadForm struct {
|
||||
Files []File `form:"files" binding:"required"`
|
||||
|
||||
// Default time.RFC3339
|
||||
TimeStamp time.Time `form:"timestamp"`
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"git.sp4ke.com/sp4ke/bit4sat-server.git/db"
|
||||
"github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
var DB = db.DB
|
||||
|
||||
const (
|
||||
DBUploadSchema = `
|
||||
CREATE TABLE IF NOT EXISTS "upload" (
|
||||
"upload_id" TEXT NOT NULL,
|
||||
"path" TEXT DEFAULT '',
|
||||
PRIMARY KEY("upload_id")
|
||||
);
|
||||
`
|
||||
|
||||
QNewUpload = `INSERT INTO upload (upload_id) VALUES (:upload_id)`
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDoesNotExist = errors.New("does not exist")
|
||||
ErrAlreadyExists = errors.New("already exists")
|
||||
)
|
||||
|
||||
type Upload struct {
|
||||
ID string `db:"upload_id"`
|
||||
Path string
|
||||
}
|
||||
|
||||
func (u *Upload) Write() error {
|
||||
_, err := DB.Handle.NamedExec(QNewUpload, u)
|
||||
sqlErr, isSqlErr := err.(sqlite3.Error)
|
||||
if isSqlErr && sqlErr.Code == sqlite3.ErrConstraint {
|
||||
return ErrAlreadyExists
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
_, err := DB.Handle.Exec(DBUploadSchema)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
MkdirMode = 0770
|
||||
)
|
||||
|
||||
func Mkdir(path ...string) error {
|
||||
joined := filepath.Join(path...)
|
||||
|
||||
return os.MkdirAll(joined, MkdirMode)
|
||||
}
|
Loading…
Reference in New Issue