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>
76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
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)
|
|
}
|