diff --git a/build.sh b/build.sh index def8429b..de5f42f2 100755 --- a/build.sh +++ b/build.sh @@ -25,7 +25,7 @@ cp documize/api/mail/*.html documize/web/bindata/mail cp documize/database/templates/*.html documize/web/bindata rm -rf documize/web/bindata/scripts mkdir -p documize/web/bindata/scripts -cp -r documize/database/scripts documize/web/bindata +cp -r documize/database/scripts/autobuild/*.sql documize/web/bindata/scripts echo "Generating in-memory static assets..." go get github.com/jteeuwen/go-bindata/... diff --git a/documize/api/convert/apidocumizecom/init.go b/documize/api/convert/apidocumizecom/init.go index 25984174..17d5d190 100644 --- a/documize/api/convert/apidocumizecom/init.go +++ b/documize/api/convert/apidocumizecom/init.go @@ -6,27 +6,32 @@ import ( "net/http" "github.com/documize/community/documize/api/request" - "github.com/documize/community/wordsmith/environment" ) -var endPoint = "https://api.documize.com" +func endPoint() string { + r := request.ConfigString("LICENSE", "endpoint") + if r != "" { + return r + } + return "https://api.documize.com" +} -var token string - -func init() { - environment.GetString(&endPoint, "endpoint", false, "Documize end-point", request.FlagFromDB) - environment.GetString(&token, "token", false, "Documize token", request.FlagFromDB) +func token() (string, error) { + r := request.ConfigString("LICENSE", "token") + if r == "" { + return "", errors.New("Documize token is empty") + } + // TODO more validation here + return r, nil } var transport = &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // TODO should be from -insecure flag -} + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, // TODO should be glick.InsecureSkipVerifyTLS (from -insecure flag) but get error: x509: certificate signed by unknown authority + }} -// CheckToken tests if the supplied token is valid. +// CheckToken returns an error if the Documize LICENSE token is invalid. func CheckToken() error { - if token == "" { - return errors.New("Documize token is empty") - } - // TODO validate against endPoint site - return nil + _, err := token() + return err } diff --git a/documize/api/convert/apidocumizecom/msword.go b/documize/api/convert/apidocumizecom/msword.go index a6e69a9c..e00f8dff 100644 --- a/documize/api/convert/apidocumizecom/msword.go +++ b/documize/api/convert/apidocumizecom/msword.go @@ -26,7 +26,12 @@ func (file *Msword) Convert(r api.DocumentConversionRequest, reply *api.Document client := &http.Client{Transport: transport} - resp, err := client.Post(endPoint+"/api/word?token="+token, "application/json", bytes.NewReader(byts)) + tok,err:=token() + if err != nil { + return err + } + + resp, err := client.Post(endPoint()+"/api/word?token="+tok, "application/json", bytes.NewReader(byts)) if err != nil { return err } diff --git a/documize/api/endpoint/router.go b/documize/api/endpoint/router.go index 58eb7876..7432c15f 100644 --- a/documize/api/endpoint/router.go +++ b/documize/api/endpoint/router.go @@ -8,7 +8,6 @@ import ( "github.com/codegangsta/negroni" "github.com/documize/community/documize/api/plugins" - "github.com/documize/community/documize/api/request" "github.com/documize/community/documize/database" "github.com/documize/community/documize/web" "github.com/documize/community/wordsmith/environment" @@ -26,10 +25,10 @@ const ( var port, certFile, keyFile, forcePort2SSL string func init() { - environment.GetString(&certFile, "cert", false, "the cert.pem file used for https", request.FlagFromDB) - environment.GetString(&keyFile, "key", false, "the key.pem file used for https", request.FlagFromDB) - environment.GetString(&port, "port", false, "http/https port number", request.FlagFromDB) - environment.GetString(&forcePort2SSL, "forcesslport", false, "redirect given http port number to TLS", request.FlagFromDB) + environment.GetString(&certFile, "cert", false, "the cert.pem file used for https", nil) + environment.GetString(&keyFile, "key", false, "the key.pem file used for https", nil) + environment.GetString(&port, "port", false, "http/https port number", nil) + environment.GetString(&forcePort2SSL, "forcesslport", false, "redirect given http port number to TLS", nil) } var testHost string // used during automated testing diff --git a/documize/api/mail/mailer.go b/documize/api/mail/mailer.go index 3933d403..480910f0 100644 --- a/documize/api/mail/mailer.go +++ b/documize/api/mail/mailer.go @@ -10,7 +10,6 @@ import ( "github.com/documize/community/documize/api/request" "github.com/documize/community/documize/web" - "github.com/documize/community/wordsmith/environment" "github.com/documize/community/wordsmith/log" ) @@ -35,7 +34,7 @@ func InviteNewUser(recipient, inviter, url, username, password string) { subject := fmt.Sprintf("%s has invited you to Documize", inviter) e := newEmail() - e.From = creds.SMTPsender + e.From = creds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -86,7 +85,7 @@ func InviteExistingUser(recipient, inviter, url string) { subject := fmt.Sprintf("%s has invited you to their Documize account", inviter) e := newEmail() - e.From = creds.SMTPsender + e.From = creds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -128,7 +127,7 @@ func PasswordReset(recipient, url string) { subject := "Documize password reset request" e := newEmail() - e.From = "Documize " + e.From = creds.SMTPsender() //e.g. "Documize " e.To = []string{recipient} e.Subject = subject @@ -173,7 +172,7 @@ func ShareFolderExistingUser(recipient, inviter, url, folder, intro string) { subject := fmt.Sprintf("%s has shared %s with you", inviter, folder) e := newEmail() - e.From = creds.SMTPsender + e.From = creds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -224,7 +223,7 @@ func ShareFolderNewUser(recipient, inviter, url, folder, invitationMessage strin subject := fmt.Sprintf("%s has shared %s with you on Documize", inviter, folder) e := newEmail() - e.From = creds.SMTPsender + e.From = creds.SMTPsender() e.To = []string{recipient} e.Subject = subject @@ -254,24 +253,30 @@ func ShareFolderNewUser(recipient, inviter, url, folder, invitationMessage strin } } -var creds struct{ SMTPuserid, SMTPpassword, SMTPhost, SMTPport, SMTPsender string } - -func init() { - creds.SMTPport = "587" // the default value for outgoing SMTP traffic - creds.SMTPsender = "Documize " // TODO review as SAAS specific - environment.GetString(&creds.SMTPuserid, "smtpuserid", false, "SMTP username for outgoing email", request.FlagFromDB) - environment.GetString(&creds.SMTPpassword, "smtppassword", false, "SMTP password for outgoing email", request.FlagFromDB) - environment.GetString(&creds.SMTPhost, "smtphost", false, "SMTP host for outgoing email", request.FlagFromDB) - environment.GetString(&creds.SMTPport, "smtpport", false, "SMTP port for outgoing email", request.FlagFromDB) - environment.GetString(&creds.SMTPsender, "smtpsender", false, "SMTP sender's e-mail for outgoing email", request.FlagFromDB) +var creds = struct{ SMTPuserid, SMTPpassword, SMTPhost, SMTPport, SMTPsender func() string }{ + func() string { return request.ConfigString("SMTP", "userid") }, + func() string { return request.ConfigString("SMTP", "password") }, + func() string { return request.ConfigString("SMTP", "host") }, + func() string { + r := request.ConfigString("SMTP", "port") + if r == "" { + return "587" // default port number + } + return r + }, + func() string { return request.ConfigString("SMTP", "sender") }, } // Helper to return SMTP credentials func getAuth() smtp.Auth { - return smtp.PlainAuth("", creds.SMTPuserid, creds.SMTPpassword, creds.SMTPhost) + a := smtp.PlainAuth("", creds.SMTPuserid(), creds.SMTPpassword(), creds.SMTPhost()) + //fmt.Printf("DEBUG getAuth() = %#v\n", a) + return a } // Helper to return SMTP host details func getHost() string { - return creds.SMTPhost + ":" + creds.SMTPport + h := creds.SMTPhost() + ":" + creds.SMTPport() + //fmt.Printf("DEBUG getHost() = %#v\n", h) + return h } diff --git a/documize/api/plugins/glick.go b/documize/api/plugins/glick.go index ebc274c6..7d597be2 100644 --- a/documize/api/plugins/glick.go +++ b/documize/api/plugins/glick.go @@ -2,6 +2,7 @@ package plugins import ( + "bytes" "fmt" "io/ioutil" "time" @@ -18,14 +19,14 @@ import ( ) // PluginFile is the path to the file containing the configuration information for the plugin system in JSON format. -var PluginFile = "plugin.json" +var PluginFile = "DB" // this points to the database var insecure = "false" func init() { environment.GetString(&PluginFile, "plugin", false, - "the JSON file describing plugins, default 'plugin.json' set to 'PLUGIN' to configure from database settings", request.FlagFromDB) + "the JSON file describing plugins, default 'DB' uses the database config table 'FILEPLUGINS' entry", nil) environment.GetString(&insecure, "insecure", false, - "if 'true' allow https endpoints with invalid certificates (only for testing)", request.FlagFromDB) + "if 'true' allow https endpoints with invalid certificates (only for testing)", nil) } type infoLog struct{} @@ -100,8 +101,11 @@ func LibSetup() error { } var json = make([]byte, 0) - if PluginFile == "PLUGIN" { - json = []byte(request.ConfigString(PluginFile, "")) + if PluginFile == "DB" { + json = []byte(request.ConfigString("FILEPLUGINS", "")) + if len(bytes.TrimSpace(json)) == 0 { + return nil // don't fail if the DB does not exist yet + } } else { json, err = ioutil.ReadFile(PluginFile) if err != nil { @@ -112,6 +116,7 @@ func LibSetup() error { } err = Lib.Configure(json) if err != nil { + //fmt.Println("DEBUG plugin: "+string(json)) return err } return Lib.StartLocalRPCservers(infoLog{}, errorLog{}) diff --git a/documize/api/request/config.go b/documize/api/request/config.go index 0d8e730f..5460e2db 100644 --- a/documize/api/request/config.go +++ b/documize/api/request/config.go @@ -1,14 +1,14 @@ package request import ( - "strings" + "bytes" - "github.com/documize/community/wordsmith/environment" "github.com/documize/community/wordsmith/utility" ) +/* NOT CURRENTLY USED // FlagFromDB overrides the value in *target if it is set in the database configuration JSON. -// Function signiture must map that in environment +// Function signaiture must map that in environment. func FlagFromDB(target *string, name string) bool { value := ConfigString(environment.Prefix, name) //fmt.Println("DEBUG FlagFromDB " + value) @@ -18,17 +18,18 @@ func FlagFromDB(target *string, name string) bool { } return false } +*/ // ConfigString fetches a configuration JSON element from the config table. func ConfigString(area, path string) (ret string) { if path != "" { path = "." + path } - sql := `SELECT JSON_EXTRACT(details,'$` + path + `') AS item FROM config WHERE area = '` + area + `';` + sql := "SELECT JSON_EXTRACT(`config`,'$" + path + "') FROM `config` WHERE `key` = '" + area + "';" stmt, err := Db.Preparex(sql) if err != nil { - //log.Error(fmt.Sprintf("Unable to prepare select for ConfigString: %s", sql), err) + //fmt.Printf("DEBUG: Unable to prepare select SQL for ConfigString: %s -- error: %v\n", sql, err) return "" } defer utility.Close(stmt) @@ -38,12 +39,13 @@ func ConfigString(area, path string) (ret string) { err = stmt.Get(&item) if err != nil { - //log.Error(fmt.Sprintf("Unable to execute select for ConfigString: %s", sql), err) + //fmt.Printf("DEBUG: Unable to prepare execute SQL for ConfigString: %s -- error: %v\n", sql, err) return "" } if len(item) > 1 { - ret = string(item) + q := []byte(`"`) + ret = string(bytes.TrimPrefix(bytes.TrimSuffix(item, q), q)) } //fmt.Println("DEBUG ConfigString " + sql + " => " + ret) diff --git a/documize/api/request/init.go b/documize/api/request/init.go index 3394645d..314f4407 100644 --- a/documize/api/request/init.go +++ b/documize/api/request/init.go @@ -36,10 +36,6 @@ func (dr *databaseRequest) MakeTx() (err error) { func init() { var err error - var upgrade = "false" - - environment.GetString(&upgrade, "upgrade", false, - "to upgrade the database set to 'true' (only this Documize binary must be running)", nil) environment.GetString(&connectionString, "db", true, `"username:password@protocol(hostname:port)/databasename" for example "fred:bloggs@tcp(localhost:3306)/documize"`, @@ -50,8 +46,6 @@ func init() { log.Error("Unable to setup database", err) } - database.DbPtr = &Db // allow the database package to see this DB connection - Db.SetMaxIdleConns(30) Db.SetMaxOpenConns(100) @@ -64,25 +58,21 @@ func init() { } // go into setup mode if required - if database.Check(Db, connectionString) { - log.Info("database.Check(Db) OK") - migrations, err := database.Migrations(ConfigString("DATABASE", "last_migration")) - if err != nil { - log.Error("Unable to find required database migrations: ", err) + if database.Check(Db, connectionString, + func() (bool, error) { + // LockDB locks the database for migrations, returning if locked and an error. + // TODO, and if lock fails, wait here until it unlocks + return false, errors.New("LockDB TODO") + }, + func() { + // UnlockDB unlocks the database for migrations. + // Reports errors in the log. + // TODO + }) { + if err := database.Migrate(ConfigString("META", "database")); err != nil { + log.Error("Unable to run database migration: ", err) os.Exit(2) } - if len(migrations) > 0 { - if strings.ToLower(upgrade) != "true" { - log.Error("database migrations are required", - errors.New("the -upgrade flag is not 'true'")) - os.Exit(2) - - } - if err := migrations.Migrate(); err != nil { - log.Error("Unable to run database migration: ", err) - os.Exit(2) - } - } } else { log.Info("database.Check(Db) !OK, going into setup mode") } diff --git a/documize/database/check.go b/documize/database/check.go index 2521f9f6..e456ef68 100644 --- a/documize/database/check.go +++ b/documize/database/check.go @@ -13,8 +13,22 @@ import ( var dbCheckOK bool // default false -// Check that the database is configured correctly and that all the required tables exist -func Check(Db *sqlx.DB, connectionString string) bool { +// dbPtr is a pointer to the central connection to the database, used by all database requests. +var dbPtr **sqlx.DB + +// lockDB locks the database +var lockDB func() (bool, error) + +// unlockDB unlocks the database +var unlockDB func() + +// Check that the database is configured correctly and that all the required tables exist. +// It must be the first function called in the +func Check(Db *sqlx.DB, connectionString string,lDB func() (bool, error),ulDB func()) bool { + dbPtr = &Db + lockDB=lDB + unlockDB=ulDB + csBits := strings.Split(connectionString, "/") if len(csBits) > 1 { web.SiteInfo.DBname = strings.Split(csBits[len(csBits)-1], "?")[0] diff --git a/documize/database/create.go b/documize/database/create.go index a5475d26..2f8ec7bf 100644 --- a/documize/database/create.go +++ b/documize/database/create.go @@ -8,20 +8,19 @@ import ( "strings" "time" - "github.com/jmoiron/sqlx" - "github.com/documize/community/documize/api/util" "github.com/documize/community/documize/web" "github.com/documize/community/wordsmith/log" "github.com/documize/community/wordsmith/utility" ) -// DbPtr is a pointer to the central connection to the database, used by all database requests. -var DbPtr **sqlx.DB - func runSQL(sql string) (id uint64, err error) { - tx, err := (*DbPtr).Beginx() + if strings.TrimSpace(sql) == "" { + return 0, nil + } + + tx, err := (*dbPtr).Beginx() if err != nil { log.Error("runSql - failed to get transaction", err) @@ -50,6 +49,7 @@ func runSQL(sql string) (id uint64, err error) { // Create the tables in a blank database func Create(w http.ResponseWriter, r *http.Request) { txt := "database.Create()" + //defer func(){fmt.Println("DEBUG"+txt)}() if dbCheckOK { txt += " Check OK" @@ -119,13 +119,15 @@ func Create(w http.ResponseWriter, r *http.Request) { return } - buf, err := web.ReadFile("scripts/create.sql") + firstSQL := "db_00000.sql" + + buf, err := web.ReadFile("scripts/" + firstSQL) if err != nil { log.Error("database.Create()'s web.ReadFile()", err) return } - tx, err := (*DbPtr).Beginx() + tx, err := (*dbPtr).Beginx() if err != nil { log.Error(" failed to get transaction", err) return @@ -149,6 +151,11 @@ func Create(w http.ResponseWriter, r *http.Request) { return } + if err := Migrate(firstSQL); err != nil { + log.Error("database.Create()", err) + return + } + err = setupAccount(details, util.GenerateSalt()) if err != nil { log.Error("database.Create()", err) @@ -235,8 +242,8 @@ func setupAccount(completion onboardRequest, serial string) (err error) { // getStatement strips out the comments and returns all the individual SQL commands (apart from "USE") as a []string. func getStatements(bytes []byte) []string { - /* Strip comments of the form '-- comment', '// comment' or like this one */ - stripped := regexp.MustCompile("(?s)--.*?\n|(?s)//.*?\n|/\\*.*?\\*/").ReplaceAll(bytes, []byte("\n")) + /* Strip comments of the form '-- comment' or like this one */ + stripped := regexp.MustCompile("(?s)--.*?\n|/\\*.*?\\*/").ReplaceAll(bytes, []byte("\n")) sqls := strings.Split(string(stripped), ";") ret := make([]string, 0, len(sqls)) for _, v := range sqls { diff --git a/documize/database/migrate.go b/documize/database/migrate.go index c7e83f2b..11ec96d9 100644 --- a/documize/database/migrate.go +++ b/documize/database/migrate.go @@ -8,15 +8,17 @@ import ( "github.com/documize/community/documize/web" ) -const migrationsDir = "bindata/scripts/migrate" +const migrationsDir = "bindata/scripts" -// MigrationsT holds a list of migration sql files to run. -type MigrationsT []string +// migrationsT holds a list of migration sql files to run. +type migrationsT []string -// Migrations returns a list of the migrations to update the database as required for this version of the code. -func Migrations(last_migration string) (MigrationsT, error) { +// migrations returns a list of the migrations to update the database as required for this version of the code. +func migrations(lastMigration string) (migrationsT, error) { - last_migration = strings.TrimPrefix(strings.TrimSuffix(last_migration, `"`), `"`) + lastMigration = strings.TrimPrefix(strings.TrimSuffix(lastMigration, `"`), `"`) + + //fmt.Println(`DEBUG Migrations("`+lastMigration+`")`) files, err := web.AssetDir(migrationsDir) if err != nil { @@ -24,12 +26,12 @@ func Migrations(last_migration string) (MigrationsT, error) { } sort.Strings(files) - ret := make(MigrationsT, 0, len(files)) + ret := make(migrationsT, 0, len(files)) hadLast := false for _, v := range files { - if v == last_migration { + if v == lastMigration { hadLast = true } else { if hadLast { @@ -38,11 +40,12 @@ func Migrations(last_migration string) (MigrationsT, error) { } } + //fmt.Println(`DEBUG Migrations("`+lastMigration+`")=`,ret) return ret, nil } -// Migrate the database as required. -func (m MigrationsT) Migrate() error { +// migrate the database as required, by applying the migrations. +func (m migrationsT) migrate() error { for _, v := range m { buf, err := web.Asset(migrationsDir + "/" + v) if err != nil { @@ -52,3 +55,25 @@ func (m MigrationsT) Migrate() error { } return nil } + +// Migrate the database as required, consolidated action. +func Migrate(lastMigration string) error { + mig, err := migrations(lastMigration) + if err != nil { + return err + } + if len(mig) == 0 { + return nil // no migrations to perform + } + locked, err := lockDB() + if err != nil { + return err + } + if locked { + defer unlockDB() + if err := mig.migrate(); err != nil { + return err + } + } + return nil +} diff --git a/documize/database/scripts/autobuild/db_00000.sql b/documize/database/scripts/autobuild/db_00000.sql new file mode 100644 index 00000000..6000c1c2 --- /dev/null +++ b/documize/database/scripts/autobuild/db_00000.sql @@ -0,0 +1,279 @@ +-- SQL to set up the Documize database + +DROP TABLE IF EXISTS `user`; + +CREATE TABLE IF NOT EXISTS `user` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `firstname` NVARCHAR(500) NOT NULL, + `lastname` NVARCHAR(500) NOT NULL, + `email` NVARCHAR(250) NOT NULL UNIQUE, + `initials` NVARCHAR(10) NOT NULL DEFAULT "", + `password` NVARCHAR(500) NOT NULL DEFAULT "", + `salt` NVARCHAR(100) NOT NULL DEFAULT "", + `reset` NVARCHAR(100) NOT NULL DEFAULT "", + `active` BOOL NOT NULL DEFAULT 1, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_user_id` (`id` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `audit`; + +CREATE TABLE IF NOT EXISTS `audit` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `userid` CHAR(16) NOT NULL COLLATE utf8_bin, + `documentid` CHAR(16) NOT NULL DEFAULT "" COLLATE utf8_bin, + `pageid` CHAR(16) NOT NULL DEFAULT "" COLLATE utf8_bin, + `action` NVARCHAR(200) NOT NULL DEFAULT "", + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE INDEX `idx_audit_id` (`id` ASC), + INDEX `idx_orgid_url` (`orgid`)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `organization`; + +CREATE TABLE IF NOT EXISTS `organization` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `company` NVARCHAR(500) NOT NULL, + `title` NVARCHAR(500) NOT NULL, + `message` NVARCHAR(500) NOT NULL, + `url` NVARCHAR(200) NOT NULL DEFAULT "", + `domain` NVARCHAR(200) NOT NULL DEFAULT "", + `email` NVARCHAR(500) NOT NULL DEFAULT "", + `allowanonymousaccess` BOOL NOT NULL DEFAULT 0, + `verified` BOOL NOT NULL DEFAULT 0, + `serial` NVARCHAR(50) NOT NULL DEFAULT "", + `active` BOOL NOT NULL DEFAULT 1, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_organization_id` (`id` ASC), + INDEX `idx_organization_url` (`url`), + INDEX `idx_organization_domain` (`domain`)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `account`; + +CREATE TABLE IF NOT EXISTS `account` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `userid` CHAR(16) NOT NULL COLLATE utf8_bin, + `editor` BOOL NOT NULL DEFAULT 0, + `admin` BOOL NOT NULL DEFAULT 0, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_account_id` (`id` ASC), + INDEX `idx_account_userid` (`userid` ASC), + INDEX `idx_account_orgid` (`orgid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `label`; + +CREATE TABLE IF NOT EXISTS `label` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `label` NVARCHAR(255) NOT NULL, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `userid` CHAR(16) NOT NULL DEFAULT "" COLLATE utf8_bin, + `type` INT NOT NULL DEFAULT 1, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_label_id` (`id` ASC), + INDEX `idx_label_userid` (`userid` ASC), + INDEX `idx_label_orgid` (`orgid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `labelrole`; + +CREATE TABLE IF NOT EXISTS `labelrole` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `labelid` CHAR(16) NOT NULL COLLATE utf8_bin, + `userid` CHAR(16) NOT NULL COLLATE utf8_bin, + `canview` BOOL NOT NULL DEFAULT 0, + `canedit` BOOL NOT NULL DEFAULT 0, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_labelrole_id` (`id` ASC), + INDEX `idx_labelrole_userid` (`userid` ASC), + INDEX `idx_labelrole_labelid` (`labelid` ASC), + INDEX `idx_labelrole_orgid` (`orgid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `document`; + +CREATE TABLE IF NOT EXISTS `document` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `labelid` CHAR(16) NOT NULL COLLATE utf8_bin, + `userid` CHAR(16) NOT NULL COLLATE utf8_bin, + `job` CHAR(36) NOT NULL, + `location` NVARCHAR(2000) NOT NULL, + `title` NVARCHAR(2000) NOT NULL, + `excerpt` NVARCHAR(2000) NOT NULL, + `slug` NVARCHAR(2000) NOT NULL, + `tags` NVARCHAR(1000) NOT NULL DEFAULT '', + `template` BOOL NOT NULL DEFAULT 0, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_document_id` (`id` ASC), + INDEX `idx_document_orgid` (`orgid` ASC), + INDEX `idx_document_labelid` (`labelid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `page`; + +CREATE TABLE IF NOT EXISTS `page` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `documentid` CHAR(16) NOT NULL COLLATE utf8_bin, + `userid` CHAR(16) DEFAULT '' COLLATE utf8_bin, + `contenttype` CHAR(20) NOT NULL DEFAULT 'wysiwyg', + `level` INT UNSIGNED NOT NULL, + `sequence` DOUBLE NOT NULL, + `title` NVARCHAR(2000) NOT NULL, + `body` LONGTEXT, + `revisions` INT UNSIGNED NOT NULL, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_page_id` (`id` ASC), + INDEX `idx_page_orgid` (`orgid` ASC), + INDEX `idx_page_documentid` (`documentid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `pagemeta`; + +CREATE TABLE IF NOT EXISTS `pagemeta` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `pageid` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `documentid` CHAR(16) NOT NULL COLLATE utf8_bin, + `rawbody` LONGBLOB, + `config` JSON, + `externalsource` BOOL DEFAULT 0, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_pageid PRIMARY KEY (pageid), + UNIQUE INDEX `idx_pagemeta_id` (`id` ASC), + INDEX `idx_pagemeta_pageid` (`pageid` ASC), + INDEX `idx_pagemeta_orgid` (`orgid` ASC), + INDEX `idx_pagemeta_documentid` (`documentid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `attachment`; + +CREATE TABLE IF NOT EXISTS `attachment` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `documentid` CHAR(16) NOT NULL COLLATE utf8_bin, + `job` CHAR(36) NOT NULL, + `fileid` CHAR(10) NOT NULL, + `filename` NVARCHAR(255) NOT NULL, + `data` LONGBLOB, + `extension` CHAR(6) NOT NULL, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_attachment_id` (`id` ASC), + INDEX `idx_attachment_orgid` (`orgid` ASC), + INDEX `idx_attachment_documentid` (`documentid` ASC), + INDEX `idx_attachment_job_and_fileid` (`job`,`fileid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +DROP TABLE IF EXISTS `search`; + +CREATE TABLE IF NOT EXISTS `search` ( + `id` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `documentid` CHAR(16) NOT NULL COLLATE utf8_bin, + `level` INT UNSIGNED NOT NULL, + `sequence` DOUBLE NOT NULL, + `documenttitle` NVARCHAR(2000) NOT NULL, + `pagetitle` NVARCHAR(2000) NOT NULL, + `slug` NVARCHAR(2000) NOT NULL, + `body` LONGTEXT, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE INDEX `idx_search_id` (`id` ASC), + INDEX `idx_search_orgid` (`orgid` ASC), + INDEX `idx_search_documentid` (`documentid` ASC), + INDEX `idx_search_sequence` (`sequence` ASC), + FULLTEXT(`pagetitle`,`body`)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = MyISAM; + +DROP TABLE IF EXISTS `revision`; + +CREATE TABLE IF NOT EXISTS `revision` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `refid` CHAR(16) NOT NULL COLLATE utf8_bin, + `orgid` CHAR(16) NOT NULL COLLATE utf8_bin, + `documentid` CHAR(16) NOT NULL COLLATE utf8_bin, + `ownerid` CHAR(16) DEFAULT '' COLLATE utf8_bin, + `pageid` CHAR(16) NOT NULL COLLATE utf8_bin, + `userid` CHAR(16) NOT NULL COLLATE utf8_bin, + `contenttype` CHAR(20) NOT NULL DEFAULT 'wysiwyg', + `title` NVARCHAR(2000) NOT NULL, + `body` LONGTEXT, + `rawbody` LONGBLOB, + `config` JSON, + `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT pk_refid PRIMARY KEY (refid), + UNIQUE INDEX `idx_revision_id` (`id` ASC), + INDEX `idx_revision_orgid` (`orgid` ASC), + INDEX `idx_revision_documentid` (`documentid` ASC), + INDEX `idx_revision_pageid` (`pageid` ASC)) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci +ENGINE = InnoDB; + +/* +ALTER DATABASE documize CHARACTER SET utf8 COLLATE utf8_general_ci; +ALTER TABLE organization CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; +ALTER TABLE account CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; +ALTER TABLE user CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; +ALTER TABLE revision CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; +ALTER TABLE label CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; +ALTER TABLE document CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; +ALTER TABLE page CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; +*/ + +DROP TABLE IF EXISTS `config`; + +CREATE TABLE IF NOT EXISTS `config` ( + `key` CHAR(16) NOT NULL, + `config` JSON, + UNIQUE INDEX `idx_config_area` (`key` ASC) ) ; + +INSERT INTO `config` VALUES ('SMTP','{\"userid\": \"\",\"password\": \"\",\"host\": \"\",\"port\": \"\",\"sender\": \"\"}'); + +INSERT INTO `config` VALUES ('FILEPLUGINS', +'[{\"Comment\": \"Disable (or not) built-in html import (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"htm\",\"html\"]},{\"Comment\": \"Disable (or not) built-in Documize API import used from SDK (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"documizeapi\"]}]'); + +INSERT INTO `config` VALUES ('LICENSE','{\"token\": \"\",\"endpoint\": \"https://api.documize.com\"}'); + +INSERT INTO `config` VALUES ('META','{\"database\": \"db_00000.sql\"}'); diff --git a/documize/database/scripts/create.sql b/documize/database/scripts/create.sql index 6b3bb280..106b5b4d 100644 --- a/documize/database/scripts/create.sql +++ b/documize/database/scripts/create.sql @@ -266,13 +266,16 @@ ALTER TABLE page CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; DROP TABLE IF EXISTS `config`; CREATE TABLE IF NOT EXISTS `config` ( - `area` CHAR(16) NOT NULL, - `details` JSON, - UNIQUE INDEX `idx_config_area` (`area` ASC) ) ; + `key` CHAR(16) NOT NULL, + `config` JSON, + UNIQUE INDEX `idx_config_area` (`key` ASC) ) ; -INSERT INTO `config` VALUES ('DOCUMIZE','{\"plugin\": \"PLUGIN\"}'); -INSERT INTO `config` VALUES ('PLUGIN', +INSERT INTO `config` VALUES ('SMTP','{\"userid\": \"\",\"password\": \"\",\"host\": \"\",\"port\": \"\",\"sender\": \"\"}'); + +INSERT INTO `config` VALUES ('FILEPLUGINS', '[{\"Comment\": \"Disable (or not) built-in html import (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"htm\",\"html\"]},{\"Comment\": \"Disable (or not) built-in Documize API import used from SDK (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"documizeapi\"]}]'); -INSERT INTO `config` VALUES ('DATABASE','{\"last_migration\": \"migrate-00002.sql\"}'); +INSERT INTO `config` VALUES ('LICENSE','{\"token\": \"\",\"endpoint\": \"https://api.documize.com\"}'); + +INSERT INTO `config` VALUES ('META','{\"database\": \"migrate-00002.sql\"}'); /* NOTE the line above must be changed every time a new migration is incorporated into this file */ diff --git a/documize/database/scripts/migrate/migrate-00002.sql b/documize/database/scripts/migrate/migrate-00002.sql index 25c61f34..a622afc1 100644 --- a/documize/database/scripts/migrate/migrate-00002.sql +++ b/documize/database/scripts/migrate/migrate-00002.sql @@ -1,12 +1,16 @@ DROP TABLE IF EXISTS `config`; CREATE TABLE IF NOT EXISTS `config` ( - `area` CHAR(16) NOT NULL, - `details` JSON, - UNIQUE INDEX `idx_config_area` (`area` ASC) ) ; + `key` CHAR(16) NOT NULL, + `config` JSON, + UNIQUE INDEX `idx_config_area` (`key` ASC) ) ; -INSERT INTO `config` VALUES ('DOCUMIZE','{\"plugin\": \"PLUGIN\"}'); -INSERT INTO `config` VALUES ('PLUGIN', +INSERT INTO `config` VALUES ('SMTP','{\"userid\": \"\",\"password\": \"\",\"host\": \"\",\"port\": \"\",\"sender\": \"\"}'); + +INSERT INTO `config` VALUES ('FILEPLUGINS', '[{\"Comment\": \"Disable (or not) built-in html import (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"htm\",\"html\"]},{\"Comment\": \"Disable (or not) built-in Documize API import used from SDK (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"documizeapi\"]}]'); -INSERT INTO `config` VALUES ('DATABASE','{\"last_migration\": \"migrate-00002.sql\"}'); +INSERT INTO `config` VALUES ('META','{\"database\": \"migrate-00002.sql\"}'); + +INSERT INTO `config` VALUES ('LICENSE','{\"token\": \"\",\"endpoint\": \"https://api.documize.com\"}'); +