package adlin import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" "os" "time" ) var db *sql.DB func DSNGenerator() string { db_user := "adlin" db_password := "adlin" db_host := "" db_db := "adlin" if v, exists := os.LookupEnv("MYSQL_HOST"); exists { db_host = v } if v, exists := os.LookupEnv("MYSQL_PASSWORD"); exists { db_password = v } else if v, exists := os.LookupEnv("MYSQL_ROOT_PASSWORD"); exists { db_user = "root" db_password = v } if v, exists := os.LookupEnv("MYSQL_USER"); exists { db_user = v } if v, exists := os.LookupEnv("MYSQL_DATABASE"); exists { db_db = v } return db_user + ":" + db_password + "@" + db_host + "/" + db_db } func DBInit(dsn string) (err error) { if db, err = sql.Open("mysql", dsn+"?parseTime=true&foreign_key_checks=1"); err != nil { return } _, err = db.Exec(`SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';`) for i := 0; err != nil && i < 5; i += 1 { if _, err = db.Exec(`SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';`); err != nil && i <= 5 { log.Println("An error occurs when trying to connect to DB, will retry in 2 seconds: ", err) time.Sleep(2 * time.Second) } } db.SetConnMaxLifetime(time.Minute * 5) db.SetMaxOpenConns(20) db.SetMaxIdleConns(10) return } func DBCreate() (err error) { if _, err = db.Exec(` CREATE TABLE IF NOT EXISTS students( id_student INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, login VARCHAR(255) NOT NULL UNIQUE, time TIMESTAMP NOT NULL, associatedDomain VARCHAR(255) UNIQUE, delegatedDomain VARCHAR(255) UNIQUE ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return } if _, err = db.Exec(` CREATE TABLE IF NOT EXISTS student_keys( id_key INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, id_student INTEGER NOT NULL, sshkey TEXT, time TIMESTAMP NOT NULL, FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS student_login( id_student INTEGER NOT NULL, ip VARCHAR(255) NOT NULL, mac VARCHAR(255) NOT NULL, time TIMESTAMP NOT NULL, FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return err } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS student_challenges( id_st INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, id_student INTEGER NOT NULL, challenge INTEGER NOT NULL, time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, value VARCHAR(255) NOT NULL, CONSTRAINT token_found UNIQUE (id_student,challenge), FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return err } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS student_challenge_errors( id_st INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, id_student INTEGER NOT NULL, challenge INTEGER NOT NULL, time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, error VARCHAR(255) NOT NULL, CONSTRAINT token_found UNIQUE (id_student,challenge), FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return err } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS student_pong( id_student INTEGER NOT NULL, last TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, count INTEGER UNSIGNED DEFAULT 1, state BOOLEAN NOT NULL DEFAULT 0, CONSTRAINT one_pong UNIQUE (id_student,state), FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return err } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS student_sessions( id_session BLOB(255) NOT NULL, id_student INTEGER, time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return err } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS student_tunnel_tokens( token BLOB(255) NOT NULL, token_text CHAR(10) NOT NULL, id_student INTEGER NOT NULL, time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, pubkey BLOB(50) DEFAULT NULL, suffixip INTEGER NOT NULL, idoverride INTEGER NOT NULL DEFAULT 0, version INTEGER NOT NULL, FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { return err } return } func DBClose() error { return db.Close() } func DBPrepare(query string) (*sql.Stmt, error) { return db.Prepare(query) } func DBQuery(query string, args ...interface{}) (*sql.Rows, error) { return db.Query(query, args...) } func DBExec(query string, args ...interface{}) (sql.Result, error) { return db.Exec(query, args...) } func DBQueryRow(query string, args ...interface{}) *sql.Row { return db.QueryRow(query, args...) }