This commit is contained in:
2019-12-22 01:17:18 +05:00
parent da4bc379d8
commit a52b18ffe4
31 changed files with 202 additions and 82 deletions

View File

@@ -30,7 +30,7 @@ import (
// local
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/flatfiles"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/mysql"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/postgresql"
"go.dev.pztrn.name/fastpastebin/internal/structs"

View File

@@ -27,7 +27,7 @@ package flatfiles
import (
// local
"go.dev.pztrn.name/fastpastebin/internal/context"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
)
var (
@@ -38,5 +38,6 @@ var (
func New(cc *context.Context) {
c = cc
f = &FlatFiles{}
c.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
}

View File

@@ -54,15 +54,18 @@ func (ff *FlatFiles) GetPaste(pasteID int) (*structs.Paste, error) {
ff.writeMutex.Lock()
pastePath := filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json")
c.Logger.Debug().Msgf("Trying to load paste data from '%s'...", pastePath)
pasteInBytes, err := ioutil.ReadFile(pastePath)
if err != nil {
c.Logger.Debug().Msgf("Failed to read paste from storage: %s", err.Error())
return nil, err
}
c.Logger.Debug().Msgf("Loaded %d bytes: %s", len(pasteInBytes), string(pasteInBytes))
ff.writeMutex.Unlock()
paste := &structs.Paste{}
err = json.Unmarshal(pasteInBytes, paste)
if err != nil {
c.Logger.Error().Msgf("Failed to parse paste: %s", err.Error())
@@ -83,6 +86,7 @@ func (ff *FlatFiles) GetPagedPastes(page int) ([]structs.Paste, error) {
// Iteration one - get only public pastes.
var publicPastes []*Index
for _, paste := range ff.pastesIndex {
if !paste.Private {
publicPastes = append(publicPastes, paste)
@@ -92,7 +96,9 @@ func (ff *FlatFiles) GetPagedPastes(page int) ([]structs.Paste, error) {
c.Logger.Debug().Msgf("%+v", publicPastes)
// Iteration two - get paginated pastes.
// nolint
var pastesData []structs.Paste
for idx, paste := range publicPastes {
if len(pastesData) == c.Config.Pastes.Pagination {
break
@@ -107,10 +113,12 @@ func (ff *FlatFiles) GetPagedPastes(page int) ([]structs.Paste, error) {
c.Logger.Debug().Msgf("Paste with index %d isn't in pagination query: too high index", idx)
break
}
c.Logger.Debug().Msgf("Getting paste data (ID: %d, index: %d)", paste.ID, idx)
// Get paste data.
pasteData := &structs.Paste{}
pasteRawData, err := ioutil.ReadFile(filepath.Join(ff.path, "pastes", strconv.Itoa(paste.ID)+".json"))
if err != nil {
c.Logger.Error().Msgf("Failed to read paste data: %s", err.Error())
@@ -160,13 +168,16 @@ func (ff *FlatFiles) Initialize() {
curUser, err := user.Current()
if err != nil {
c.Logger.Error().Msg("Failed to get current user. Will replace '~' for '/' in storage path!")
path = strings.Replace(path, "~", "/", -1)
}
path = strings.Replace(path, "~", curUser.HomeDir, -1)
}
path, _ = filepath.Abs(path)
ff.path = path
c.Logger.Debug().Msgf("Storage path is now: %s", ff.path)
// Create directory if necessary.
@@ -209,29 +220,35 @@ func (ff *FlatFiles) SavePaste(p *structs.Paste) (int64, error) {
// Write paste data on disk.
filesOnDisk, _ := ioutil.ReadDir(filepath.Join(ff.path, "pastes"))
pasteID := len(filesOnDisk) + 1
c.Logger.Debug().Msgf("Writing paste to disk, ID will be " + strconv.Itoa(pasteID))
p.ID = pasteID
c.Logger.Debug().Msgf("Writing paste to disk, ID will be " + strconv.Itoa(pasteID))
data, err := json.Marshal(p)
if err != nil {
ff.writeMutex.Unlock()
return 0, err
}
err = ioutil.WriteFile(filepath.Join(ff.path, "pastes", strconv.Itoa(pasteID)+".json"), data, 0644)
if err != nil {
ff.writeMutex.Unlock()
return 0, err
}
// Add it to cache.
indexData := &Index{}
indexData.ID = pasteID
indexData.Private = p.Private
ff.pastesIndex = append(ff.pastesIndex, indexData)
ff.writeMutex.Unlock()
return int64(pasteID), nil
}
func (ff *FlatFiles) Shutdown() {
c.Logger.Info().Msg("Saving indexes...")
indexData, err := json.Marshal(ff.pastesIndex)
if err != nil {
c.Logger.Error().Msgf("Failed to encode index data into JSON: %s", err.Error())

View File

@@ -27,7 +27,7 @@ package mysql
import (
// local
"go.dev.pztrn.name/fastpastebin/internal/context"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
)
var (
@@ -38,5 +38,6 @@ var (
func New(cc *context.Context) {
c = cc
d = &Database{}
c.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
}

View File

@@ -30,6 +30,7 @@ import (
)
func InitialUp(tx *sql.Tx) error {
// nolint
_, err := tx.Exec("CREATE TABLE `pastes` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Paste ID', `title` text NOT NULL COMMENT 'Paste title', `data` longtext NOT NULL COMMENT 'Paste data', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Paste creation timestamp', `keep_for` int(4) NOT NULL DEFAULT 1 COMMENT 'Keep for integer. 0 - forever.', `keep_for_unit_type` int(1) NOT NULL DEFAULT 1 COMMENT 'Keep for unit type. 1 - minutes, 2 - hours, 3 - days, 4 - months.', PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Pastes';")
if err != nil {
return err

View File

@@ -69,7 +69,9 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
// GetPaste returns a single paste by ID.
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
db.check()
p := &structs.Paste{}
err := db.db.Get(p, db.db.Rebind("SELECT * FROM `pastes` WHERE id=?"), pasteID)
if err != nil {
return nil, err
@@ -80,8 +82,11 @@ func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
db.check()
var pastesRaw []structs.Paste
var pastes []structs.Paste
var (
pastesRaw []structs.Paste
pastes []structs.Paste
)
// Pagination.
var startPagination = 0
@@ -105,8 +110,12 @@ func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
func (db *Database) GetPastesPages() int {
db.check()
var pastesRaw []structs.Paste
var pastes []structs.Paste
var (
pastesRaw []structs.Paste
pastes []structs.Paste
)
err := db.db.Get(&pastesRaw, "SELECT * FROM `pastes` WHERE private != true")
if err != nil {
return 1
@@ -155,6 +164,7 @@ func (db *Database) Initialize() {
_ = dbConn.MustExec("SET @@session.time_zone='+00:00';")
c.Logger.Info().Msg("Database connection established")
db.db = dbConn
// Perform migrations.
@@ -164,6 +174,7 @@ func (db *Database) Initialize() {
func (db *Database) SavePaste(p *structs.Paste) (int64, error) {
db.check()
result, err := db.db.NamedExec("INSERT INTO `pastes` (title, data, created_at, keep_for, keep_for_unit_type, language, private, password, password_salt) VALUES (:title, :data, :created_at, :keep_for, :keep_for_unit_type, :language, :private, :password, :password_salt)", p)
if err != nil {
return 0, err

View File

@@ -27,7 +27,7 @@ package postgresql
import (
// local
"go.dev.pztrn.name/fastpastebin/internal/context"
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
)
var (
@@ -38,5 +38,6 @@ var (
func New(cc *context.Context) {
c = cc
d = &Database{}
c.Database.RegisterDialect(dialectinterface.Interface(Handler{}))
}

View File

@@ -36,6 +36,7 @@ import (
// other
"github.com/jmoiron/sqlx"
// postgresql adapter
_ "github.com/lib/pq"
)
@@ -70,7 +71,9 @@ func (db *Database) GetDatabaseConnection() *sql.DB {
// GetPaste returns a single paste by ID.
func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
db.check()
p := &structs.Paste{}
err := db.db.Get(p, db.db.Rebind("SELECT * FROM pastes WHERE id=$1"), pasteID)
if err != nil {
return nil, err
@@ -88,8 +91,11 @@ func (db *Database) GetPaste(pasteID int) (*structs.Paste, error) {
func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
db.check()
var pastesRaw []structs.Paste
var pastes []structs.Paste
var (
pastesRaw []structs.Paste
pastes []structs.Paste
)
// Pagination.
var startPagination = 0
@@ -119,8 +125,12 @@ func (db *Database) GetPagedPastes(page int) ([]structs.Paste, error) {
func (db *Database) GetPastesPages() int {
db.check()
var pastesRaw []structs.Paste
var pastes []structs.Paste
var (
pastesRaw []structs.Paste
pastes []structs.Paste
)
err := db.db.Get(&pastesRaw, "SELECT * FROM pastes WHERE private != true")
if err != nil {
return 1
@@ -164,6 +174,7 @@ func (db *Database) Initialize() {
}
c.Logger.Info().Msg("Database connection established")
db.db = dbConn
// Perform migrations.
@@ -173,12 +184,14 @@ func (db *Database) Initialize() {
func (db *Database) SavePaste(p *structs.Paste) (int64, error) {
db.check()
stmt, err := db.db.PrepareNamed("INSERT INTO pastes (title, data, created_at, keep_for, keep_for_unit_type, language, private, password, password_salt) VALUES (:title, :data, :created_at, :keep_for, :keep_for_unit_type, :language, :private, :password, :password_salt) RETURNING id")
if err != nil {
return 0, err
}
var id int64
err = stmt.Get(&id, p)
if err != nil {
return 0, err

View File

@@ -27,7 +27,7 @@ package database
import (
// local
"go.dev.pztrn.name/fastpastebin/internal/context"
"go.dev.pztrn.name/fastpastebin/internal/database/interface"
databaseinterface "go.dev.pztrn.name/fastpastebin/internal/database/interface"
)
var (
@@ -39,5 +39,6 @@ var (
func New(cc *context.Context) {
c = cc
d = &Database{}
c.RegisterDatabaseInterface(databaseinterface.Interface(Handler{}))
}

View File

@@ -29,7 +29,8 @@ import (
"database/sql"
// local
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
"go.dev.pztrn.name/fastpastebin/internal/structs"
)

View File

@@ -29,7 +29,7 @@ import (
"database/sql"
// local
"go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
dialectinterface "go.dev.pztrn.name/fastpastebin/internal/database/dialects/interface"
"go.dev.pztrn.name/fastpastebin/internal/structs"
)