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:
parent
c7f15e3d25
commit
e12b2fb982
19 changed files with 295 additions and 47 deletions
4
build.py
4
build.py
|
@ -38,8 +38,8 @@ release_files = (
|
|||
"README.md",
|
||||
)
|
||||
|
||||
GOCHAN_VERSION = "3.10.2"
|
||||
DATABASE_VERSION = "3" # stored in DBNAME.DBPREFIXdatabase_version
|
||||
GOCHAN_VERSION = "3.11.0"
|
||||
DATABASE_VERSION = "4" # stored in DBNAME.DBPREFIXdatabase_version
|
||||
|
||||
PATH_NOTHING = -1
|
||||
PATH_UNKNOWN = 0
|
||||
|
|
180
cmd/gochan-migration/internal/common/filters.go
Normal file
180
cmd/gochan-migration/internal/common/filters.go
Normal 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
|
||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
|
@ -49,6 +50,30 @@ func ColumnType(db *gcsql.GCDB, tx *sql.Tx, columnName string, tableName string,
|
|||
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
|
||||
func IsStringType(dataType string) bool {
|
||||
lower := strings.ToLower(dataType)
|
||||
|
@ -75,13 +100,21 @@ func RunSQLFile(path string, db *gcsql.GCDB) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func InitDB(initFile string, db *gcsql.GCDB) error {
|
||||
func getInitFilePath(initFile string) (string, error) {
|
||||
filePath := gcutil.FindResource(initFile,
|
||||
"/usr/local/share/gochan/"+initFile,
|
||||
"/usr/share/gochan/"+initFile)
|
||||
path.Join("./sql", initFile),
|
||||
path.Join("/usr/local/share/gochan", initFile),
|
||||
path.Join("/usr/share/gochan", initFile))
|
||||
if filePath == "" {
|
||||
return fmt.Errorf(
|
||||
"SQL database initialization file (%s) missing. Please reinstall gochan-migration", initFile)
|
||||
return "", fmt.Errorf("missing SQL database initialization file (%s), please reinstall gochan", 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)
|
||||
|
|
|
@ -11,14 +11,12 @@ import (
|
|||
"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 {
|
||||
options *common.MigrationOptions
|
||||
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 {
|
||||
|
@ -36,12 +34,12 @@ func (dbu *GCDatabaseUpdater) IsMigrated() (bool, error) {
|
|||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if currentDatabaseVersion == latestDatabaseVersion {
|
||||
if currentDatabaseVersion == dbu.TargetDBVer {
|
||||
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",
|
||||
currentDatabaseVersion, latestDatabaseVersion)
|
||||
currentDatabaseVersion, dbu.TargetDBVer)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
@ -75,8 +73,37 @@ func (dbu *GCDatabaseUpdater) MigrateDB() (bool, error) {
|
|||
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'`
|
||||
_, err = dbu.db.ExecTxSQL(tx, query, latestDatabaseVersion)
|
||||
_, err = dbu.db.ExecTxSQL(tx, query, dbu.TargetDBVer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/gochan-org/gochan/cmd/gochan-migration/internal/common"
|
||||
"github.com/gochan-org/gochan/cmd/gochan-migration/internal/gcupdate"
|
||||
|
@ -15,10 +16,7 @@ import (
|
|||
|
||||
const (
|
||||
banner = `Welcome to the gochan database migration tool for gochan %s!
|
||||
This migration tool is currently unstable, and will likely go through
|
||||
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.
|
||||
|
||||
Make sure you check the README and/or the -h command line flag, and back up your current database before you use it.
|
||||
`
|
||||
migrateCompleteTxt = `Database migration successful!
|
||||
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 (
|
||||
versionStr string
|
||||
migrator common.DBMigrator
|
||||
versionStr string
|
||||
migrator common.DBMigrator
|
||||
dbVersionStr string
|
||||
)
|
||||
|
||||
func cleanup() int {
|
||||
|
@ -87,7 +86,13 @@ func main() {
|
|||
log.Printf(banner, versionStr)
|
||||
switch options.ChanType {
|
||||
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":
|
||||
migrator = &pre2021.Pre2021Migrator{}
|
||||
case "kusabax":
|
||||
|
@ -108,7 +113,7 @@ func main() {
|
|||
if err != nil {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
versionStr string
|
||||
versionStr string
|
||||
dbVersionStr string
|
||||
)
|
||||
|
||||
func cleanup() {
|
||||
|
@ -70,7 +71,7 @@ func main() {
|
|||
Str("dbType", systemCritical.DBtype).
|
||||
Msg("Connected to database")
|
||||
|
||||
if err = gcsql.CheckAndInitializeDatabase(systemCritical.DBtype); err != nil {
|
||||
if err = gcsql.CheckAndInitializeDatabase(systemCritical.DBtype, dbVersionStr); err != nil {
|
||||
cleanup()
|
||||
gcutil.LogFatal().Err(err).Msg("Failed to initialize the database")
|
||||
}
|
||||
|
|
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "gochan.js",
|
||||
"version": "3.10.2",
|
||||
"version": "3.11.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gochan.js",
|
||||
"version": "3.10.2",
|
||||
"version": "3.11.0",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"jquery": "^3.7.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gochan.js",
|
||||
"version": "3.10.2",
|
||||
"version": "3.11.0",
|
||||
"description": "",
|
||||
"main": "./ts/main.ts",
|
||||
"private": true,
|
||||
|
|
|
@ -7,6 +7,6 @@
|
|||
<h1>404: File not found</h1>
|
||||
<img src="/error/lol 404.gif" alt="lol 404">
|
||||
<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>
|
||||
</html>
|
|
@ -7,6 +7,6 @@
|
|||
<h1>Error 500: Internal Server error</h1>
|
||||
<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>
|
||||
<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>
|
||||
</html>
|
|
@ -7,6 +7,6 @@
|
|||
<h1>Error 502: Bad gateway</h1>
|
||||
<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>
|
||||
<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>
|
||||
</html>
|
|
@ -25,7 +25,7 @@ func TestBuildJS(t *testing.T) {
|
|||
}
|
||||
|
||||
outDir := t.TempDir()
|
||||
config.SetVersion("3.10.2")
|
||||
config.SetVersion("3.11.0")
|
||||
systemCriticalCfg := config.GetSystemCriticalConfig()
|
||||
systemCriticalCfg.DocumentRoot = path.Join(outDir, "html")
|
||||
systemCriticalCfg.TemplateDir = path.Join(testRoot, "templates")
|
||||
|
@ -156,7 +156,7 @@ func TestBuildFrontPage(t *testing.T) {
|
|||
}
|
||||
t.Run(driver, func(t *testing.T) {
|
||||
outDir := t.TempDir()
|
||||
config.SetVersion("3.10.2")
|
||||
config.SetVersion("3.11.0")
|
||||
systemCriticalCfg := config.GetSystemCriticalConfig()
|
||||
systemCriticalCfg.DocumentRoot = path.Join(outDir, "html")
|
||||
systemCriticalCfg.TemplateDir = path.Join(testRoot, "templates")
|
||||
|
|
|
@ -7,7 +7,7 @@ var defaultStyle = "test1.css";
|
|||
var webroot = "/chan";
|
||||
var serverTZ = 8;
|
||||
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>
|
||||
<html>
|
||||
<head>
|
||||
|
@ -74,7 +74,7 @@ var fileTypes = [];`
|
|||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</body>
|
||||
|
|
|
@ -3,6 +3,7 @@ package gcsql
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/gochan-org/gochan/pkg/config"
|
||||
"github.com/gochan-org/gochan/pkg/gcutil"
|
||||
|
@ -15,17 +16,16 @@ const (
|
|||
DBModernButBehind
|
||||
DBUpToDate
|
||||
DBModernButAhead
|
||||
|
||||
targetDatabaseVersion = 3
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidVersion is used when the db contains a 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)")
|
||||
ErrDeprecatedDB = errors.New("database layout is deprecated, please run gochan-migration -updatedb")
|
||||
ErrInvalidDBVersion = errors.New("invalid version flag returned by GetCompleteDatabaseVersion()")
|
||||
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)")
|
||||
ErrDeprecatedDB = errors.New("database layout is deprecated, please run gochan-migration -updatedb")
|
||||
ErrInvalidDBVersion = errors.New("invalid version flag returned by GetCompleteDatabaseVersion()")
|
||||
targetDatabaseVersion = 3
|
||||
)
|
||||
|
||||
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
|
||||
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()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
|
|||
|
||||
CREATE TABLE DBPREFIXfilters(
|
||||
id {serial pk},
|
||||
board_dirs VARCHAR(255) DEFAULT '*',
|
||||
staff_id {fk to serial},
|
||||
staff_note VARCHAR(255) NOT NULL,
|
||||
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
|
|
@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
|
|||
|
||||
CREATE TABLE DBPREFIXfilters(
|
||||
id BIGINT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY,
|
||||
board_dirs VARCHAR(255) DEFAULT '*',
|
||||
staff_id BIGINT,
|
||||
staff_note VARCHAR(255) NOT NULL,
|
||||
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
|
|
@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
|
|||
|
||||
CREATE TABLE DBPREFIXfilters(
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
board_dirs VARCHAR(255) DEFAULT '*',
|
||||
staff_id BIGINT,
|
||||
staff_note VARCHAR(255) NOT NULL,
|
||||
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
|
|
@ -262,7 +262,6 @@ CREATE TABLE DBPREFIXfile_ban(
|
|||
|
||||
CREATE TABLE DBPREFIXfilters(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
board_dirs VARCHAR(255) DEFAULT '*',
|
||||
staff_id BIGINT,
|
||||
staff_note VARCHAR(255) NOT NULL,
|
||||
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
<tr>
|
||||
<th>Actions</th><th>Filter action</th><th>Conditions</th><th>Staff</th><th>Last modified</th>
|
||||
</tr>
|
||||
<!-- TODO: replace dummy data with actual data -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{webPath `/manage/filters?edit=1`}}">Edit</a> | <a href="{{webPath `/manage/filters?delete=1`}}">Delete</a>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue