diff options
Diffstat (limited to 'internal/admin/api_courses.go')
| -rw-r--r-- | internal/admin/api_courses.go | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/internal/admin/api_courses.go b/internal/admin/api_courses.go new file mode 100644 index 0000000..63b356c --- /dev/null +++ b/internal/admin/api_courses.go @@ -0,0 +1,138 @@ +package admin + +import ( + "net/http" + "os" + "path/filepath" + "strings" +) + +func (s *AdminServer) handleCourses(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + ids, err := listYAMLFiles(s.dataDir, "courses") + if err != nil { + writeJSON(w, map[string]any{"error": err.Error()}) + return + } + if ids == nil { + ids = []string{} + } + writeJSON(w, ids) + case http.MethodPost: + var m map[string]any + if err := readJSON(r, &m); err != nil { + writeJSON(w, map[string]any{"error": "invalid json"}) + return + } + id, _ := m["id"].(string) + if strings.TrimSpace(id) == "" { + writeJSON(w, map[string]any{"error": "missing id"}) + return + } + delete(m, "id") + path := filepath.Join(s.dataDir, "courses", id+".yaml") + if _, err := os.Stat(path); err == nil { + writeJSON(w, map[string]any{"error": "course already exists"}) + return + } + newContent, err := writeMapAsYAML(path, m) + if err != nil { + writeJSON(w, map[string]any{"error": "write error: " + err.Error()}) + return + } + s.undoStack.Push(ChangeDesc{ + Description: "Created course " + id, + FilePath: path, + NewContent: newContent, + IsCreate: true, + }) + writeJSON(w, map[string]any{"ok": true, "id": id}) + default: + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + } +} + +func (s *AdminServer) handleCourseByID(w http.ResponseWriter, r *http.Request) { + id := strings.TrimPrefix(r.URL.Path, "/api/courses/") + if id == "" { + http.Error(w, `{"error":"missing id"}`, http.StatusBadRequest) + return + } + + switch r.Method { + case http.MethodGet: + data, path, err := findYAMLFileInSubdirs(s.dataDir, "courses", id) + if err != nil { + writeJSON(w, map[string]any{"error": "not found: " + id}) + return + } + raw, err := yamlToMap(data) + if err != nil { + writeJSON(w, map[string]any{"error": "parse error: " + err.Error()}) + return + } + raw["id"] = id + raw["_path"] = path + raw["_raw"] = string(data) + writeJSON(w, raw) + + case http.MethodPost, http.MethodPut: + var body map[string]any + if err := readJSON(r, &body); err != nil { + writeJSON(w, map[string]any{"error": "invalid JSON: " + err.Error()}) + return + } + delete(body, "id") + delete(body, "_path") + delete(body, "_raw") + + path := filepath.Join(s.dataDir, "courses", id+".yaml") + var oldContent []byte + if existing, err := snapshotFile(path); err == nil { + oldContent = existing + } + + newContent, err := writeMapAsYAML(path, body) + if err != nil { + writeJSON(w, map[string]any{"error": "write error: " + err.Error()}) + return + } + + isCreate := oldContent == nil + desc := "Updated course " + id + if isCreate { + desc = "Created course " + id + } + s.undoStack.Push(ChangeDesc{ + Description: desc, + FilePath: path, + OldContent: oldContent, + NewContent: newContent, + IsCreate: isCreate, + }) + writeJSON(w, map[string]any{"ok": true, "id": id}) + + case http.MethodDelete: + _, path, err := findYAMLFileInSubdirs(s.dataDir, "courses", id) + if err != nil { + writeJSON(w, map[string]any{"error": "not found: " + id}) + return + } + oldContent, _ := snapshotFile(path) + if err := os.Remove(path); err != nil { + writeJSON(w, map[string]any{"error": "delete error: " + err.Error()}) + return + } + s.undoStack.Push(ChangeDesc{ + Description: "Deleted course " + id, + FilePath: path, + OldContent: oldContent, + IsDelete: true, + }) + writeJSON(w, map[string]any{"ok": true, "id": id}) + + default: + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + } +} |
