1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-02 10:56:25 -07:00

Add migration stuff for filter tables

This commit is contained in:
Eggbertx 2024-08-10 20:01:33 -07:00
parent c7f15e3d25
commit e12b2fb982
19 changed files with 295 additions and 47 deletions

View file

@ -38,8 +38,8 @@ release_files = (
"README.md", "README.md",
) )
GOCHAN_VERSION = "3.10.2" GOCHAN_VERSION = "3.11.0"
DATABASE_VERSION = "3" # stored in DBNAME.DBPREFIXdatabase_version DATABASE_VERSION = "4" # stored in DBNAME.DBPREFIXdatabase_version
PATH_NOTHING = -1 PATH_NOTHING = -1
PATH_UNKNOWN = 0 PATH_UNKNOWN = 0

View file

@ -0,0 +1,180 @@
package common
import (
"context"
"database/sql"
"os"
"strings"
"time"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gcsql"
)
// Used for db version 4 upgrade to create the filter tables from the respective SQL init file
func AddFilterTables(db *gcsql.GCDB, ctx context.Context, tx *sql.Tx, sqlConfig *config.SQLConfig) error {
filePath, err := getInitFilePath("initdb_" + sqlConfig.DBtype + ".sql")
if err != nil {
return err
}
ba, err := os.ReadFile(filePath)
if err != nil {
return err
}
sqlStr := commentRemover.ReplaceAllString(string(ba), " ")
sqlArr := strings.Split(sqlStr, ";")
for _, stmtStr := range sqlArr {
stmtStr = strings.TrimSpace(stmtStr)
if !strings.HasPrefix(stmtStr, "CREATE TABLE DBPREFIXfilter") {
continue
}
if _, err = db.ExecContextSQL(ctx, tx, stmtStr); err != nil {
return err
}
}
return nil
}
func MigrateFileBans(db *gcsql.GCDB, ctx context.Context, tx *sql.Tx, cfg *config.SQLConfig) error {
rows, err := db.QueryContextSQL(ctx, nil, `SELECT board_id,staff_id,staff_note,issued_at,checksum,fingerprinter,ban_ip,ban_ip_message FROM DBPREFIXfile_ban`)
if err != nil {
return err
}
var fBanBoardID *int
var fBanStaffID int
var fBanStaffNote string
var fBanIssuedAt time.Time
var fBanChecksum string
var fBanFingerprinter *string
var fBanBanIP bool
var fBanBanIPMessage *string
var matchAction string
var detail string
var filterID int
var field string
for rows.Next() {
if err = rows.Scan(
&fBanBoardID, &fBanStaffID, &fBanStaffNote, &fBanIssuedAt, &fBanChecksum, &fBanFingerprinter, &fBanBanIP, &fBanBanIPMessage,
); err != nil {
return err
}
if fBanBanIP {
matchAction = "ban"
} else {
matchAction = "reject"
}
if fBanBanIPMessage == nil {
detail = ""
} else {
detail = *fBanBanIPMessage
}
if _, err = db.ExecContextSQL(ctx, tx,
`INSERT INTO DBPREFIXfilters(staff_id, staff_note, issued_at, match_action, match_detail) VALUES(?,?,?,?,?)`,
fBanStaffID, fBanStaffNote, fBanIssuedAt, matchAction, detail); err != nil {
return err
}
if err = db.QueryRowContextSQL(ctx, tx, `SELECT MAX(id) FROM DBPREFIXfilters`, nil, []any{&filterID}); err != nil {
return err
}
if fBanBoardID != nil {
if _, err = db.ExecContextSQL(ctx, tx,
`INSERT INTO DBPREFIXfilter_boards(filter_id, board_id) VALUES(?,?)`, filterID, *fBanBoardID,
); err != nil {
return err
}
}
if fBanFingerprinter != nil {
field = *fBanFingerprinter
}
if field == "" {
field = "checksum"
}
if _, err = db.ExecContextSQL(ctx, tx,
`INSERT INTO DBPREFIXfilter_conditions(filter_id,is_regex,search,field) VALUES(?,?,?,?)`, filterID, false, fBanChecksum, field,
); err != nil {
return err
}
}
return nil
}
func MigrateFilenameBans(db *gcsql.GCDB, ctx context.Context, tx *sql.Tx, cfg *config.SQLConfig) error {
rows, err := db.QueryContextSQL(ctx, nil, `SELECT board_id,staff_id,staff_note,issued_at,filename,is_regex FROM DBPREFIXfilename_ban`)
if err != nil {
return err
}
var fnBanBoardID *int
var fnBanStaffID int
var fnBanStaffNote string
var fnBanIssuedAt time.Time
var fnBanFilename string
var fnBanIsRegex bool
var filterID int
for rows.Next() {
if err = rows.Scan(
&fnBanBoardID, &fnBanStaffID, &fnBanStaffNote, &fnBanIssuedAt, &fnBanFilename, &fnBanIsRegex,
); err != nil {
return err
}
if _, err = db.ExecContextSQL(ctx, tx,
`INSERT INTO DBPREFIXfilters(staff_id, staff_note, issued_at, match_action, match_detail) VALUES(?,?,?,?,?)`,
fnBanStaffID, fnBanStaffNote, fnBanIssuedAt, "reject", "",
); err != nil {
return err
}
if err = db.QueryRowContextSQL(ctx, tx, `SELECT MAX(id) FROM DBPREFIXfilters`, nil, []any{&filterID}); err != nil {
return err
}
if _, err = db.ExecContextSQL(ctx, tx,
`INSERT INTO DBPREFIXfilter_conditions(filter_id,is_regex,search,field) VALUES(?,?,?,?)`,
filterID, fnBanIsRegex, fnBanFilename, "filename",
); err != nil {
return err
}
}
return nil
}
func MigrateUsernameBans(db *gcsql.GCDB, ctx context.Context, tx *sql.Tx, cfg *config.SQLConfig) error {
rows, err := db.QueryContextSQL(ctx, nil, `SELECT board_id,staff_id,staff_note,issued_at,username,is_regex FROM DBPREFIXusername_ban`)
if err != nil {
return err
}
var unBanBoardID *int
var unBanStaffID int
var unBanStaffNote string
var unBanIssuedAt time.Time
var unBanUsername string
var unBanIsRegex bool
var filterID int
for rows.Next() {
if err = rows.Scan(
&unBanBoardID, &unBanStaffID, &unBanStaffNote, &unBanIssuedAt, &unBanUsername, &unBanIsRegex,
); err != nil {
return err
}
if _, err = db.ExecContextSQL(ctx, tx,
`INSERT INTO DBPREFIXfilters(staff_id, staff_note, issued_at, match_action, match_detail) VALUES(?,?,?,?,?)`,
unBanStaffID, unBanStaffNote, unBanIssuedAt, "reject", "",
); err != nil {
return err
}
if err = db.QueryRowContextSQL(ctx, tx, `SELECT MAX(id) FROM DBPREFIXfilters`, nil, []any{&filterID}); err != nil {
return err
}
if _, err = db.ExecContextSQL(ctx, tx,
`INSERT INTO DBPREFIXfilter_conditions(filter_id,is_regex,search,field) VALUES(?,?,?,?)`,
filterID, unBanIsRegex, unBanUsername, "name",
); err != nil {
return err
}
}
return nil
}

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"path"
"regexp" "regexp"
"strings" "strings"
@ -49,6 +50,30 @@ func ColumnType(db *gcsql.GCDB, tx *sql.Tx, columnName string, tableName string,
return dataType, err return dataType, err
} }
// TableExists returns true if the given table exists in the given database, and an error if one occured
func TableExists(db *gcsql.GCDB, tx *sql.Tx, tableName string, sqlConfig *config.SQLConfig) (bool, error) {
tableName = strings.ReplaceAll(tableName, "DBPREFIX", sqlConfig.DBprefix)
dbName := sqlConfig.DBname
var query string
var params []any
switch sqlConfig.DBtype {
case "mysql":
query = `SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?`
params = []any{dbName, tableName}
case "postgresql":
query = `SELECT COUNT(*) FROM information_schema.TABLES WHERE table_catalog = ? AND table_name = ?`
params = []any{dbName, tableName}
case "sqlite3":
query = `SELECT COUNT(*) FROM sqlite_master WHERE name = ? AND type = 'table'`
params = []any{tableName}
default:
return false, gcsql.ErrUnsupportedDB
}
var count int
err := db.QueryRowTxSQL(tx, query, params, []any{&count})
return count == 1, err
}
// IsStringType returns true if the given column data type is TEXT or VARCHAR // IsStringType returns true if the given column data type is TEXT or VARCHAR
func IsStringType(dataType string) bool { func IsStringType(dataType string) bool {
lower := strings.ToLower(dataType) lower := strings.ToLower(dataType)
@ -75,13 +100,21 @@ func RunSQLFile(path string, db *gcsql.GCDB) error {
return nil return nil
} }
func InitDB(initFile string, db *gcsql.GCDB) error { func getInitFilePath(initFile string) (string, error) {
filePath := gcutil.FindResource(initFile, filePath := gcutil.FindResource(initFile,
"/usr/local/share/gochan/"+initFile, path.Join("./sql", initFile),
"/usr/share/gochan/"+initFile) path.Join("/usr/local/share/gochan", initFile),
path.Join("/usr/share/gochan", initFile))
if filePath == "" { if filePath == "" {
return fmt.Errorf( return "", fmt.Errorf("missing SQL database initialization file (%s), please reinstall gochan", initFile)
"SQL database initialization file (%s) missing. Please reinstall gochan-migration", initFile) }
return filePath, nil
}
func InitDB(initFile string, db *gcsql.GCDB) error {
filePath, err := getInitFilePath(initFile)
if err != nil {
return err
} }
return RunSQLFile(filePath, db) return RunSQLFile(filePath, db)

View file

@ -11,14 +11,12 @@ import (
"github.com/gochan-org/gochan/pkg/gcutil" "github.com/gochan-org/gochan/pkg/gcutil"
) )
const (
// if the database version is less than this, it is assumed to be out of date, and the schema needs to be adjusted
latestDatabaseVersion = 3
)
type GCDatabaseUpdater struct { type GCDatabaseUpdater struct {
options *common.MigrationOptions options *common.MigrationOptions
db *gcsql.GCDB db *gcsql.GCDB
// if the database version is less than TargetDBVer, it is assumed to be out of date, and the schema needs to be adjusted.
// It is expected to be set by the build script
TargetDBVer int
} }
func (dbu *GCDatabaseUpdater) Init(options *common.MigrationOptions) error { func (dbu *GCDatabaseUpdater) Init(options *common.MigrationOptions) error {
@ -36,12 +34,12 @@ func (dbu *GCDatabaseUpdater) IsMigrated() (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
if currentDatabaseVersion == latestDatabaseVersion { if currentDatabaseVersion == dbu.TargetDBVer {
return true, nil return true, nil
} }
if currentDatabaseVersion > latestDatabaseVersion { if currentDatabaseVersion > dbu.TargetDBVer {
return false, fmt.Errorf("database layout is ahead of current version (%d), target version: %d", return false, fmt.Errorf("database layout is ahead of current version (%d), target version: %d",
currentDatabaseVersion, latestDatabaseVersion) currentDatabaseVersion, dbu.TargetDBVer)
} }
return false, nil return false, nil
} }
@ -75,8 +73,37 @@ func (dbu *GCDatabaseUpdater) MigrateDB() (bool, error) {
return false, err return false, err
} }
filterTableExists, err := common.TableExists(dbu.db, nil, "DBPREFIXfilters", &sqlConfig)
if err != nil {
return false, err
}
if !filterTableExists {
if err = common.AddFilterTables(dbu.db, ctx, tx, &sqlConfig); err != nil {
return false, err
}
if err = common.MigrateFileBans(dbu.db, ctx, tx, &sqlConfig); err != nil {
return false, err
}
if err = common.MigrateFilenameBans(dbu.db, ctx, tx, &sqlConfig); err != nil {
return false, err
}
if err = common.MigrateUsernameBans(dbu.db, ctx, tx, &sqlConfig); err != nil {
return false, err
}
if _, err = dbu.db.ExecContextSQL(ctx, tx, `DROP TABLE DBPREFIXfile_ban`); err != nil {
return false, err
}
if _, err = dbu.db.ExecContextSQL(ctx, tx, `DROP TABLE DBPREFIXfilename_ban`); err != nil {
return false, err
}
if _, err = dbu.db.ExecContextSQL(ctx, tx, `DROP TABLE DBPREFIXfile_ban`); err != nil {
return false, err
}
}
query := `UPDATE DBPREFIXdatabase_version SET version = ? WHERE component = 'gochan'` query := `UPDATE DBPREFIXdatabase_version SET version = ? WHERE component = 'gochan'`
_, err = dbu.db.ExecTxSQL(tx, query, latestDatabaseVersion) _, err = dbu.db.ExecTxSQL(tx, query, dbu.TargetDBVer)
if err != nil { if err != nil {
return false, err return false, err
} }

View file

@ -4,6 +4,7 @@ import (
"flag" "flag"
"log" "log"
"os" "os"
"strconv"
"github.com/gochan-org/gochan/cmd/gochan-migration/internal/common" "github.com/gochan-org/gochan/cmd/gochan-migration/internal/common"
"github.com/gochan-org/gochan/cmd/gochan-migration/internal/gcupdate" "github.com/gochan-org/gochan/cmd/gochan-migration/internal/gcupdate"
@ -15,10 +16,7 @@ import (
const ( const (
banner = `Welcome to the gochan database migration tool for gochan %s! banner = `Welcome to the gochan database migration tool for gochan %s!
This migration tool is currently unstable, and will likely go through Make sure you check the README and/or the -h command line flag, and back up your current database before you use it.
several changes before it can be considered "stable", so make sure you check
the README and/or the -h command line flag before you use it.
` `
migrateCompleteTxt = `Database migration successful! migrateCompleteTxt = `Database migration successful!
To migrate the uploads for each board, move or copy the uploads to /path/to/gochan/document/root/<boardname>/src/ To migrate the uploads for each board, move or copy the uploads to /path/to/gochan/document/root/<boardname>/src/
@ -30,8 +28,9 @@ for the threads and board pages`
) )
var ( var (
versionStr string versionStr string
migrator common.DBMigrator migrator common.DBMigrator
dbVersionStr string
) )
func cleanup() int { func cleanup() int {
@ -87,7 +86,13 @@ func main() {
log.Printf(banner, versionStr) log.Printf(banner, versionStr)
switch options.ChanType { switch options.ChanType {
case "gcupdate": case "gcupdate":
migrator = &gcupdate.GCDatabaseUpdater{} targetDBVer, err := strconv.Atoi(dbVersionStr)
if err != nil {
log.Fatalf("Invalid database version string %q, unable to parse to int", dbVersionStr)
}
migrator = &gcupdate.GCDatabaseUpdater{
TargetDBVer: targetDBVer,
}
case "pre2021": case "pre2021":
migrator = &pre2021.Pre2021Migrator{} migrator = &pre2021.Pre2021Migrator{}
case "kusabax": case "kusabax":
@ -108,7 +113,7 @@ func main() {
if err != nil { if err != nil {
log.Fatalf("Failed to connect to the database: %s", err.Error()) log.Fatalf("Failed to connect to the database: %s", err.Error())
} }
if err = gcsql.CheckAndInitializeDatabase(sqlCfg.DBtype); err != nil { if err = gcsql.CheckAndInitializeDatabase(sqlCfg.DBtype, dbVersionStr); err != nil {
log.Fatalf("Failed to initialize the database: %s", err.Error()) log.Fatalf("Failed to initialize the database: %s", err.Error())
} }
} }

View file

@ -24,7 +24,8 @@ import (
) )
var ( var (
versionStr string versionStr string
dbVersionStr string
) )
func cleanup() { func cleanup() {
@ -70,7 +71,7 @@ func main() {
Str("dbType", systemCritical.DBtype). Str("dbType", systemCritical.DBtype).
Msg("Connected to database") Msg("Connected to database")
if err = gcsql.CheckAndInitializeDatabase(systemCritical.DBtype); err != nil { if err = gcsql.CheckAndInitializeDatabase(systemCritical.DBtype, dbVersionStr); err != nil {
cleanup() cleanup()
gcutil.LogFatal().Err(err).Msg("Failed to initialize the database") gcutil.LogFatal().Err(err).Msg("Failed to initialize the database")
} }

View file

@ -1,12 +1,12 @@
{ {
"name": "gochan.js", "name": "gochan.js",
"version": "3.10.2", "version": "3.11.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "gochan.js", "name": "gochan.js",
"version": "3.10.2", "version": "3.11.0",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"jquery": "^3.7.1", "jquery": "^3.7.1",

View file

@ -1,6 +1,6 @@
{ {
"name": "gochan.js", "name": "gochan.js",
"version": "3.10.2", "version": "3.11.0",
"description": "", "description": "",
"main": "./ts/main.ts", "main": "./ts/main.ts",
"private": true, "private": true,

View file

@ -7,6 +7,6 @@
<h1>404: File not found</h1> <h1>404: File not found</h1>
<img src="/error/lol 404.gif" alt="lol 404"> <img src="/error/lol 404.gif" alt="lol 404">
<p>The requested file could not be found on this server.</p> <p>The requested file could not be found on this server.</p>
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.10.2 <hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.11.0
</body> </body>
</html> </html>

View file

@ -7,6 +7,6 @@
<h1>Error 500: Internal Server error</h1> <h1>Error 500: Internal Server error</h1>
<img src="/error/server500.gif" alt="server burning"> <img src="/error/server500.gif" alt="server burning">
<p>The server encountered an error while trying to serve the page, and we apologize for the inconvenience. The <a href="https://en.wikipedia.org/wiki/Idiot">system administrator</a> will try to fix things as soon they get around to it, whenever that is. Hopefully soon.</p> <p>The server encountered an error while trying to serve the page, and we apologize for the inconvenience. The <a href="https://en.wikipedia.org/wiki/Idiot">system administrator</a> will try to fix things as soon they get around to it, whenever that is. Hopefully soon.</p>
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.10.2 <hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.11.0
</body> </body>
</html> </html>

View file

@ -7,6 +7,6 @@
<h1>Error 502: Bad gateway</h1> <h1>Error 502: Bad gateway</h1>
<img src="/error/server500.gif" alt="server burning"> <img src="/error/server500.gif" alt="server burning">
<p>The server encountered an error while trying to serve the page, and we apologize for the inconvenience. The <a href="https://en.wikipedia.org/wiki/Idiot">system administrator</a> will try to fix things as soon they get around to it, whenever that is. Hopefully soon.</p> <p>The server encountered an error while trying to serve the page, and we apologize for the inconvenience. The <a href="https://en.wikipedia.org/wiki/Idiot">system administrator</a> will try to fix things as soon they get around to it, whenever that is. Hopefully soon.</p>
<hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.10.2 <hr/>Site powered by <a href="https://github.com/gochan-org/gochan" target="_blank">Gochan</a> v3.11.0
</body> </body>
</html> </html>

View file

@ -25,7 +25,7 @@ func TestBuildJS(t *testing.T) {
} }
outDir := t.TempDir() outDir := t.TempDir()
config.SetVersion("3.10.2") config.SetVersion("3.11.0")
systemCriticalCfg := config.GetSystemCriticalConfig() systemCriticalCfg := config.GetSystemCriticalConfig()
systemCriticalCfg.DocumentRoot = path.Join(outDir, "html") systemCriticalCfg.DocumentRoot = path.Join(outDir, "html")
systemCriticalCfg.TemplateDir = path.Join(testRoot, "templates") systemCriticalCfg.TemplateDir = path.Join(testRoot, "templates")
@ -156,7 +156,7 @@ func TestBuildFrontPage(t *testing.T) {
} }
t.Run(driver, func(t *testing.T) { t.Run(driver, func(t *testing.T) {
outDir := t.TempDir() outDir := t.TempDir()
config.SetVersion("3.10.2") config.SetVersion("3.11.0")
systemCriticalCfg := config.GetSystemCriticalConfig() systemCriticalCfg := config.GetSystemCriticalConfig()
systemCriticalCfg.DocumentRoot = path.Join(outDir, "html") systemCriticalCfg.DocumentRoot = path.Join(outDir, "html")
systemCriticalCfg.TemplateDir = path.Join(testRoot, "templates") systemCriticalCfg.TemplateDir = path.Join(testRoot, "templates")

View file

@ -7,7 +7,7 @@ var defaultStyle = "test1.css";
var webroot = "/chan"; var webroot = "/chan";
var serverTZ = 8; var serverTZ = 8;
var fileTypes = [];` var fileTypes = [];`
expectedMinifiedFront = `<!doctype html><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Gochan</title><link rel=stylesheet href=/chan/css/global.css><link id=theme rel=stylesheet href=/chan/css/test1.css><link rel="shortcut icon" href=/chan/favicon.png><script src=/chan/js/consts.js></script><script src=/chan/js/gochan.js></script><div id=topbar><div class=topbar-section><a href=/chan/ class=topbar-item>home</a></div><div class=topbar-section><a href=/chan/test/ class=topbar-item title="Testing board">/test/</a><a href=/chan/test2/ class=topbar-item title="Testing board 2">/test2/</a></div></div><div id=content><div id=top-pane><span id=site-title>Gochan</span><br><span id=site-slogan></span></div><br><div id=frontpage><div class=section-block style="margin: 16px 64px 16px 64px;"><div class="section-body front-intro">Welcome to Gochan!</div></div><div class=section-block><div class=section-title-block><b>Boards</b></div><div class=section-body><ul style="float:left; list-style: none"><li style="text-align: center; font-weight: bold"><b><u>Main</u></b><li><a href=/chan/test/ title="Board for testing description">/test/</a> — Testing board<li><a href=/chan/test2/ title="Board for testing description 2">/test2/</a> — Testing board 2</ul></div></div><div class=section-block><div class=section-title-block><b>Recent Posts</b></div><div class=section-body><div id=recent-posts><div class=recent-post><a href=/chan/test/res/1.html#1 class=front-reply target=_blank><img src=/chan/test/thumb alt="post thumbnail"></a><br><br><a href=/chan/test/>/test/</a><hr>message_raw</div><div class=recent-post><a href=/chan/test/res/1.html#2 class=front-reply target=_blank><img src=/chan/test/thumb alt="post thumbnail"></a><br><br><a href=/chan/test/>/test/</a><hr>message_raw</div></div></div></div></div><div id=footer>Powered by <a href=http://github.com/gochan-org/gochan/>Gochan 3.10.2</a><br></div></div>` expectedMinifiedFront = `<!doctype html><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Gochan</title><link rel=stylesheet href=/chan/css/global.css><link id=theme rel=stylesheet href=/chan/css/test1.css><link rel="shortcut icon" href=/chan/favicon.png><script src=/chan/js/consts.js></script><script src=/chan/js/gochan.js></script><div id=topbar><div class=topbar-section><a href=/chan/ class=topbar-item>home</a></div><div class=topbar-section><a href=/chan/test/ class=topbar-item title="Testing board">/test/</a><a href=/chan/test2/ class=topbar-item title="Testing board 2">/test2/</a></div></div><div id=content><div id=top-pane><span id=site-title>Gochan</span><br><span id=site-slogan></span></div><br><div id=frontpage><div class=section-block style="margin: 16px 64px 16px 64px;"><div class="section-body front-intro">Welcome to Gochan!</div></div><div class=section-block><div class=section-title-block><b>Boards</b></div><div class=section-body><ul style="float:left; list-style: none"><li style="text-align: center; font-weight: bold"><b><u>Main</u></b><li><a href=/chan/test/ title="Board for testing description">/test/</a> — Testing board<li><a href=/chan/test2/ title="Board for testing description 2">/test2/</a> — Testing board 2</ul></div></div><div class=section-block><div class=section-title-block><b>Recent Posts</b></div><div class=section-body><div id=recent-posts><div class=recent-post><a href=/chan/test/res/1.html#1 class=front-reply target=_blank><img src=/chan/test/thumb alt="post thumbnail"></a><br><br><a href=/chan/test/>/test/</a><hr>message_raw</div><div class=recent-post><a href=/chan/test/res/1.html#2 class=front-reply target=_blank><img src=/chan/test/thumb alt="post thumbnail"></a><br><br><a href=/chan/test/>/test/</a><hr>message_raw</div></div></div></div></div><div id=footer>Powered by <a href=http://github.com/gochan-org/gochan/>Gochan 3.11.0</a><br></div></div>`
expectedUnminifiedFront = `<!DOCTYPE html> expectedUnminifiedFront = `<!DOCTYPE html>
<html> <html>
<head> <head>
@ -74,7 +74,7 @@ var fileTypes = [];`
</div> </div>
</div> </div>
<div id="footer"> <div id="footer">
Powered by <a href="http://github.com/gochan-org/gochan/">Gochan 3.10.2</a><br /> Powered by <a href="http://github.com/gochan-org/gochan/">Gochan 3.11.0</a><br />
</div> </div>
</div> </div>
</body> </body>

View file

@ -3,6 +3,7 @@ package gcsql
import ( import (
"errors" "errors"
"fmt" "fmt"
"strconv"
"github.com/gochan-org/gochan/pkg/config" "github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gcutil" "github.com/gochan-org/gochan/pkg/gcutil"
@ -15,17 +16,16 @@ const (
DBModernButBehind DBModernButBehind
DBUpToDate DBUpToDate
DBModernButAhead DBModernButAhead
targetDatabaseVersion = 3
) )
var ( var (
// ErrInvalidVersion is used when the db contains a database_version table // ErrInvalidVersion is used when the db contains a database_version table
// but zero or more than one versions were found // but zero or more than one versions were found
ErrInvalidVersion = errors.New("database contains database_version table but zero or more than one versions were found") ErrInvalidVersion = errors.New("database contains database_version table but zero or more than one versions were found")
ErrCorruptedDB = errors.New("database contains gochan prefixed tables but is missing versioning tables (possibly corrupted)") ErrCorruptedDB = errors.New("database contains gochan prefixed tables but is missing versioning tables (possibly corrupted)")
ErrDeprecatedDB = errors.New("database layout is deprecated, please run gochan-migration -updatedb") ErrDeprecatedDB = errors.New("database layout is deprecated, please run gochan-migration -updatedb")
ErrInvalidDBVersion = errors.New("invalid version flag returned by GetCompleteDatabaseVersion()") ErrInvalidDBVersion = errors.New("invalid version flag returned by GetCompleteDatabaseVersion()")
targetDatabaseVersion = 3
) )
func initDB(initFile string) error { func initDB(initFile string) error {
@ -83,7 +83,12 @@ func GetCompleteDatabaseVersion() (dbVersion, dbFlag int, err error) {
} }
// CheckAndInitializeDatabase checks the validity of the database and initialises it if it is empty // CheckAndInitializeDatabase checks the validity of the database and initialises it if it is empty
func CheckAndInitializeDatabase(dbType string) error { func CheckAndInitializeDatabase(dbType string, targetDbVersionStr string) (err error) {
targetDatabaseVersion, err = strconv.Atoi(targetDbVersionStr)
if err != nil {
return err
}
dbVersion, versionFlag, err := GetCompleteDatabaseVersion() dbVersion, versionFlag, err := GetCompleteDatabaseVersion()
if err != nil { if err != nil {
return err return err

View file

@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
CREATE TABLE DBPREFIXfilters( CREATE TABLE DBPREFIXfilters(
id {serial pk}, id {serial pk},
board_dirs VARCHAR(255) DEFAULT '*',
staff_id {fk to serial}, staff_id {fk to serial},
staff_note VARCHAR(255) NOT NULL, staff_note VARCHAR(255) NOT NULL,
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View file

@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
CREATE TABLE DBPREFIXfilters( CREATE TABLE DBPREFIXfilters(
id BIGINT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY, id BIGINT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY,
board_dirs VARCHAR(255) DEFAULT '*',
staff_id BIGINT, staff_id BIGINT,
staff_note VARCHAR(255) NOT NULL, staff_note VARCHAR(255) NOT NULL,
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View file

@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
CREATE TABLE DBPREFIXfilters( CREATE TABLE DBPREFIXfilters(
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
board_dirs VARCHAR(255) DEFAULT '*',
staff_id BIGINT, staff_id BIGINT,
staff_note VARCHAR(255) NOT NULL, staff_note VARCHAR(255) NOT NULL,
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View file

@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
CREATE TABLE DBPREFIXfilters( CREATE TABLE DBPREFIXfilters(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
board_dirs VARCHAR(255) DEFAULT '*',
staff_id BIGINT, staff_id BIGINT,
staff_note VARCHAR(255) NOT NULL, staff_note VARCHAR(255) NOT NULL,
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View file

@ -76,6 +76,7 @@
<tr> <tr>
<th>Actions</th><th>Filter action</th><th>Conditions</th><th>Staff</th><th>Last modified</th> <th>Actions</th><th>Filter action</th><th>Conditions</th><th>Staff</th><th>Last modified</th>
</tr> </tr>
<!-- TODO: replace dummy data with actual data -->
<tr> <tr>
<td> <td>
<a href="{{webPath `/manage/filters?edit=1`}}">Edit</a> | <a href="{{webPath `/manage/filters?delete=1`}}">Delete</a> <a href="{{webPath `/manage/filters?edit=1`}}">Edit</a> | <a href="{{webPath `/manage/filters?delete=1`}}">Delete</a>