118 lines
4.4 KiB
Go
118 lines
4.4 KiB
Go
/*
|
|
YetAnotherToDoList
|
|
Copyright © 2023 gilex-dev gilex-dev@proton.me
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, version 3.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package database
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model"
|
|
)
|
|
|
|
type CustomDB struct {
|
|
connection *sql.DB
|
|
logger *log.Logger
|
|
schema uint
|
|
secret []byte
|
|
}
|
|
|
|
var initTimeStamp int
|
|
|
|
func InitSQLite3(path string, schema uint, logger *log.Logger, secret []byte, initialAdminName string, initialAdminPassword string) *CustomDB {
|
|
initTimeStamp = int(time.Now().Unix())
|
|
db := CustomDB{logger: logger, schema: schema, secret: secret}
|
|
var err error
|
|
|
|
db.connection, err = sql.Open("sqlite3", "file:"+path+"?_foreign_keys=1")
|
|
if err != nil {
|
|
db.logger.Fatalln("Unable to open:", err)
|
|
}
|
|
|
|
if err = db.connection.Ping(); err != nil {
|
|
db.logger.Fatalln("Unable to connect:", err)
|
|
}
|
|
|
|
var user_version uint
|
|
err = db.connection.QueryRow("PRAGMA user_version").Scan(&user_version)
|
|
if err != nil {
|
|
db.logger.Fatalln("Failed to get database schema version")
|
|
}
|
|
|
|
switch {
|
|
case user_version == 0:
|
|
db.logger.Println("Initializing empty database")
|
|
if err = db.createSQLite3Tables(); err != nil {
|
|
db.logger.Fatalln("Error in creating table: ", err)
|
|
}
|
|
err = db.CreateInitialAdmin(initialAdminName, initialAdminPassword)
|
|
if err != nil {
|
|
db.logger.Fatal("failed to create initial admin. Try to fix and delete old database file: ", err)
|
|
}
|
|
case user_version > db.schema:
|
|
db.logger.Fatalln("Incompatible database schema version. Try updating this software.")
|
|
case user_version < db.schema:
|
|
db.logger.Fatalln("Upgrading database schema currently not supported")
|
|
}
|
|
return &db
|
|
}
|
|
|
|
func (db CustomDB) createSQLite3Tables() error {
|
|
tables := []struct {
|
|
name string
|
|
sql string
|
|
}{
|
|
{"User", "userId INTEGER PRIMARY KEY NOT NULL, userName VARCHAR NOT NULL UNIQUE CHECK(length(userName)!=0), passwordHash VARCHAR NOT NULL CHECK(length(passwordHash)!=0), fullName VARCHAR CHECK(length(fullName)!=0)"},
|
|
{"Todo", "todoId INTEGER PRIMARY KEY NOT NULL, text VARCHAR NOT NULL CHECK(length(text)!=0), IS_done BOOL NOT NULL DEFAULT false, FK_User_userId INTEGER NOT NULL, FOREIGN KEY(FK_User_userId) REFERENCES User(userId) ON UPDATE CASCADE ON DELETE CASCADE"},
|
|
{"R_User_Role", "relationId INTEGER PRIMARY KEY NOT NULL, FK_Role_roleId INTEGER NOT NULL, FK_User_userId INTEGER NOT NULL, UNIQUE(FK_Role_roleId, FK_User_userId), FOREIGN KEY(FK_Role_roleId) REFERENCES Role(roleId) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY(FK_User_userId) REFERENCES User(userId) ON UPDATE CASCADE ON DELETE CASCADE"},
|
|
{"Role", "roleId INTEGER PRIMARY KEY NOT NULL, roleName VARCHAR NOT NULL UNIQUE CHECK(length(roleName)!=0), IS_admin BOOL NOT NULL, IS_userCreator BOOL NOT NULL"},
|
|
{"RefreshToken", "tokenId INTEGER PRIMARY KEY NOT NULL, FK_User_userId INTEGER NOT NULL, selector VARCHAR NOT NULL CHECK(length(selector)!=0) UNIQUE, tokenHash VARCHAR NOT NULL CHECK(length(tokenHash)!=0), expiryDate INTEGER NOT NULL, tokenName VARCHAR CHECK(length(tokenName)!=0), FOREIGN KEY(FK_User_userId) REFERENCES User(userId) ON UPDATE CASCADE ON DELETE CASCADE"},
|
|
}
|
|
for _, table := range tables {
|
|
_, err := db.connection.Exec("CREATE TABLE IF NOT EXISTS " + table.name + " (" + table.sql + ")")
|
|
if err != nil {
|
|
return err
|
|
} else {
|
|
db.logger.Println("Successfully created", table.name)
|
|
}
|
|
}
|
|
|
|
_, err := db.connection.Exec("PRAGMA user_version = " + fmt.Sprintf("%d", db.schema))
|
|
if err != nil {
|
|
db.logger.Fatalln("Failed to set user_version:", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (db CustomDB) CreateInitialAdmin(initialAdminName string, initialAdminPassword string) error {
|
|
role, err := db.CreateRole(&model.NewRole{RoleName: "admin", IsAdmin: true, IsUserCreator: true})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user, err := db.CreateUser(model.NewUser{UserName: initialAdminName, Password: initialAdminPassword})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = db.AddRole(user.ID, role.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|