feat: add Docker deployment and Microsoft OAuth support
This commit is contained in:
@@ -1,59 +1,78 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
var DB *sql.DB
|
||||
|
||||
// Init 打开 SQLite 并执行必要的表结构初始化.
|
||||
// 使用纯 Go 的 modernc.org/sqlite, 无需 CGO.
|
||||
func Init(path string) {
|
||||
dsn := "file:" + path + "?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(1)"
|
||||
db, err := sql.Open("sqlite", dsn)
|
||||
if err != nil {
|
||||
log.Fatalf("open sqlite: %v", err)
|
||||
}
|
||||
DB = db
|
||||
if err := migrate(); err != nil {
|
||||
log.Fatalf("migrate: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// migrate 创建所需表. 统一放在一处便于维护.
|
||||
func migrate() error {
|
||||
stmts := []string{
|
||||
`CREATE TABLE IF NOT EXISTS accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL,
|
||||
smtp_host TEXT NOT NULL,
|
||||
smtp_port INTEGER NOT NULL,
|
||||
imap_host TEXT NOT NULL,
|
||||
imap_port INTEGER NOT NULL,
|
||||
use_tls INTEGER DEFAULT 1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`,
|
||||
`CREATE TABLE IF NOT EXISTS sent_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER NOT NULL,
|
||||
to_addr TEXT NOT NULL,
|
||||
subject TEXT,
|
||||
body TEXT,
|
||||
status TEXT,
|
||||
error TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY(account_id) REFERENCES accounts(id) ON DELETE CASCADE
|
||||
);`,
|
||||
}
|
||||
for _, s := range stmts {
|
||||
if _, err := DB.Exec(s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
var DB *sql.DB
|
||||
|
||||
// Init 打开 SQLite 并执行必要的表结构初始化.
|
||||
func Init(path string) {
|
||||
dsn := "file:" + path + "?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)&_pragma=foreign_keys(1)"
|
||||
db, err := sql.Open("sqlite", dsn)
|
||||
if err != nil {
|
||||
log.Fatalf("open sqlite: %v", err)
|
||||
}
|
||||
DB = db
|
||||
if err := migrate(); err != nil {
|
||||
log.Fatalf("migrate: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func migrate() error {
|
||||
stmts := []string{
|
||||
`CREATE TABLE IF NOT EXISTS accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL DEFAULT '',
|
||||
smtp_host TEXT NOT NULL,
|
||||
smtp_port INTEGER NOT NULL,
|
||||
imap_host TEXT NOT NULL,
|
||||
imap_port INTEGER NOT NULL,
|
||||
use_tls INTEGER DEFAULT 1,
|
||||
auth_type TEXT DEFAULT 'basic',
|
||||
oauth_refresh_token TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`,
|
||||
`CREATE TABLE IF NOT EXISTS sent_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER NOT NULL,
|
||||
to_addr TEXT NOT NULL,
|
||||
subject TEXT,
|
||||
body TEXT,
|
||||
status TEXT,
|
||||
error TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY(account_id) REFERENCES accounts(id) ON DELETE CASCADE
|
||||
);`,
|
||||
`CREATE TABLE IF NOT EXISTS oauth_microsoft_pending (
|
||||
state TEXT PRIMARY KEY,
|
||||
refresh_token TEXT,
|
||||
email TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`,
|
||||
}
|
||||
for _, s := range stmts {
|
||||
if _, err := DB.Exec(s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// 旧库升级:逐列添加(已存在则忽略错误)
|
||||
alters := []string{
|
||||
`ALTER TABLE accounts ADD COLUMN auth_type TEXT DEFAULT 'basic'`,
|
||||
`ALTER TABLE accounts ADD COLUMN oauth_refresh_token TEXT`,
|
||||
}
|
||||
for _, s := range alters {
|
||||
if _, err := DB.Exec(s); err != nil {
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "duplicate column") {
|
||||
log.Printf("migrate alter note: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user