From 242abb86455ccdc64b2e6fb79bc8fe4d144637b8 Mon Sep 17 00:00:00 2001 From: Yanislav Igonin Date: Wed, 17 Nov 2021 10:44:12 +0200 Subject: [PATCH] Feature - Migrator (#3) * feat: rename init migration * feat: add migration for is_archived field * fix: thread title wrap * fix: captcha checks after post validation now * fix * wip on migrate method * feat: decided to write own migrator * feat: add get files on folder func * wip * feat: add migrations table * feat: add migration method * doc * feat: query -> exec --- controllers/threads_controller.go | 44 ++++++------ db/db.go | 67 +++++++++++++++++++ files/get_files_in_folder.go | 40 +++++++++++ go.mod | 4 +- go.sum | 9 ++- main.go | 1 + migrations/000001_init.down.sql | 2 - migrations/{000001_init.up.sql => 1-init.sql} | 11 +-- migrations/2-posts_archivation.sql | 2 + static/styles/thread.css | 6 +- templates/thread.html | 2 +- 11 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 files/get_files_in_folder.go delete mode 100644 migrations/000001_init.down.sql rename migrations/{000001_init.up.sql => 1-init.sql} (83%) create mode 100644 migrations/2-posts_archivation.sql diff --git a/controllers/threads_controller.go b/controllers/threads_controller.go index 67b4e73..dc7dc15 100644 --- a/controllers/threads_controller.go +++ b/controllers/threads_controller.go @@ -101,17 +101,6 @@ func CreateThread(c *gin.Context) { return } - captchaID := form.Value["captchaId"][0] - captchaString := form.Value["captcha"][0] - isCaptchaValid := captcha.VerifyString(captchaID, captchaString) - if !isCaptchaValid { - errorHtmlData := Repositories.BadRequestHtmlData{ - Message: Repositories.InvalidCaptchaErrorMessage, - } - c.HTML(http.StatusInternalServerError, "400.html", errorHtmlData) - return - } - // TODO: dat shit crashes if no fields in request text := form.Value["text"][0] title := form.Value["title"][0] @@ -125,6 +114,17 @@ func CreateThread(c *gin.Context) { return } + captchaID := form.Value["captchaId"][0] + captchaString := form.Value["captcha"][0] + isCaptchaValid := captcha.VerifyString(captchaID, captchaString) + if !isCaptchaValid { + errorHtmlData := Repositories.BadRequestHtmlData{ + Message: Repositories.InvalidCaptchaErrorMessage, + } + c.HTML(http.StatusInternalServerError, "400.html", errorHtmlData) + return + } + conn, err := Db.Pool.Acquire(context.TODO()) if err != nil { log.Println("error:", err) @@ -225,17 +225,6 @@ func UpdateThread(c *gin.Context) { return } - captchaID := form.Value["captchaId"][0] - captchaString := form.Value["captcha"][0] - isCaptchaValid := captcha.VerifyString(captchaID, captchaString) - if !isCaptchaValid { - errorHtmlData := Repositories.BadRequestHtmlData{ - Message: Repositories.InvalidCaptchaErrorMessage, - } - c.HTML(http.StatusInternalServerError, "400.html", errorHtmlData) - return - } - // TODO: dat shit crashes if no fields in request text := form.Value["text"][0] filesInRequest := form.File["files"] @@ -248,6 +237,17 @@ func UpdateThread(c *gin.Context) { return } + captchaID := form.Value["captchaId"][0] + captchaString := form.Value["captcha"][0] + isCaptchaValid := captcha.VerifyString(captchaID, captchaString) + if !isCaptchaValid { + errorHtmlData := Repositories.BadRequestHtmlData{ + Message: Repositories.InvalidCaptchaErrorMessage, + } + c.HTML(http.StatusInternalServerError, "400.html", errorHtmlData) + return + } + isSageField := form.Value["sage"] var isSageString string if len(isSageField) != 0 { diff --git a/db/db.go b/db/db.go index e3edb7e..f43d287 100644 --- a/db/db.go +++ b/db/db.go @@ -3,14 +3,24 @@ package db import ( "context" "log" + "path/filepath" + "strconv" + "strings" Config "micrach/config" + Files "micrach/files" "github.com/jackc/pgx/v4/pgxpool" ) var Pool *pgxpool.Pool +type MigrationsMap map[int]string +type Migration struct { + ID int + Name string +} + func Init() { var err error Pool, err = pgxpool.Connect(context.TODO(), Config.Db.Url) @@ -21,3 +31,60 @@ func Init() { log.Println("database - online") } + +func Migrate() { + dbMigrations := getDbMigrations() + sqlMigrations := Files.GetFullFilePathsInFolder("migrations") + for _, m := range sqlMigrations { + filename := filepath.Base(m) + splitted := strings.Split(filename, "-") + id, err := strconv.Atoi(splitted[0]) + if err != nil { + log.Panicln(err) + } + // Get name without extension + name := strings.Split(splitted[1], ".")[0] + + _, isMigrationInDb := dbMigrations[id] + if !isMigrationInDb { + _, err := Pool.Exec(context.TODO(), Files.ReadFileText(m)) + if err != nil { + log.Panicln(err) + } + + sql := `INSERT INTO migrations (id, name) VALUES ($1, $2)` + _, err = Pool.Query(context.TODO(), sql, id, name) + if err != nil { + log.Panicln(err) + } + log.Println("database migration - " + name + " - online") + } + } + + log.Println("database migrations - online") +} + +func getDbMigrations() MigrationsMap { + sql := `SELECT id, name FROM migrations` + rows, err := Pool.Query(context.TODO(), sql) + if err != nil { + log.Panicln(err) + } + + if rows.Err() != nil { + log.Panicln(rows.Err()) + } + + migrationsMap := make(MigrationsMap) + for rows.Next() { + var m Migration + err = rows.Scan(&m.ID, &m.Name) + if err != nil { + log.Panicln(err) + } + + migrationsMap[m.ID] = m.Name + } + + return migrationsMap +} diff --git a/files/get_files_in_folder.go b/files/get_files_in_folder.go new file mode 100644 index 0000000..449f31e --- /dev/null +++ b/files/get_files_in_folder.go @@ -0,0 +1,40 @@ +package files + +import ( + "io/ioutil" + "log" + "os" + "path" +) + +// Reads folder and returns full file paths slice +func GetFullFilePathsInFolder(folder string) []string { + currentPath, err := os.Getwd() + if err != nil { + log.Fatal(err) + } + + fullFolderPath := path.Join(currentPath, folder) + files, err := ioutil.ReadDir(fullFolderPath) + if err != nil { + log.Fatal(err) + } + + var paths []string + + for _, file := range files { + paths = append(paths, path.Join(fullFolderPath, file.Name())) + } + + return paths +} + +// Reads file contents by full path and returns string +func ReadFileText(fullFilePath string) string { + file, err := ioutil.ReadFile(fullFilePath) + if err != nil { + log.Fatal(err) + } + + return string(file) +} diff --git a/go.mod b/go.mod index a447df8..8dc38b9 100644 --- a/go.mod +++ b/go.mod @@ -7,18 +7,18 @@ require ( github.com/disintegration/imaging v1.6.2 github.com/gin-gonic/gin v1.7.4 github.com/go-playground/validator/v10 v10.9.0 // indirect - github.com/golang-migrate/migrate v3.5.4+incompatible // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/jackc/pgtype v1.8.1 github.com/jackc/pgx/v4 v4.13.0 github.com/jackc/puddle v1.1.4 // indirect github.com/joho/godotenv v1.3.0 github.com/json-iterator/go v1.1.12 // indirect + github.com/lib/pq v1.10.3 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/ugorji/go v1.2.6 // indirect github.com/ulule/limiter/v3 v3.8.0 - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/protobuf v1.27.1 // indirect diff --git a/go.sum b/go.sum index 88ce5ba..7d1a84f 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,6 @@ github.com/go-redis/redis/v8 v8.4.2/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hb github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA= -github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -137,8 +135,9 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= +github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -221,8 +220,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/main.go b/main.go index d6f0af2..d943847 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ import ( func main() { Config.Init() Db.Init() + Db.Migrate() defer Db.Pool.Close() gin.SetMode(Config.App.Env) if Config.App.SeedDb { diff --git a/migrations/000001_init.down.sql b/migrations/000001_init.down.sql deleted file mode 100644 index f79db12..0000000 --- a/migrations/000001_init.down.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP TABLE files; -DROP TABLE posts; diff --git a/migrations/000001_init.up.sql b/migrations/1-init.sql similarity index 83% rename from migrations/000001_init.up.sql rename to migrations/1-init.sql index a100acc..2201639 100644 --- a/migrations/000001_init.up.sql +++ b/migrations/1-init.sql @@ -1,5 +1,3 @@ --- UP --- Posts CREATE TABLE posts ( id SERIAL NOT NULL, @@ -19,8 +17,6 @@ CREATE TABLE posts PRIMARY KEY (id) ); - --- Files CREATE TABLE files ( id SERIAL PRIMARY KEY, @@ -31,3 +27,10 @@ CREATE TABLE files created_at TIMESTAMP DEFAULT NOW() NOT NULL, FOREIGN KEY (post_id) REFERENCES posts (id) ); + +CREATE TABLE migrations +( + id INT NOT NULL, + name VARCHAR NOT NULL, + created_at TIMESTAMP DEFAULT NOW() NOT NULL +) \ No newline at end of file diff --git a/migrations/2-posts_archivation.sql b/migrations/2-posts_archivation.sql new file mode 100644 index 0000000..8372110 --- /dev/null +++ b/migrations/2-posts_archivation.sql @@ -0,0 +1,2 @@ +ALTER TABLE posts +ADD COLUMN is_archived BOOLEAN DEFAULT false; diff --git a/static/styles/thread.css b/static/styles/thread.css index 60e698a..efa1902 100644 --- a/static/styles/thread.css +++ b/static/styles/thread.css @@ -3,4 +3,8 @@ } .thread-title-link:hover { text-decoration: underline; -} \ No newline at end of file +} + +.thread-title { + overflow-wrap: break-word; +} diff --git a/templates/thread.html b/templates/thread.html index 7822cf4..f463c2d 100644 --- a/templates/thread.html +++ b/templates/thread.html @@ -11,7 +11,7 @@ -

+

⤶ {{ if ne $FirstPost.Title "" }} {{$FirstPost.Title}}