Basic features done
This commit is contained in:
@@ -3,25 +3,16 @@ package lib
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
_ "turso.tech/database/tursogo"
|
||||
)
|
||||
|
||||
var DB *sql.DB
|
||||
|
||||
type User struct {
|
||||
ID int
|
||||
Username string
|
||||
PasswordHash string
|
||||
}
|
||||
|
||||
// init sqlite db — always creates app.db at project root (run from root)
|
||||
func InitDB() {
|
||||
var err error
|
||||
DB, err = sql.Open("sqlite3", "./app.db")
|
||||
DB, err = sql.Open("turso", "app.db")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -50,72 +41,66 @@ func InitDB() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// hash password
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
// check password
|
||||
func CheckPasswordHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// create new user
|
||||
func CreateUser(username, password string) error {
|
||||
hash, err := HashPassword(password)
|
||||
// make rooms table
|
||||
roomTable := `
|
||||
CREATE TABLE IF NOT EXISTS rooms (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
scale TEXT NOT NULL DEFAULT 'fibonacci',
|
||||
owner_id INTEGER NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
active_story_id INTEGER,
|
||||
FOREIGN KEY(owner_id) REFERENCES users(id)
|
||||
);`
|
||||
_, err = DB.Exec(roomTable)
|
||||
if err != nil {
|
||||
return err
|
||||
log.Fatal(err)
|
||||
}
|
||||
_, err = DB.Exec("INSERT INTO users (username, password_hash) VALUES (?, ?)", username, hash)
|
||||
return err
|
||||
}
|
||||
|
||||
// get user by name
|
||||
func GetUserByUsername(username string) (*User, error) {
|
||||
row := DB.QueryRow("SELECT id, username, password_hash FROM users WHERE username = ?", username)
|
||||
u := &User{}
|
||||
err := row.Scan(&u.ID, &u.Username, &u.PasswordHash)
|
||||
// make room_members table
|
||||
memberTable := `
|
||||
CREATE TABLE IF NOT EXISTS room_members (
|
||||
room_id INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
joined_at DATETIME NOT NULL,
|
||||
PRIMARY KEY (room_id, user_id),
|
||||
FOREIGN KEY(room_id) REFERENCES rooms(id),
|
||||
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||
);`
|
||||
_, err = DB.Exec(memberTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Fatal(err)
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// create session token
|
||||
func CreateSession(userID int) (string, error) {
|
||||
sessionID := uuid.New().String()
|
||||
expiresAt := time.Now().Add(24 * time.Hour)
|
||||
|
||||
_, err := DB.Exec("INSERT INTO sessions (id, user_id, expires_at) VALUES (?, ?, ?)", sessionID, userID, expiresAt)
|
||||
// make stories table
|
||||
storyTable := `
|
||||
CREATE TABLE IF NOT EXISTS stories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
room_id INTEGER NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
points INTEGER,
|
||||
voted INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY(room_id) REFERENCES rooms(id)
|
||||
);`
|
||||
_, err = DB.Exec(storyTable)
|
||||
if err != nil {
|
||||
return "", err
|
||||
log.Fatal(err)
|
||||
}
|
||||
return sessionID, nil
|
||||
}
|
||||
|
||||
// get user from session
|
||||
func GetUserFromSession(sessionID string) (*User, error) {
|
||||
row := DB.QueryRow(`
|
||||
SELECT u.id, u.username, u.password_hash
|
||||
FROM users u
|
||||
JOIN sessions s ON u.id = s.user_id
|
||||
WHERE s.id = ? AND s.expires_at > ?
|
||||
`, sessionID, time.Now())
|
||||
|
||||
u := &User{}
|
||||
err := row.Scan(&u.ID, &u.Username, &u.PasswordHash)
|
||||
// make votes table
|
||||
voteTable := `
|
||||
CREATE TABLE IF NOT EXISTS votes (
|
||||
story_id INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
PRIMARY KEY (story_id, user_id),
|
||||
FOREIGN KEY(story_id) REFERENCES stories(id),
|
||||
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||
);`
|
||||
_, err = DB.Exec(voteTable)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Fatal(err)
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// delete session
|
||||
func DeleteSession(sessionID string) error {
|
||||
_, err := DB.Exec("DELETE FROM sessions WHERE id = ?", sessionID)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user