dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit 0f5c85450f3db36366595b79d6b541fb099cd9e7
parent 053971a02f4cbec5b9321a07cf4d5cdfb2c75f0d
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Thu, 21 Dec 2023 10:29:33 -0500

cleanup

Diffstat:
Mcmd/dkf/main.go | 13+++++++------
Mpkg/actions/actions.go | 38+++++++++++++++++++-------------------
Mpkg/config/config.go | 211++++++-------------------------------------------------------------------------
Mpkg/database/database.go | 5+++--
Mpkg/database/tableFiledrops.go | 6+++---
Mpkg/database/tableMemes.go | 8++++----
Mpkg/database/tableUploads.go | 12++++++------
Mpkg/template/templates.go | 6+++---
Apkg/utils/rwmtx/rwmtx.go | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpkg/utils/utils.go | 45+++------------------------------------------
Mpkg/web/handlers/admin.go | 2+-
Mpkg/web/handlers/api/v1/handlers.go | 2+-
Mpkg/web/handlers/fileDrop.go | 26+++++++++++++-------------
Mpkg/web/handlers/interceptors/slashInterceptor.go | 4++--
Mpkg/web/handlers/poker/poker.go | 23++++++++++++-----------
Mpkg/web/handlers/utils/utils.go | 4++--
Mpkg/web/middlewares/middlewares.go | 4++--
17 files changed, 150 insertions(+), 313 deletions(-)

diff --git a/cmd/dkf/main.go b/cmd/dkf/main.go @@ -8,6 +8,7 @@ import ( _ "embed" b64 "encoding/base64" "fmt" + "github.com/hashicorp/go-version" _ "github.com/mattn/go-sqlite3" cli "github.com/urfave/cli/v2" "log" @@ -20,8 +21,8 @@ import ( // These variables are overwritten during the build process using ldflags // "version" is base64 encoded to make it harder for a hacker to change // the value by simply ctrl+f & replace the compiled binary file. -var version = "MTAwMC4wLjAK" // Base64 encoded (`echo '1000.0.0' | base64`) -var versionVoid = "" // Useless, just to confuse hackers :) +var versionTmp = "MTAwMC4wLjAK" // Base64 encoded (`echo '1000.0.0' | base64`) +var versionVoid = "" // Useless, just to confuse hackers :) var sha = "" var development = "1" @@ -56,14 +57,14 @@ func void(nothing string) { func main() { void(versionVoid) - versionDecodedBytes, _ := b64.StdEncoding.DecodeString(version) + versionDecodedBytes, _ := b64.StdEncoding.DecodeString(versionTmp) versionDecoded := strings.TrimSpace(string(versionDecodedBytes)) - config.Global.SetVersion(versionDecoded) + config.Global.AppVersion.Set(version.Must(version.NewVersion(versionDecoded))) developmentFlag := utils.DoParseBool(development) config.Development.Store(developmentFlag) config.NullUserPrivateKey = string(nullPrivateKey) config.NullUserPublicKey = string(nullPublicKey) - config.Global.SetMasterKey(string(masterKey)) + config.Global.MasterKey.Set(string(masterKey)) config.GistPasswordSalt = string(gistPasswordSalt) config.RoomPasswordSalt = string(roomPasswordSalt) config.MigrationsFs = migrationsFs @@ -75,7 +76,7 @@ func main() { } app.Name = "darkforest" app.Usage = "Tor service" - app.Version = version + app.Version = versionTmp app.Flags = []cli.Flag{ &cli.StringFlag{ Name: "host", diff --git a/pkg/actions/actions.go b/pkg/actions/actions.go @@ -38,18 +38,18 @@ func Start(c *cli.Context) error { logrus.SetFormatter(LogFormatter{}) logrus.SetOutput(colorable.NewColorableStderr()) - logrus.Info("DarkForest v" + config.Global.GetVersion().String()) + logrus.Info("DarkForest v" + config.Global.AppVersion.Get().String()) port := c.Int("port") host := c.String("host") noBrowser := c.Bool("no-browser") - config.Global.SetCookieSecure(c.Bool("cookie-secure")) - config.Global.SetCookieDomain(c.String("cookie-domain")) + config.Global.CookieSecure.Set(c.Bool("cookie-secure")) + config.Global.CookieDomain.Set(c.String("cookie-domain")) ensureProjectHome() - dbPath := filepath.Join(config.Global.ProjectPath(), config.DbFileName) + dbPath := filepath.Join(config.Global.ProjectPath.Get(), config.DbFileName) db := database.NewDkfDB(dbPath) runMigrations(db) @@ -139,40 +139,40 @@ func runMigrations(db *database.DkfDB) { // Ensure the project folder is created properly func ensureProjectHome() { - config.Global.SetProjectPath(utils.MustGetDefaultProjectPath()) - projectPath := config.Global.ProjectPath() + config.Global.ProjectPath.Set(utils.MustGetDefaultProjectPath()) + projectPath := config.Global.ProjectPath.Get() if err := os.MkdirAll(projectPath, 0755); err != nil { logrus.Fatal("Failed to create project folder", err) } - config.Global.SetProjectLocalsPath(filepath.Join(projectPath, "locals")) - if err := os.MkdirAll(config.Global.ProjectLocalsPath(), 0755); err != nil { + config.Global.ProjectLocalsPath.Set(filepath.Join(projectPath, "locals")) + if err := os.MkdirAll(config.Global.ProjectLocalsPath.Get(), 0755); err != nil { logrus.Fatal("Failed to create dkforest locals folder", err) } - config.Global.SetProjectHTMLPath(filepath.Join(projectPath, "html")) - if err := os.MkdirAll(config.Global.ProjectHTMLPath(), 0755); err != nil { + config.Global.ProjectHTMLPath.Set(filepath.Join(projectPath, "html")) + if err := os.MkdirAll(config.Global.ProjectHTMLPath.Get(), 0755); err != nil { logrus.Fatal("Failed to create dkforest html folder", err) } - config.Global.SetProjectMemesPath(filepath.Join(projectPath, "memes")) - if err := os.MkdirAll(config.Global.ProjectMemesPath(), 0755); err != nil { + config.Global.ProjectMemesPath.Set(filepath.Join(projectPath, "memes")) + if err := os.MkdirAll(config.Global.ProjectMemesPath.Get(), 0755); err != nil { logrus.Fatal("Failed to create memes uploads folder", err) } - config.Global.SetProjectUploadsPath(filepath.Join(projectPath, "uploads")) - if err := os.MkdirAll(config.Global.ProjectUploadsPath(), 0755); err != nil { + config.Global.ProjectUploadsPath.Set(filepath.Join(projectPath, "uploads")) + if err := os.MkdirAll(config.Global.ProjectUploadsPath.Get(), 0755); err != nil { logrus.Fatal("Failed to create dkforest uploads folder", err) } - config.Global.SetProjectFiledropPath(filepath.Join(projectPath, "filedrop")) - if err := os.MkdirAll(config.Global.ProjectFiledropPath(), 0755); err != nil { + config.Global.ProjectFiledropPath.Set(filepath.Join(projectPath, "filedrop")) + if err := os.MkdirAll(config.Global.ProjectFiledropPath.Get(), 0755); err != nil { logrus.Fatal("Failed to create dkforest filedrop folder", err) } // Contains files that we offer for download directly - config.Global.SetProjectDownloadsPath(filepath.Join(projectPath, "downloads")) - if err := os.MkdirAll(config.Global.ProjectDownloadsPath(), 0755); err != nil { + config.Global.ProjectDownloadsPath.Set(filepath.Join(projectPath, "downloads")) + if err := os.MkdirAll(config.Global.ProjectDownloadsPath.Get(), 0755); err != nil { logrus.Fatal("Failed to create dkforest downloads folder", err) } } @@ -332,7 +332,7 @@ func BuildProhibitedPasswords(c *cli.Context) error { ensureProjectHome() - dbPath := filepath.Join(config.Global.ProjectPath(), config.DbFileName) + dbPath := filepath.Join(config.Global.ProjectPath.Get(), config.DbFileName) db := database.NewDkfDB(dbPath).DB() readFile, _ := os.Open("rockyou.txt") diff --git a/pkg/config/config.go b/pkg/config/config.go @@ -1,6 +1,7 @@ package config import ( + "dkforest/pkg/utils/rwmtx" "embed" wallet1 "github.com/monero-ecosystem/go-monero-rpc-client/wallet" "net" @@ -163,206 +164,24 @@ var ConnMap = NewConnManager() // GlobalConf ... type GlobalConf struct { sync.RWMutex - appVersion *version.Version - projectPath string // project path - projectLocalsPath string // directory where we keep custom translation files - projectHtmlPath string - projectMemesPath string - projectUploadsPath string - projectFiledropPath string - projectDownloadsPath string - sha string - masterKey string - cookieSecure bool - cookieDomain string - baseURL string // (http://127.0.0.1:8080) + AppVersion rwmtx.RWMtx[*version.Version] + ProjectPath rwmtx.RWMtx[string] // project path + ProjectLocalsPath rwmtx.RWMtx[string] // directory where we keep custom translation files + ProjectHTMLPath rwmtx.RWMtx[string] + ProjectMemesPath rwmtx.RWMtx[string] + ProjectUploadsPath rwmtx.RWMtx[string] + ProjectFiledropPath rwmtx.RWMtx[string] + ProjectDownloadsPath rwmtx.RWMtx[string] + Sha rwmtx.RWMtx[string] + MasterKey rwmtx.RWMtx[string] + CookieSecure rwmtx.RWMtx[bool] + CookieDomain rwmtx.RWMtx[string] + BaseURL rwmtx.RWMtx[string] // (http://127.0.0.1:8080) } // NewGlobalConf ... func NewGlobalConf() *GlobalConf { c := new(GlobalConf) - c.masterKey = DefaultMasterKey + c.MasterKey.Set(DefaultMasterKey) return c } - -// ProjectPath ... -func (c *GlobalConf) ProjectPath() string { - c.RLock() - defer c.RUnlock() - return c.projectPath -} - -// SetProjectPath ... -func (c *GlobalConf) SetProjectPath(v string) { - c.Lock() - defer c.Unlock() - c.projectPath = v -} - -// MasterKey ... -func (c *GlobalConf) MasterKey() string { - c.RLock() - defer c.RUnlock() - return c.masterKey -} - -// SetMasterKey ... -func (c *GlobalConf) SetMasterKey(v string) { - c.Lock() - defer c.Unlock() - c.masterKey = v -} - -// GetVersion ... -func (c *GlobalConf) GetVersion() *version.Version { - c.RLock() - defer c.RUnlock() - return c.appVersion -} - -// SetVersion ... -func (c *GlobalConf) SetVersion(newVersion string) { - c.Lock() - defer c.Unlock() - c.appVersion = version.Must(version.NewVersion(newVersion)) -} - -// Sha ... -func (c *GlobalConf) Sha() string { - c.RLock() - defer c.RUnlock() - return c.sha -} - -// SetSha ... -func (c *GlobalConf) SetSha(sha string) { - c.Lock() - defer c.Unlock() - c.sha = sha -} - -// CookieSecure ... -func (c *GlobalConf) CookieSecure() bool { - c.RLock() - defer c.RUnlock() - return c.cookieSecure -} - -// SetCookieSecure ... -func (c *GlobalConf) SetCookieSecure(cookieSecure bool) { - c.Lock() - defer c.Unlock() - c.cookieSecure = cookieSecure -} - -// CookieDomain ... -func (c *GlobalConf) CookieDomain() string { - c.RLock() - defer c.RUnlock() - return c.cookieDomain -} - -// SetCookieDomain ... -func (c *GlobalConf) SetCookieDomain(cookieDomain string) { - c.Lock() - defer c.Unlock() - c.cookieDomain = cookieDomain -} - -// ProjectLocalsPath ... -func (c *GlobalConf) ProjectLocalsPath() string { - c.RLock() - defer c.RUnlock() - return c.projectLocalsPath -} - -// SetProjectLocalsPath ... -func (c *GlobalConf) SetProjectLocalsPath(projectLocalsPath string) { - c.Lock() - defer c.Unlock() - c.projectLocalsPath = projectLocalsPath -} - -// ProjectHTMLPath ... -func (c *GlobalConf) ProjectHTMLPath() string { - c.RLock() - defer c.RUnlock() - return c.projectHtmlPath -} - -// SetProjectHTMLPath ... -func (c *GlobalConf) SetProjectHTMLPath(projectHtmlPath string) { - c.Lock() - defer c.Unlock() - c.projectHtmlPath = projectHtmlPath -} - -// ProjectMemesPath ... -func (c *GlobalConf) ProjectMemesPath() string { - c.RLock() - defer c.RUnlock() - return c.projectMemesPath -} - -// SetProjectMemesPath ... -func (c *GlobalConf) SetProjectMemesPath(projectMemesPath string) { - c.Lock() - defer c.Unlock() - c.projectMemesPath = projectMemesPath -} - -// ProjectUploadsPath ... -func (c *GlobalConf) ProjectUploadsPath() string { - c.RLock() - defer c.RUnlock() - return c.projectUploadsPath -} - -// SetProjectUploadsPath ... -func (c *GlobalConf) SetProjectUploadsPath(projectUploadsPath string) { - c.Lock() - defer c.Unlock() - c.projectUploadsPath = projectUploadsPath -} - -// ProjectFiledropPath ... -func (c *GlobalConf) ProjectFiledropPath() string { - c.RLock() - defer c.RUnlock() - return c.projectFiledropPath -} - -// SetProjectFiledropPath ... -func (c *GlobalConf) SetProjectFiledropPath(projectFiledropPath string) { - c.Lock() - defer c.Unlock() - c.projectFiledropPath = projectFiledropPath -} - -// ProjectDownloadsPath ... -func (c *GlobalConf) ProjectDownloadsPath() string { - c.RLock() - defer c.RUnlock() - return c.projectDownloadsPath -} - -// SetProjectDownloadsPath ... -func (c *GlobalConf) SetProjectDownloadsPath(projectDownloadsPath string) { - c.Lock() - defer c.Unlock() - c.projectDownloadsPath = projectDownloadsPath -} - -// BaseURL ... -func (c *GlobalConf) BaseURL() string { - c.RLock() - defer c.RUnlock() - return c.baseURL -} - -// SetBaseURL ... -func (c *GlobalConf) SetBaseURL(v string) { - c.Lock() - defer c.Unlock() - c.baseURL = v -} diff --git a/pkg/database/database.go b/pkg/database/database.go @@ -296,8 +296,9 @@ const bkDelay = 250 // Backup the database func Backup() error { - dbPath := filepath.Join(config.Global.ProjectPath(), config.DbFileName) - bckPath := filepath.Join(config.Global.ProjectPath(), "backup.db") + projectPath := config.Global.ProjectPath.Get() + dbPath := filepath.Join(projectPath, config.DbFileName) + bckPath := filepath.Join(projectPath, "backup.db") srcDB, err := New(dbPath, "", false) if err != nil { return err diff --git a/pkg/database/tableFiledrops.go b/pkg/database/tableFiledrops.go @@ -46,13 +46,13 @@ func (d *DkfDB) CreateFiledrop() (out Filedrop, err error) { } func (d *Filedrop) Exists() bool { - filePath1 := filepath.Join(config.Global.ProjectFiledropPath(), d.FileName) + filePath1 := filepath.Join(config.Global.ProjectFiledropPath.Get(), d.FileName) return utils.FileExists(filePath1) } func (d *Filedrop) GetContent() (*os.File, *ucrypto.StreamDecrypter, error) { password := []byte(d.Password) - filePath1 := filepath.Join(config.Global.ProjectFiledropPath(), d.FileName) + filePath1 := filepath.Join(config.Global.ProjectFiledropPath.Get(), d.FileName) f, err := os.Open(filePath1) if err != nil { return nil, nil, err @@ -67,7 +67,7 @@ func (d *Filedrop) GetContent() (*os.File, *ucrypto.StreamDecrypter, error) { func (d *Filedrop) Delete(db *DkfDB) error { if d.FileName != "" { - if err := os.Remove(filepath.Join(config.Global.ProjectFiledropPath(), d.FileName)); err != nil { + if err := os.Remove(filepath.Join(config.Global.ProjectFiledropPath.Get(), d.FileName)); err != nil { logrus.Error(err) } } diff --git a/pkg/database/tableMemes.go b/pkg/database/tableMemes.go @@ -35,7 +35,7 @@ func (u *Meme) GetHTMLLink() string { } func (u *Meme) GetContent() (os.FileInfo, []byte, error) { - filePath1 := filepath.Join(config.Global.ProjectMemesPath(), u.FileName) + filePath1 := filepath.Join(config.Global.ProjectMemesPath.Get(), u.FileName) f, err := os.Open(filePath1) if err != nil { return nil, nil, err @@ -55,12 +55,12 @@ func (u *Meme) GetContent() (os.FileInfo, []byte, error) { } func (u *Meme) Exists() bool { - filePath1 := filepath.Join(config.Global.ProjectMemesPath(), u.FileName) + filePath1 := filepath.Join(config.Global.ProjectMemesPath.Get(), u.FileName) return utils.FileExists(filePath1) } func (u *Meme) Delete(db *DkfDB) error { - if err := os.Remove(filepath.Join(config.Global.ProjectMemesPath(), u.FileName)); err != nil { + if err := os.Remove(filepath.Join(config.Global.ProjectMemesPath.Get(), u.FileName)); err != nil { return err } if err := db.db.Delete(&u).Error; err != nil { @@ -84,7 +84,7 @@ func (d *DkfDB) CreateEncryptedMemeWithSize(fileName string, content []byte, siz func (d *DkfDB) createMemeWithSize(fileName string, content []byte, size int64) (*Meme, error) { newFileName := utils.MD5([]byte(utils.GenerateToken32())) - if err := os.WriteFile(filepath.Join(config.Global.ProjectMemesPath(), newFileName), content, 0644); err != nil { + if err := os.WriteFile(filepath.Join(config.Global.ProjectMemesPath.Get(), newFileName), content, 0644); err != nil { return nil, err } meme := Meme{ diff --git a/pkg/database/tableUploads.go b/pkg/database/tableUploads.go @@ -31,7 +31,7 @@ func (u *Upload) GetHTMLLink() string { } func (u *Upload) GetContent() (os.FileInfo, []byte, error) { - filePath1 := filepath.Join(config.Global.ProjectUploadsPath(), u.FileName) + filePath1 := filepath.Join(config.Global.ProjectUploadsPath.Get(), u.FileName) f, err := os.Open(filePath1) if err != nil { return nil, nil, err @@ -51,12 +51,12 @@ func (u *Upload) GetContent() (os.FileInfo, []byte, error) { } func (u *Upload) Exists() bool { - filePath1 := filepath.Join(config.Global.ProjectUploadsPath(), u.FileName) + filePath1 := filepath.Join(config.Global.ProjectUploadsPath.Get(), u.FileName) return utils.FileExists(filePath1) } func (u *Upload) Delete(db *DkfDB) error { - if err := os.Remove(filepath.Join(config.Global.ProjectUploadsPath(), u.FileName)); err != nil { + if err := os.Remove(filepath.Join(config.Global.ProjectUploadsPath.Get(), u.FileName)); err != nil { return err } if err := db.db.Delete(&u).Error; err != nil { @@ -80,7 +80,7 @@ func (d *DkfDB) CreateEncryptedUploadWithSize(fileName string, content []byte, u func (d *DkfDB) createUploadWithSize(fileName string, content []byte, userID UserID, size int64) (*Upload, error) { newFileName := utils.MD5([]byte(utils.GenerateToken32())) - if err := os.WriteFile(filepath.Join(config.Global.ProjectUploadsPath(), newFileName), content, 0644); err != nil { + if err := os.WriteFile(filepath.Join(config.Global.ProjectUploadsPath.Get(), newFileName), content, 0644); err != nil { return nil, err } upload := Upload{ @@ -127,7 +127,7 @@ func (d *DkfDB) DeleteOldUploads() { if err := d.db.Exec(`DELETE FROM uploads WHERE created_at < date('now', '-1 Day')`).Error; err != nil { logrus.Error(err.Error()) } - entries, err := os.ReadDir(config.Global.ProjectUploadsPath()) + entries, err := os.ReadDir(config.Global.ProjectUploadsPath.Get()) if err != nil { logrus.Error(err.Error()) return @@ -139,7 +139,7 @@ func (d *DkfDB) DeleteOldUploads() { continue } if diff := now.Sub(info.ModTime()); diff > 24*time.Hour { - if err := os.Remove(filepath.Join(config.Global.ProjectUploadsPath(), info.Name())); err != nil { + if err := os.Remove(filepath.Join(config.Global.ProjectUploadsPath.Get(), info.Name())); err != nil { logrus.Error(err.Error()) } } diff --git a/pkg/template/templates.go b/pkg/template/templates.go @@ -74,15 +74,15 @@ func (t *Templates) Render(w io.Writer, name string, data any, c echo.Context) e d := templateDataStruct{} d.TmplName = name d.Data = data - d.VERSION = config.Global.GetVersion().Original() + d.VERSION = config.Global.AppVersion.Get().Original() if config.Development.IsTrue() { d.VERSION += utils.FormatInt64(time.Now().Unix()) } d.Reverse = c.Echo().Reverse // {{ call .Reverse "name" }} || {{ call .Reverse "name" "params" }} d.Bundle = c.Get("bundle").(*i18n.Bundle) //d.SHA = config.Global.Sha() - d.VersionHTML = template.HTML(fmt.Sprintf("<!-- VERSION: %s -->", config.Global.GetVersion().Original())) - d.ShaHTML = template.HTML(fmt.Sprintf("<!-- SHA: %s -->", config.Global.Sha())) + d.VersionHTML = template.HTML(fmt.Sprintf("<!-- VERSION: %s -->", config.Global.AppVersion.Get().Original())) + d.ShaHTML = template.HTML(fmt.Sprintf("<!-- SHA: %s -->", config.Global.Sha.Get())) d.NullUsername = config.NullUsername d.CSRF, _ = c.Get("csrf").(string) d.DB = db diff --git a/pkg/utils/rwmtx/rwmtx.go b/pkg/utils/rwmtx/rwmtx.go @@ -0,0 +1,54 @@ +package rwmtx + +import "sync" + +type RWMtx[T any] struct { + sync.RWMutex + v T +} + +func New[T any](v T) RWMtx[T] { + return RWMtx[T]{v: v} +} + +func (m *RWMtx[T]) Get() T { + m.RLock() + defer m.RUnlock() + return m.v +} + +func (m *RWMtx[T]) Set(v T) { + m.Lock() + defer m.Unlock() + m.v = v +} + +func (m *RWMtx[T]) Val() *T { + return &m.v +} + +func (m *RWMtx[T]) RWith(clb func(v *T)) { + _ = m.RWithE(func(tx *T) error { + clb(tx) + return nil + }) +} + +func (m *RWMtx[T]) RWithE(clb func(v *T) error) error { + m.RLock() + defer m.RUnlock() + return clb(&m.v) +} + +func (m *RWMtx[T]) With(clb func(v *T)) { + _ = m.WithE(func(tx *T) error { + clb(tx) + return nil + }) +} + +func (m *RWMtx[T]) WithE(clb func(v *T) error) error { + m.Lock() + defer m.Unlock() + return clb(&m.v) +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go @@ -400,12 +400,12 @@ func DecryptAES(ciphertext []byte, key []byte) ([]byte, error) { // EncryptAESMaster same as EncryptAES but use the default master key func EncryptAESMaster(plaintext []byte) ([]byte, error) { - return EncryptAES(plaintext, []byte(config.Global.MasterKey())) + return EncryptAES(plaintext, []byte(config.Global.MasterKey.Get())) } // DecryptAESMaster same as DecryptAES but use the default master key func DecryptAESMaster(ciphertext []byte) ([]byte, error) { - return DecryptAES(ciphertext, []byte(config.Global.MasterKey())) + return DecryptAES(ciphertext, []byte(config.Global.MasterKey.Get())) } func EncryptStream(password []byte, src io.Reader) (*crypto.StreamEncrypter, error) { @@ -558,7 +558,7 @@ func GeneratePgpEncryptedMessage(pkey, msg string) (string, error) { // LoadLocals ... func LoadLocals(bundle *i18n.Bundle) error { - err := filepath.Walk(config.Global.ProjectLocalsPath(), func(path string, info os.FileInfo, err error) error { + err := filepath.Walk(config.Global.ProjectLocalsPath.Get(), func(path string, info os.FileInfo, err error) error { if !info.IsDir() { if strings.HasSuffix(info.Name(), ".yaml") { if _, err = bundle.LoadMessageFile(path); err != nil { @@ -1191,42 +1191,3 @@ func (_ CryptoRandSource) Int63() int64 { } func (_ CryptoRandSource) Seed(_ int64) {} - -type RWMtx[T any] struct { - sync.RWMutex - v T -} - -func NewRWMtx[T any](v T) RWMtx[T] { - return RWMtx[T]{v: v} -} - -func (m *RWMtx[T]) Val() *T { - return &m.v -} - -func (m *RWMtx[T]) RWith(clb func(v *T)) { - _ = m.RWithE(func(tx *T) error { - clb(tx) - return nil - }) -} - -func (m *RWMtx[T]) RWithE(clb func(v *T) error) error { - m.RLock() - defer m.RUnlock() - return clb(&m.v) -} - -func (m *RWMtx[T]) With(clb func(v *T)) { - _ = m.WithE(func(tx *T) error { - clb(tx) - return nil - }) -} - -func (m *RWMtx[T]) WithE(clb func(v *T) error) error { - m.Lock() - defer m.Unlock() - return clb(&m.v) -} diff --git a/pkg/web/handlers/admin.go b/pkg/web/handlers/admin.go @@ -267,7 +267,7 @@ func AdminSettingsHandler(c echo.Context) error { if c.Request().Method == http.MethodPost { formName := c.Request().PostFormValue("formName") if formName == "openProjectFolder" { - if err := open.Run(config.Global.ProjectPath()); err != nil { + if err := open.Run(config.Global.ProjectPath.Get()); err != nil { logrus.Error(err) } return c.Redirect(http.StatusFound, "/admin/settings") diff --git a/pkg/web/handlers/api/v1/handlers.go b/pkg/web/handlers/api/v1/handlers.go @@ -158,7 +158,7 @@ func ChatMessagesHandler(c echo.Context) error { } return c.JSON(http.StatusOK, data) } - version := config.Global.GetVersion().Original() + version := config.Global.AppVersion.Get().Original() csrf, _ := c.Get("csrf").(string) return c.HTML(http.StatusOK, Messages(version, csrf, config.NullUsername, authUser, data)) //return c.Render(http.StatusOK, "chat-messages", data) diff --git a/pkg/web/handlers/fileDrop.go b/pkg/web/handlers/fileDrop.go @@ -77,7 +77,7 @@ func FileDropHandler(c echo.Context) error { return c.Render(http.StatusOK, filedropTmplName, data) } - outFile, err := os.OpenFile(filepath.Join(config.Global.ProjectFiledropPath(), filedrop.FileName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + outFile, err := os.OpenFile(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedrop.FileName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { data.Error = err.Error() return c.Render(http.StatusOK, filedropTmplName, data) @@ -109,8 +109,8 @@ func FileDropDkfUploadHandler(c echo.Context) error { return c.Redirect(http.StatusFound, "/") } - _ = os.Mkdir(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID), 0755) - metadataPath := filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, "metadata") + _ = os.Mkdir(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID), 0755) + metadataPath := filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID, "metadata") fileName := c.Request().PostFormValue("fileName") fileSize := c.Request().PostFormValue("fileSize") @@ -149,7 +149,7 @@ func FileDropDkfUploadHandler(c echo.Context) error { return c.Redirect(http.StatusFound, "/") } - dirEntries, _ := os.ReadDir(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID)) + dirEntries, _ := os.ReadDir(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID)) fileNames := make([]string, 0) for _, dirEntry := range dirEntries { if !strings.HasPrefix(dirEntry.Name(), "part_") { @@ -165,7 +165,7 @@ func FileDropDkfUploadHandler(c echo.Context) error { return numA < numB }) - metadata, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, "metadata")) + metadata, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID, "metadata")) if err != nil { logrus.Error(err) return c.NoContent(http.StatusInternalServerError) @@ -174,7 +174,7 @@ func FileDropDkfUploadHandler(c echo.Context) error { origFileName := lines[0] fileSha256 := lines[2] - f, err := os.OpenFile(filepath.Join(config.Global.ProjectFiledropPath(), filedrop.FileName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + f, err := os.OpenFile(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedrop.FileName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { logrus.Error(err) return c.NoContent(http.StatusInternalServerError) @@ -192,7 +192,7 @@ func FileDropDkfUploadHandler(c echo.Context) error { } written := int64(0) for _, fileName := range fileNames { - by, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, fileName)) + by, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID, fileName)) if err != nil { logrus.Error(err) return c.NoContent(http.StatusInternalServerError) @@ -217,7 +217,7 @@ func FileDropDkfUploadHandler(c echo.Context) error { } // Cleanup - _ = os.RemoveAll(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID)) + _ = os.RemoveAll(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID)) filedrop.Password = database.EncryptedString(password) filedrop.IV = iv @@ -233,7 +233,7 @@ func FileDropDkfUploadHandler(c echo.Context) error { { chunkFileName := c.Request().PostFormValue("chunkFileName") if chunkFileName != "" { - if _, err := os.Stat(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, chunkFileName)); err != nil { + if _, err := os.Stat(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID, chunkFileName)); err != nil { return c.NoContent(http.StatusOK) } // Let's use the teapot response (because why not) to say that we already have the file @@ -254,7 +254,7 @@ func FileDropDkfUploadHandler(c echo.Context) error { defer file.Close() fileName := handler.Filename by, _ := io.ReadAll(file) - p := filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, fileName) + p := filepath.Join(config.Global.ProjectFiledropPath.Get(), filedropUUID, fileName) if err := os.WriteFile(p, by, 0644); err != nil { logrus.Error(err) return c.NoContent(http.StatusInternalServerError) @@ -271,7 +271,7 @@ func FileDropDkfDownloadHandler(c echo.Context) error { } maxChunkSize := int64(2 << 20) // 2MB - f, err := os.Open(filepath.Join(config.Global.ProjectFiledropPath(), filedrop.FileName)) + f, err := os.Open(filepath.Join(config.Global.ProjectFiledropPath.Get(), filedrop.FileName)) if err != nil { logrus.Error(err) return c.NoContent(http.StatusInternalServerError) @@ -330,7 +330,7 @@ func FileDropDownloadHandler(c echo.Context) error { } fileName := c.Param("fileName") - if !utils.FileExists(filepath.Join(config.Global.ProjectDownloadsPath(), fileName)) { + if !utils.FileExists(filepath.Join(config.Global.ProjectDownloadsPath.Get(), fileName)) { logrus.Error(fileName + " does not exists") return c.Redirect(http.StatusFound, "/") } @@ -365,7 +365,7 @@ func FileDropDownloadHandler(c echo.Context) error { logrus.Error(err) } - f, err := os.Open(filepath.Join(config.Global.ProjectDownloadsPath(), fileName)) + f, err := os.Open(filepath.Join(config.Global.ProjectDownloadsPath.Get(), fileName)) if err != nil { return c.Redirect(http.StatusFound, "/") } diff --git a/pkg/web/handlers/interceptors/slashInterceptor.go b/pkg/web/handlers/interceptors/slashInterceptor.go @@ -1724,8 +1724,8 @@ func handleNewMeme(c *command.Command) (handled bool) { return true } slug := m[1] - oldPath := filepath.Join(config.Global.ProjectUploadsPath(), c.Upload.FileName) - newPath := filepath.Join(config.Global.ProjectMemesPath(), c.Upload.FileName) + oldPath := filepath.Join(config.Global.ProjectUploadsPath.Get(), c.Upload.FileName) + newPath := filepath.Join(config.Global.ProjectMemesPath.Get(), c.Upload.FileName) _ = os.Rename(oldPath, newPath) if err := c.DB.DB().Delete(&c.Upload).Error; err != nil { diff --git a/pkg/web/handlers/poker/poker.go b/pkg/web/handlers/poker/poker.go @@ -5,6 +5,7 @@ import ( "dkforest/pkg/database" "dkforest/pkg/pubsub" "dkforest/pkg/utils" + "dkforest/pkg/utils/rwmtx" hutils "dkforest/pkg/web/handlers/utils" "errors" "fmt" @@ -91,7 +92,7 @@ func (p *Poker) newGame(db *database.DkfDB, roomID RoomID, pokerTableID int64, PokerTableMinBet: pokerTableMinBet, pokerTableIsTest: pokerTableIsTest, playersEventCh: make(chan playerEvent), - Players: utils.NewRWMtx(make([]*seatedPlayer, NbPlayers)), + Players: rwmtx.New(make([]*seatedPlayer, NbPlayers)), dealerSeatIdx: atomic.Int32{}, } g.dealerSeatIdx.Store(-1) @@ -127,12 +128,12 @@ func (e playerEvent) getAction() PlayerAction { var PokerInstance = newPoker() type ongoingGame struct { - logEvents utils.RWMtx[[]LogEvent] + logEvents rwmtx.RWMtx[[]LogEvent] deck []string players []*pokerPlayer - events utils.RWMtx[[]PokerEvent] - waitTurnEvent utils.RWMtx[PokerWaitTurnEvent] - autoActionEvent utils.RWMtx[AutoActionEvent] + events rwmtx.RWMtx[[]PokerEvent] + waitTurnEvent rwmtx.RWMtx[PokerWaitTurnEvent] + autoActionEvent rwmtx.RWMtx[AutoActionEvent] createdAt time.Time mainPot atomic.Uint64 communityCards []string @@ -142,7 +143,7 @@ type seatedPlayer struct { seatIdx int userID database.UserID username database.Username - cash utils.RWMtx[database.PokerChip] + cash rwmtx.RWMtx[database.PokerChip] lastActionTS time.Time } @@ -158,8 +159,8 @@ func (p *seatedPlayer) isEligible(pokerTableMinBet database.PokerChip) bool { type pokerPlayer struct { *seatedPlayer - bet utils.RWMtx[database.PokerChip] - cards utils.RWMtx[[]playerCard] + bet rwmtx.RWMtx[database.PokerChip] + cards rwmtx.RWMtx[[]playerCard] folded atomic.Bool unsit atomic.Bool gameBet database.PokerChip @@ -227,7 +228,7 @@ type playerCard struct { } type PokerGame struct { - Players utils.RWMtx[[]*seatedPlayer] + Players rwmtx.RWMtx[[]*seatedPlayer] ongoing *ongoingGame db *database.DkfDB roomID RoomID @@ -508,7 +509,7 @@ func (g *PokerGame) Sit(userID database.UserID, username database.Username, pos if (*gPlayers)[pos] != nil { return errors.New("seat already taken") } - (*gPlayers)[pos] = &seatedPlayer{seatIdx: pos, userID: userID, username: username, cash: utils.NewRWMtx(tableAccount.Amount), lastActionTS: time.Now()} + (*gPlayers)[pos] = &seatedPlayer{seatIdx: pos, userID: userID, username: username, cash: rwmtx.New(tableAccount.Amount), lastActionTS: time.Now()} PokerPubSub.Pub(g.roomID.Topic(), PokerSeatTakenEvent{}) g.newLogEvent(fmt.Sprintf("%s sit", username.String())) @@ -573,7 +574,7 @@ func newOngoing(g *PokerGame) *ongoingGame { return &ongoingGame{ deck: generateDeck(), players: players, - waitTurnEvent: utils.NewRWMtx(PokerWaitTurnEvent{Idx: -1}), + waitTurnEvent: rwmtx.New(PokerWaitTurnEvent{Idx: -1}), createdAt: time.Now(), } } diff --git a/pkg/web/handlers/utils/utils.go b/pkg/web/handlers/utils/utils.go @@ -38,8 +38,8 @@ func CreateCookie(name, value string, maxAge int64) *http.Cookie { cookie := &http.Cookie{ Name: name, Value: value, - Domain: config.Global.CookieDomain(), - Secure: config.Global.CookieSecure(), + Domain: config.Global.CookieDomain.Get(), + Secure: config.Global.CookieSecure.Get(), Path: "/", HttpOnly: true, MaxAge: int(maxAge), diff --git a/pkg/web/middlewares/middlewares.go b/pkg/web/middlewares/middlewares.go @@ -170,10 +170,10 @@ func AuthRateLimitMiddleware(period time.Duration, limit int64) echo.MiddlewareF func CSRFMiddleware() echo.MiddlewareFunc { csrfConfig := CSRFConfig{ TokenLookup: "form:csrf", - CookieDomain: config.Global.CookieDomain(), + CookieDomain: config.Global.CookieDomain.Get(), CookiePath: "/", CookieHTTPOnly: true, - CookieSecure: config.Global.CookieSecure(), + CookieSecure: config.Global.CookieSecure.Get(), CookieMaxAge: utils.OneMonthSecs, SameSite: http.SameSiteLaxMode, Skipper: func(c echo.Context) bool {