school-timetracker/backend/database.go

178 lines
4.7 KiB
Go

package main
import (
"database/sql"
"fmt"
"log"
"golang.org/x/crypto/bcrypt"
_ "modernc.org/sqlite"
)
func InitDB(filepath string) *sql.DB {
db, err := sql.Open("sqlite", filepath)
if err != nil {
log.Fatal(err)
}
if err = db.Ping(); err != nil {
log.Fatal(err)
}
createTables(db)
return db
}
func createTables(db *sql.DB) {
queries := []string{
`CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
is_admin BOOLEAN NOT NULL DEFAULT 0
)`,
`CREATE TABLE IF NOT EXISTS schedules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
day_of_week INTEGER NOT NULL,
start_time TEXT NOT NULL,
end_time TEXT NOT NULL,
type TEXT NOT NULL,
title TEXT NOT NULL
)`,
`CREATE TABLE IF NOT EXISTS time_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
schedule_id INTEGER NOT NULL,
date TEXT NOT NULL,
type TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (schedule_id) REFERENCES schedules(id)
)`,
}
for _, query := range queries {
if _, err := db.Exec(query); err != nil {
log.Fatal(err)
}
}
// Create default admin user (password: admin123)
// Hash generated with bcrypt
hash, _ := bcrypt.GenerateFromPassword([]byte("admin123"), bcrypt.DefaultCost)
fmt.Println(string(hash))
_, err := db.Exec(`
INSERT OR IGNORE INTO users (id, username, password, is_admin)
VALUES (?, ?, ?, ?)`,
1, "admin", string(hash), true,
)
if err != nil {
log.Fatal(err)
}
}
func GetUserByUsername(db *sql.DB, username string) (*User, error) {
user := &User{}
err := db.QueryRow("SELECT id, username, password, is_admin FROM users WHERE username = ?", username).
Scan(&user.ID, &user.Username, &user.Password, &user.IsAdmin)
if err != nil {
return nil, err
}
return user, nil
}
func CreateUser(db *sql.DB, username, hashedPassword string, isAdmin bool) error {
_, err := db.Exec("INSERT INTO users (username, password, is_admin) VALUES (?, ?, ?)",
username, hashedPassword, isAdmin)
return err
}
func GetAllUsers(db *sql.DB) ([]User, error) {
rows, err := db.Query("SELECT id, username, is_admin FROM users")
if err != nil {
return nil, err
}
defer rows.Close()
var users []User
for rows.Next() {
var u User
if err := rows.Scan(&u.ID, &u.Username, &u.IsAdmin); err != nil {
continue
}
users = append(users, u)
}
return users, nil
}
func CreateSchedule(db *sql.DB, schedule *Schedule) error {
_, err := db.Exec("INSERT INTO schedules (day_of_week, start_time, end_time, type, title) VALUES (?, ?, ?, ?, ?)",
schedule.DayOfWeek, schedule.StartTime, schedule.EndTime, schedule.Type, schedule.Title)
return err
}
func GetAllSchedules(db *sql.DB) ([]Schedule, error) {
rows, err := db.Query("SELECT id, day_of_week, start_time, end_time, type, title FROM schedules ORDER BY day_of_week, start_time")
if err != nil {
return nil, err
}
defer rows.Close()
var schedules []Schedule
for rows.Next() {
var s Schedule
if err := rows.Scan(&s.ID, &s.DayOfWeek, &s.StartTime, &s.EndTime, &s.Type, &s.Title); err != nil {
continue
}
schedules = append(schedules, s)
}
return schedules, nil
}
func DeleteSchedule(db *sql.DB, id int) error {
_, err := db.Exec("DELETE FROM schedules WHERE id = ?", id)
return err
}
func CreateTimeEntry(db *sql.DB, entry *TimeEntry) error {
_, err := db.Exec("INSERT INTO time_entries (user_id, schedule_id, date, type) VALUES (?, ?, ?, ?)",
entry.UserID, entry.ScheduleID, entry.Date, entry.Type)
return err
}
func GetTimeEntriesByUser(db *sql.DB, userID int) ([]TimeEntry, error) {
rows, err := db.Query("SELECT id, user_id, schedule_id, date, type, created_at FROM time_entries WHERE user_id = ? ORDER BY date DESC, created_at DESC",
userID)
if err != nil {
return nil, err
}
defer rows.Close()
var entries []TimeEntry
for rows.Next() {
var e TimeEntry
if err := rows.Scan(&e.ID, &e.UserID, &e.ScheduleID, &e.Date, &e.Type, &e.CreatedAt); err != nil {
continue
}
entries = append(entries, e)
}
return entries, nil
}
func GetAllTimeEntries(db *sql.DB) ([]TimeEntry, error) {
rows, err := db.Query("SELECT id, user_id, schedule_id, date, type, created_at FROM time_entries ORDER BY date DESC, created_at DESC")
if err != nil {
return nil, err
}
defer rows.Close()
var entries []TimeEntry
for rows.Next() {
var e TimeEntry
if err := rows.Scan(&e.ID, &e.UserID, &e.ScheduleID, &e.Date, &e.Type, &e.CreatedAt); err != nil {
continue
}
entries = append(entries, e)
}
return entries, nil
}