Complete TODO items: security, features, polish
Security: - Encrypt Gitea tokens at rest (AES-256-GCM with MH_SECRET) - Secure cookie flag when behind HTTPS (X-Forwarded-Proto) - Password complexity (min 8 chars) - TOTP: defer persist until verified (totp_pending column) - Audit log table + logging on login/rename/password change Features: - Rename files/folders (double-click in tree, /api/files/rename) - beforeunload warning for unsaved changes - Mobile hamburger menu - PWA icons (192px, 512px) - Max file size enforcement (10MB) - Shared file read access (cross-user with permission check) Polish: - Toast notifications replace all alert() calls - Keyboard shortcut help overlay (Ctrl+/) - File rename via double-click in FileTree
This commit is contained in:
+18
-1
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"markdownhub/internal/crypto"
|
||||
"markdownhub/internal/files"
|
||||
)
|
||||
|
||||
@@ -39,10 +40,18 @@ func (s *Server) handleBuildSubmit(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
jobID := uuid.New().String()
|
||||
// Encrypt Gitea token at rest
|
||||
encToken := req.GiteaToken
|
||||
if encToken != "" {
|
||||
key := crypto.KeyFromSecret(s.secret)
|
||||
if enc, err := crypto.EncryptString(encToken, key); err == nil {
|
||||
encToken = enc
|
||||
}
|
||||
}
|
||||
_, err := s.db.Exec(
|
||||
`INSERT INTO build_jobs (id, user_id, status, spec_content, gitea_url, gitea_token, gitea_org, repo_name, model)
|
||||
VALUES (?, ?, 'pending', ?, ?, ?, ?, ?, ?)`,
|
||||
jobID, userID, specContent, req.GiteaURL, req.GiteaToken, req.GiteaOrg, req.RepoName, req.Model,
|
||||
jobID, userID, specContent, req.GiteaURL, encToken, req.GiteaOrg, req.RepoName, req.Model,
|
||||
)
|
||||
if err != nil {
|
||||
writeJSON(w, 500, map[string]string{"error": "failed to create job"})
|
||||
@@ -133,6 +142,14 @@ func (s *Server) handleDaemonPoll(w http.ResponseWriter, r *http.Request) {
|
||||
// Mark as picked up
|
||||
s.db.Exec("UPDATE build_jobs SET status = 'running', updated_at = datetime('now') WHERE id = ?", id)
|
||||
|
||||
// Decrypt token
|
||||
if giteaToken != "" {
|
||||
key := crypto.KeyFromSecret(s.secret)
|
||||
if dec, err := crypto.DecryptString(giteaToken, key); err == nil {
|
||||
giteaToken = dec
|
||||
}
|
||||
}
|
||||
|
||||
writeJSON(w, 200, map[string]interface{}{
|
||||
"job_id": id,
|
||||
"spec_content": specContent,
|
||||
|
||||
Reference in New Issue
Block a user