1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-02 19:16:23 -07:00
gochan/pkg/gcsql/provisioning.go

130 lines
3.9 KiB
Go

package gcsql
import (
"errors"
"fmt"
"strconv"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gcutil"
)
const (
DBIsPreApril = 1 << iota
DBCorrupted
DBClean
DBModernButBehind
DBUpToDate
DBModernButAhead
)
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()")
targetDatabaseVersion = -1
)
func initDB(initFile string) error {
filePath := gcutil.FindResource(initFile,
"./sql/"+initFile,
"/usr/local/share/gochan/"+initFile,
"/usr/share/gochan/"+initFile)
if filePath == "" {
return fmt.Errorf("missing SQL database initialization file (%s), please reinstall gochan", initFile)
}
return RunSQLFile(filePath)
}
// GetCompleteDatabaseVersion checks the database for any versions and errors that may exist.
// If a version is found, execute the version check. Otherwise check for deprecated info
// If no deprecated info is found, check if any databases exist prefixed with config.DBprefix
// if no prefixed databases exist, assume this is a new installation
func GetCompleteDatabaseVersion() (dbVersion, dbFlag int, err error) {
versionTableExists, err := doesTableExist("database_version")
if err != nil {
return 0, 0, err
}
if versionTableExists {
databaseVersion, versionError := getDatabaseVersion(gochanVersionKeyConstant)
if versionError != nil {
return 0, 0, versionError
}
if databaseVersion < targetDatabaseVersion {
return databaseVersion, DBModernButBehind, nil
}
if databaseVersion > targetDatabaseVersion {
return databaseVersion, DBModernButAhead, nil
}
return databaseVersion, DBUpToDate, nil
}
isOldDesign, err := doesTableExist("info")
if err != nil {
return 0, 0, err
}
if isOldDesign {
return 0, DBIsPreApril, nil
}
//No old or current database versioning tables found.
if config.GetSystemCriticalConfig().DBprefix != "" {
//Check if any gochan tables exist
gochanTableExists, err := doesGochanPrefixTableExist()
if err != nil {
return 0, 0, err
}
if gochanTableExists {
return 0, DBCorrupted, nil
}
}
return 0, DBClean, nil
}
// CheckAndInitializeDatabase checks the validity of the database and initialises it if it is empty
func CheckAndInitializeDatabase(dbType string, targetDbVersionStr string) (err error) {
if targetDatabaseVersion == -1 {
targetDatabaseVersion, err = strconv.Atoi(targetDbVersionStr)
if err != nil {
return err
}
}
dbVersion, versionFlag, err := GetCompleteDatabaseVersion()
if err != nil {
return err
}
switch versionFlag {
case DBIsPreApril:
fallthrough
case DBModernButBehind:
err = ErrDeprecatedDB
case DBClean:
err = buildNewDatabase(dbType)
case DBUpToDate:
err = nil
case DBCorrupted:
err = ErrCorruptedDB
case DBModernButAhead:
// Uer might be running an old gochan version
err = fmt.Errorf("database layout is ahead of current version (%d), target version: %d", dbVersion, targetDatabaseVersion)
default:
err = ErrInvalidDBVersion
}
return err
}
func buildNewDatabase(dbType string) error {
var err error
if err = initDB("initdb_" + dbType + ".sql"); err != nil {
return err
}
if err = createDefaultAdminIfNoStaff(); err != nil {
return errors.New("failed creating default admin account: " + err.Error())
}
if err = createDefaultBoardIfNoneExist(); err != nil {
return errors.New("failed creating default board if non already exists: " + err.Error())
}
return nil
}