Implement SQL storage driver

This commit is contained in:
Lukas SP 2020-08-28 19:55:10 +02:00
parent f97531e765
commit bf96209d99
6 changed files with 135 additions and 1 deletions

View File

@ -40,4 +40,13 @@ Every single one of them has its own configuration variables:
|-------------------------------------|--------------------------------------------|----------|-----------------------------------------------------------------|
| `STORAGE_MONGODB_CONNECTION_STRING` | `mongodb://pasty:pasty@example.host/pasty` | `string` | Defines the connection string to use for the MongoDB connection |
| `STORAGE_MONGODB_DATABASE` | `pasty` | `string` | Defines the name of the database to use |
| `STORAGE_MONGODB_COLLECTION` | `pastes` | `string` | Defines the name of the collection to use |
| `STORAGE_MONGODB_COLLECTION` | `pastes` | `string` | Defines the name of the collection to use |
---
### SQL (`sql`)
| Environment Variable | Default Value | Type | Description |
|----------------------|---------------|----------|-------------------------------------------------------------------------------------|
| `STORAGE_SQL_DRIVER` | `sqlite3` | `string` | Defines the driver to use for the SQL connection (`sqlite3`, `postgres` or `mysql`) |
| `STORAGE_SQL_DSN` | `./db` | `string` | Defines the DSN to use for the SQL connection |
| `STORAGE_SQL_TABLE` | `pasty` | `string` | Defines the table name to use for the SQL connection |

3
go.mod
View File

@ -5,8 +5,11 @@ go 1.15
require (
github.com/alexedwards/argon2id v0.0.0-20200802152012-2464efd3196b
github.com/fasthttp/router v1.2.4
github.com/go-sql-driver/mysql v1.5.0
github.com/joho/godotenv v1.3.0
github.com/klauspost/compress v1.10.11 // indirect
github.com/lib/pq v1.8.0
github.com/mattn/go-sqlite3 v1.14.2
github.com/minio/minio-go/v7 v7.0.5
github.com/ulule/limiter/v3 v3.5.0
github.com/valyala/fasthttp v1.16.0

9
go.sum
View File

@ -1,8 +1,10 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/alexedwards/argon2id v0.0.0-20200802152012-2464efd3196b h1:rcCpjI1OMGtBY8nnBvExeM1pXNoaM35zqmXBGpgJR2o=
github.com/alexedwards/argon2id v0.0.0-20200802152012-2464efd3196b/go.mod h1:GFtu6vaWaRJV5EvSFaVqgq/3Iq95xyYElBV/aupGzUo=
github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/aws/aws-sdk-go v1.29.15 h1:0ms/213murpsujhsnxnNKNeVouW60aJqSd992Ks3mxs=
github.com/aws/aws-sdk-go v1.29.15/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -18,6 +20,7 @@ github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTM
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@ -89,9 +92,13 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.2 h1:A2EQLwjYf/hfYaM20FVjs1UewCTTFR7RmjEHkLjldIA=
github.com/mattn/go-sqlite3 v1.14.2/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/minio-go/v7 v7.0.5 h1:I2NIJ2ojwJqD/YByemC1M59e1b4FW9kS7NlOar7HPV4=
@ -168,12 +175,14 @@ golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=

View File

@ -47,6 +47,8 @@ func GetDriver(storageType string) (Driver, error) {
return new(S3Driver), nil
case "mongodb":
return new(MongoDBDriver), nil
case "sql":
return new(SQLDriver), nil
default:
return nil, fmt.Errorf("invalid storage type '%s'", storageType)
}

View File

@ -63,6 +63,9 @@ func (driver *S3Driver) Get(id string) (*pastes.Paste, error) {
if err != nil {
return nil, err
}
if object == nil {
return nil, nil
}
data, err := ioutil.ReadAll(object)
if err != nil {
return nil, err

View File

@ -0,0 +1,108 @@
package storage
import (
"database/sql"
"github.com/Lukaesebrot/pasty/internal/env"
"github.com/Lukaesebrot/pasty/internal/pastes"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
)
// SQLDriver represents the SQL storage driver
type SQLDriver struct {
database *sql.DB
table string
}
// Initialize initializes the SQL storage driver
func (driver *SQLDriver) Initialize() error {
// Parse the DSN and create a database object
db, err := sql.Open(env.Get("STORAGE_SQL_DRIVER", "sqlite3"), env.Get("STORAGE_SQL_DSN", "./db"))
if err != nil {
return err
}
// Ping the database
err = db.Ping()
if err != nil {
return err
}
// Migrate the database
table := env.Get("STORAGE_SQL_TABLE", "pasty")
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS ? (
id varchar NOT NULL PRIMARY KEY,
content varchar NOT NULL,
suggestedSyntaxType varchar NOT NULL,
deletionToken varchar NOT NULL
);
`, table)
if err != nil {
return err
}
// Set the database object and table name of the SQL driver
driver.database = db
driver.table = table
return nil
}
// Terminate terminates the SQL storage driver
func (driver *SQLDriver) Terminate() error {
return driver.database.Close()
}
// ListIDs returns a list of all existing paste IDs
func (driver *SQLDriver) ListIDs() ([]string, error) {
// Execute a SELECT query to retrieve all the paste IDs
rows, err := driver.database.Query("SELECT id FROM ?", driver.table)
if err != nil {
return nil, err
}
defer rows.Close()
// Scan the rows into a slice of IDs and return it
var ids []string
err = rows.Scan(&ids)
if err != nil {
return nil, err
}
return ids, nil
}
// Get loads a paste
func (driver *SQLDriver) Get(id string) (*pastes.Paste, error) {
// Execute a SELECT query to retrieve the paste
row := driver.database.QueryRow("SELECT * FROM ? WHERE id = ?", driver.table, id)
err := row.Err()
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
// Scan the row into a paste and return it
paste := new(pastes.Paste)
err = row.Scan(&paste)
if err != nil {
return nil, err
}
return paste, nil
}
// Save saves a paste
func (driver *SQLDriver) Save(paste *pastes.Paste) error {
// Execute an INSERT statement to create the paste
_, err := driver.database.Exec("INSERT INTO ? (?, ?, ?, ?)", driver.table, paste.ID, paste.Content, paste.SuggestedSyntaxType, paste.DeletionToken)
return err
}
// Delete deletes a paste
func (driver *SQLDriver) Delete(id string) error {
// Execute a DELETE statement to delete the paste
_, err := driver.database.Exec("DELETE FROM ? WHERE id = ?", driver.table, id)
return err
}