Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F14949273
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Subscribers
None
View Options
diff --git a/migrations/migrations.go b/migrations/migrations.go
index 6b5b094..e787107 100644
--- a/migrations/migrations.go
+++ b/migrations/migrations.go
@@ -1,151 +1,152 @@
/*
* Copyright © 2019 Musing Studio LLC.
*
* This file is part of WriteFreely.
*
* WriteFreely is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, included
* in the LICENSE file in this source code package.
*/
// Package migrations contains database migrations for WriteFreely
package migrations
import (
"database/sql"
"github.com/writeas/web-core/log"
)
// TODO: refactor to use the datastore struct from writefreely pkg
type datastore struct {
*sql.DB
driverName string
}
func NewDatastore(db *sql.DB, dn string) *datastore {
return &datastore{db, dn}
}
// TODO: use these consts from writefreely pkg
const (
driverMySQL = "mysql"
driverSQLite = "sqlite3"
)
type Migration interface {
Description() string
Migrate(db *datastore) error
}
type migration struct {
description string
migrate func(db *datastore) error
}
func New(d string, fn func(db *datastore) error) Migration {
return &migration{d, fn}
}
func (m *migration) Description() string {
return m.description
}
func (m *migration) Migrate(db *datastore) error {
return m.migrate(db)
}
var migrations = []Migration{
- New("support user invites", supportUserInvites), // -> V1 (v0.8.0)
- New("support dynamic instance pages", supportInstancePages), // V1 -> V2 (v0.9.0)
- New("support users suspension", supportUserStatus), // V2 -> V3 (v0.11.0)
- New("support oauth", oauth), // V3 -> V4
- New("support slack oauth", oauthSlack), // V4 -> v5
- New("support ActivityPub mentions", supportActivityPubMentions), // V5 -> V6
- New("support oauth attach", oauthAttach), // V6 -> V7
- New("support oauth via invite", oauthInvites), // V7 -> V8 (v0.12.0)
- New("optimize drafts retrieval", optimizeDrafts), // V8 -> V9
- New("support post signatures", supportPostSignatures), // V9 -> V10 (v0.13.0)
- New("Widen oauth_users.access_token", widenOauthAcceesToken), // V10 -> V11
- New("support verifying fedi profile", fediverseVerifyProfile), // V11 -> V12 (v0.14.0)
- New("support newsletters", supportLetters), // V12 -> V13
- New("support password resetting", supportPassReset), // V13 -> V14
- New("speed up blog post retrieval", addPostRetrievalIndex), // V14 -> V15
- New("support ActivityPub likes", supportRemoteLikes), // V15 -> V16 (v0.16.0)
+ New("support user invites", supportUserInvites), // -> V1 (v0.8.0)
+ New("support dynamic instance pages", supportInstancePages), // V1 -> V2 (v0.9.0)
+ New("support users suspension", supportUserStatus), // V2 -> V3 (v0.11.0)
+ New("support oauth", oauth), // V3 -> V4
+ New("support slack oauth", oauthSlack), // V4 -> v5
+ New("support ActivityPub mentions", supportActivityPubMentions), // V5 -> V6
+ New("support oauth attach", oauthAttach), // V6 -> V7
+ New("support oauth via invite", oauthInvites), // V7 -> V8 (v0.12.0)
+ New("optimize drafts retrieval", optimizeDrafts), // V8 -> V9
+ New("support post signatures", supportPostSignatures), // V9 -> V10 (v0.13.0)
+ New("Widen oauth_users.access_token", widenOauthAcceesToken), // V10 -> V11
+ New("support verifying fedi profile", fediverseVerifyProfile), // V11 -> V12 (v0.14.0)
+ New("support newsletters", supportLetters), // V12 -> V13
+ New("support password resetting", supportPassReset), // V13 -> V14
+ New("speed up blog post retrieval", addPostRetrievalIndex), // V14 -> V15
+ New("support ActivityPub likes", supportRemoteLikes), // V15 -> V16 (v0.16.0)
+ New("fix post signature character set", fixPostSignatureCharset), // V16 -> V17 (v0.17.0)
}
// CurrentVer returns the current migration version the application is on
func CurrentVer() int {
return len(migrations)
}
func SetInitialMigrations(db *datastore) error {
// Included schema files represent changes up to V1, so note that in the database
_, err := db.Exec("INSERT INTO appmigrations (version, migrated, result) VALUES (?, "+db.now()+", ?)", 1, "")
if err != nil {
return err
}
return nil
}
func Migrate(db *datastore) error {
var version int
var err error
if db.tableExists("appmigrations") {
err = db.QueryRow("SELECT MAX(version) FROM appmigrations").Scan(&version)
if err != nil {
return err
}
} else {
log.Info("Initializing appmigrations table...")
version = 0
_, err = db.Exec(`CREATE TABLE appmigrations (
version ` + db.typeInt() + ` NOT NULL,
migrated ` + db.typeDateTime() + ` NOT NULL,
result ` + db.typeText() + ` NOT NULL
) ` + db.engine() + `;`)
if err != nil {
return err
}
}
if len(migrations[version:]) > 0 {
for i, m := range migrations[version:] {
curVer := version + i + 1
log.Info("Migrating to V%d: %s", curVer, m.Description())
err = m.Migrate(db)
if err != nil {
return err
}
// Update migrations table
_, err = db.Exec("INSERT INTO appmigrations (version, migrated, result) VALUES (?, "+db.now()+", ?)", curVer, "")
if err != nil {
return err
}
}
} else {
log.Info("Database up-to-date. No migrations to run.")
}
return nil
}
func (db *datastore) tableExists(t string) bool {
var dummy string
var err error
if db.driverName == driverSQLite {
err = db.QueryRow("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?", t).Scan(&dummy)
} else {
err = db.QueryRow("SHOW TABLES LIKE '" + t + "'").Scan(&dummy)
}
switch {
case err == sql.ErrNoRows:
return false
case err != nil:
log.Error("Couldn't SHOW TABLES: %v", err)
return false
}
return true
}
diff --git a/migrations/v17.go b/migrations/v17.go
new file mode 100644
index 0000000..02f529b
--- /dev/null
+++ b/migrations/v17.go
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2026 Musing Studio LLC.
+ *
+ * This file is part of WriteFreely.
+ *
+ * WriteFreely is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, included
+ * in the LICENSE file in this source code package.
+ */
+
+package migrations
+
+func fixPostSignatureCharset(db *datastore) error {
+ // Only run this migration on MySQL databases
+ if db.driverName != driverMySQL {
+ return nil
+ }
+
+ t, err := db.Begin()
+ if err != nil {
+ t.Rollback()
+ return err
+ }
+
+ _, err = t.Exec(`ALTER TABLE collections MODIFY post_signature TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;`)
+ if err != nil {
+ t.Rollback()
+ return err
+ }
+
+ err = t.Commit()
+ if err != nil {
+ t.Rollback()
+ return err
+ }
+
+ return nil
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 7, 12:39 PM (7 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3774194
Attached To
rWF WriteFreely
Event Timeline
Log In to Comment