package main import ( "database/sql" "github.com/google/uuid" _ "github.com/mattn/go-sqlite3" ) var DB *sql.DB func initDB() error { db, err := sql.Open("sqlite3", "./db.sqlite") if err != nil { return err } DB = db err = createDatabase() if err != nil { return err } return nil } func createDatabase() error { sqlStatement := ` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, uuid VARCHAR(255) NOT NULL, client_token VARCHAR(255) NOT NULL, auth_token VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ` _, err := DB.Exec(sqlStatement) if err != nil { return err } return nil } func insertUser(username string, password string) error { playeruuid := uuid.New().String() sqlStatement := ` INSERT INTO users (username, password, uuid, client_token, auth_token) VALUES (?, ?, ?, ? ,?); ` _, err := DB.Exec(sqlStatement, username, password, playeruuid, "", "") if err != nil { return err } return nil } func getAuthToken(username string, password string) (string, error) { sqlStatement := ` SELECT auth_token FROM users WHERE username = ? AND password = ?; ` rows, err := DB.Query(sqlStatement, username, password) if err != nil { return "", err } defer rows.Close() // check amount of rows if rows.Next() { // get auth token var authToken string rows.Scan(&authToken) rows.Close() if authToken == "" { // generate new authToken authToken = uuid.New().String() // update authToken sqlStatement := ` UPDATE users SET auth_token = ? WHERE username = ? AND password = ?; ` _, err := DB.Exec(sqlStatement, authToken, username, password) if err != nil { return "", err } } return authToken, nil } else { return "", &NotFoundError{} } } func checkClientToken(clientToken string, userName string) (string, error) { // assumes user is already logged in sqlStatement := ` SELECT id FROM users WHERE client_token = ? AND username = ?; ` rows, err := DB.Query(sqlStatement, clientToken, userName) if err != nil { return "", err } defer rows.Close() // check amount of rows if rows.Next() { return clientToken, nil } else { clientToken = uuid.New().String() sqlStatement := ` UPDATE users SET client_token = ? WHERE username = ?; ` _, err := DB.Exec(sqlStatement, clientToken, userName) if err != nil { return "", err } clearAuthToken(userName) return clientToken, nil } } func clearAuthToken(username string) error { // runs when user logs out sqlStatement := ` UPDATE users SET auth_token = ? WHERE username = ?; ` _, err := DB.Exec(sqlStatement, "", username) if err != nil { return err } return nil } // func insertAuthToken(authToken string, userName string) error { // sqlStatement := ` // UPDATE users SET auth_token = ? WHERE username = ?; // ` // _, err := DB.Exec(sqlStatement, authToken, userName) // if err != nil { // return err // } // return nil // } func createUser(username string, adminToken string) (string, error) { // check if adminToken is valid if validateAdminToken(adminToken) { password := uuid.New().String() insertUser(username, password) return password, nil } else { return "", &InvalidCredentialsError{} } } func getPlayerUUID(username string) (string, error) { sqlStatement := ` SELECT uuid FROM users WHERE username = ?; ` rows, err := DB.Query(sqlStatement, username) if err != nil { return "", err } defer rows.Close() // check amount of rows if rows.Next() { // get uuid var uuid string err = rows.Scan(&uuid) if err != nil { return "", err } return uuid, nil } else { return "", &NotFoundError{} } } func refreshTokens(refresh RefreshPayload) (RefreshPayload, error) { sqlStatement := ` SELECT id FROM users WHERE auth_token = ? and client_token = ?; ` rows, err := DB.Query(sqlStatement, refresh.AccessToken, refresh.ClientToken) if err != nil { return RefreshPayload{}, err } if rows.Next() { // get id var id int err = rows.Scan(&id) rows.Close() if err != nil { return RefreshPayload{}, err } // generate new authToken authToken := uuid.New().String() // update authToken sqlStatement := ` UPDATE users SET auth_token = ? WHERE id = ?; ` _, err := DB.Exec(sqlStatement, authToken, id) if err != nil { return RefreshPayload{}, err } // generate new clientToken clientToken := uuid.New().String() // update clientToken sqlStatement = ` UPDATE users SET client_token = ? WHERE id = ?; ` _, err = DB.Exec(sqlStatement, clientToken, id) if err != nil { return RefreshPayload{}, err } refresh.AccessToken = authToken refresh.ClientToken = clientToken return refresh, nil } else { return refresh, nil } } func validateTokens(authToken string, clientToken string) (bool, error) { sqlStatement := ` SELECT id FROM users WHERE auth_token = ? and client_token = ?; ` rows, err := DB.Query(sqlStatement, authToken, clientToken) if err != nil { return false, err } if rows.Next() { return true, nil } else { return false, nil } } func invalidateTokens(authToken string, clientToken string) error { sqlStatement := ` UPDATE users SET auth_token = ?, client_token = ? WHERE auth_token = ? and client_token = ?; ` _, err := DB.Exec(sqlStatement, "", "", authToken, clientToken) if err != nil { return err } return nil } func invalidateTokensWithLogin(username string, password string) error { sqlStatement := ` UPDATE users SET auth_token = ?, client_token = ? WHERE username = ? AND password = ?; ` _, err := DB.Exec(sqlStatement, "", "", username, password) if err != nil { return err } return nil }