Add tm_server with SQLite, Svelte UI, and task-master TUI sync.

Introduces the web backend (auth, RBAC, project tokens, revisions),
YouTrack-or-taskmaster backend choice in the TUI, and a first-pass
embedded Svelte UI. The frontend is functional but needs a major rework.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-27 22:23:11 +01:00
co-authored by Cursor
parent 98d2253f44
commit 4adfcdb95a
67 changed files with 7188 additions and 129 deletions
+75
View File
@@ -0,0 +1,75 @@
package server
import (
"net/http"
"strings"
"time"
"task/internal/sqlite"
)
func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
var body struct {
Username string `json:"username"`
Password string `json:"password"`
}
if err := readJSON(r, &body); err != nil {
writeError(w, http.StatusBadRequest, "invalid json")
return
}
body.Username = strings.TrimSpace(body.Username)
u, err := s.DB.GetUserByUsername(body.Username)
if err != nil || !sqlite.CheckPassword(body.Password, u.PasswordHash) {
writeError(w, http.StatusUnauthorized, "invalid credentials")
return
}
token, exp, err := s.DB.CreateSession(u.ID, 7*24*time.Hour)
if err != nil {
writeError(w, http.StatusInternalServerError, "session failed")
return
}
s.setSessionCookie(w, token, exp)
u.PasswordHash = ""
writeJSON(w, http.StatusOK, u)
}
func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {
if c, err := r.Cookie(sessionCookie); err == nil && c.Value != "" {
_ = s.DB.DeleteSession(c.Value)
}
s.clearSessionCookie(w)
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
}
func (s *Server) handleMe(w http.ResponseWriter, r *http.Request) {
u, _ := s.currentUser(r)
writeJSON(w, http.StatusOK, u)
}
func (s *Server) handleListUsers(w http.ResponseWriter, r *http.Request) {
users, err := s.DB.ListUsers()
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJSON(w, http.StatusOK, users)
}
func (s *Server) handleCreateUser(w http.ResponseWriter, r *http.Request) {
var body struct {
Username string `json:"username"`
Password string `json:"password"`
IsAdmin bool `json:"isAdmin"`
}
if err := readJSON(r, &body); err != nil {
writeError(w, http.StatusBadRequest, "invalid json")
return
}
u, err := s.DB.CreateUser(body.Username, body.Password, body.IsAdmin)
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
u.PasswordHash = ""
writeJSON(w, http.StatusCreated, u)
}