617 lines
19 KiB
Go
617 lines
19 KiB
Go
package httpapp
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"gitea.avt.data-center.id/othman.suseno/atlas/internal/models"
|
|
)
|
|
|
|
// pathParam is now in router_helpers.go
|
|
|
|
// Disk Handlers
|
|
func (a *App) handleListDisks(w http.ResponseWriter, r *http.Request) {
|
|
disks, err := a.zfs.ListDisks()
|
|
if err != nil {
|
|
log.Printf("list disks error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, disks)
|
|
}
|
|
|
|
// ZFS Pool Handlers
|
|
func (a *App) handleListPools(w http.ResponseWriter, r *http.Request) {
|
|
pools, err := a.zfs.ListPools()
|
|
if err != nil {
|
|
log.Printf("list pools error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, pools)
|
|
}
|
|
|
|
func (a *App) handleCreatePool(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Name string `json:"name"`
|
|
VDEVs []string `json:"vdevs"`
|
|
Options map[string]string `json:"options,omitempty"`
|
|
}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
if req.Name == "" || len(req.VDEVs) == 0 {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "name and vdevs are required"})
|
|
return
|
|
}
|
|
|
|
if req.Options == nil {
|
|
req.Options = make(map[string]string)
|
|
}
|
|
|
|
if err := a.zfs.CreatePool(req.Name, req.VDEVs, req.Options); err != nil {
|
|
log.Printf("create pool error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
pool, err := a.zfs.GetPool(req.Name)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusCreated, map[string]string{"message": "pool created", "name": req.Name})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusCreated, pool)
|
|
}
|
|
|
|
func (a *App) handleGetPool(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/pools/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "pool name required"})
|
|
return
|
|
}
|
|
|
|
pool, err := a.zfs.GetPool(name)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, pool)
|
|
}
|
|
|
|
func (a *App) handleDeletePool(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/pools/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "pool name required"})
|
|
return
|
|
}
|
|
|
|
if err := a.zfs.DestroyPool(name); err != nil {
|
|
log.Printf("destroy pool error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "pool destroyed", "name": name})
|
|
}
|
|
|
|
func (a *App) handleScrubPool(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/pools/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "pool name required"})
|
|
return
|
|
}
|
|
|
|
if err := a.zfs.ScrubPool(name); err != nil {
|
|
log.Printf("scrub pool error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "scrub started", "pool": name})
|
|
}
|
|
|
|
// Dataset Handlers
|
|
func (a *App) handleListDatasets(w http.ResponseWriter, r *http.Request) {
|
|
pool := r.URL.Query().Get("pool")
|
|
datasets, err := a.zfs.ListDatasets(pool)
|
|
if err != nil {
|
|
log.Printf("list datasets error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, datasets)
|
|
}
|
|
|
|
func (a *App) handleCreateDataset(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Name string `json:"name"`
|
|
Options map[string]string `json:"options,omitempty"`
|
|
}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
if req.Name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name is required"})
|
|
return
|
|
}
|
|
|
|
if req.Options == nil {
|
|
req.Options = make(map[string]string)
|
|
}
|
|
|
|
if err := a.zfs.CreateDataset(req.Name, req.Options); err != nil {
|
|
log.Printf("create dataset error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusCreated, map[string]string{"message": "dataset created", "name": req.Name})
|
|
}
|
|
|
|
func (a *App) handleGetDataset(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/datasets/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
|
|
return
|
|
}
|
|
|
|
datasets, err := a.zfs.ListDatasets("")
|
|
if err != nil {
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
for _, ds := range datasets {
|
|
if ds.Name == name {
|
|
writeJSON(w, http.StatusOK, ds)
|
|
return
|
|
}
|
|
}
|
|
|
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": "dataset not found"})
|
|
}
|
|
|
|
func (a *App) handleUpdateDataset(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/datasets/")
|
|
// TODO: Implement dataset property updates
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "name": name})
|
|
}
|
|
|
|
func (a *App) handleDeleteDataset(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/datasets/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
|
|
return
|
|
}
|
|
|
|
recursive := r.URL.Query().Get("recursive") == "true"
|
|
|
|
if err := a.zfs.DestroyDataset(name, recursive); err != nil {
|
|
log.Printf("destroy dataset error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "dataset destroyed", "name": name})
|
|
}
|
|
|
|
// ZVOL Handlers
|
|
func (a *App) handleListZVOLs(w http.ResponseWriter, r *http.Request) {
|
|
pool := r.URL.Query().Get("pool")
|
|
zvols, err := a.zfs.ListZVOLs(pool)
|
|
if err != nil {
|
|
log.Printf("list zvols error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, zvols)
|
|
}
|
|
|
|
func (a *App) handleCreateZVOL(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Name string `json:"name"`
|
|
Size uint64 `json:"size"` // in bytes
|
|
Options map[string]string `json:"options,omitempty"`
|
|
}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
if req.Name == "" || req.Size == 0 {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "name and size are required"})
|
|
return
|
|
}
|
|
|
|
if req.Options == nil {
|
|
req.Options = make(map[string]string)
|
|
}
|
|
|
|
if err := a.zfs.CreateZVOL(req.Name, req.Size, req.Options); err != nil {
|
|
log.Printf("create zvol error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusCreated, map[string]string{"message": "zvol created", "name": req.Name})
|
|
}
|
|
|
|
func (a *App) handleGetZVOL(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/zvols/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "zvol name required"})
|
|
return
|
|
}
|
|
|
|
zvols, err := a.zfs.ListZVOLs("")
|
|
if err != nil {
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
for _, zvol := range zvols {
|
|
if zvol.Name == name {
|
|
writeJSON(w, http.StatusOK, zvol)
|
|
return
|
|
}
|
|
}
|
|
|
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": "zvol not found"})
|
|
}
|
|
|
|
func (a *App) handleDeleteZVOL(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/zvols/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "zvol name required"})
|
|
return
|
|
}
|
|
|
|
if err := a.zfs.DestroyZVOL(name); err != nil {
|
|
log.Printf("destroy zvol error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "zvol destroyed", "name": name})
|
|
}
|
|
|
|
// Snapshot Handlers
|
|
func (a *App) handleListSnapshots(w http.ResponseWriter, r *http.Request) {
|
|
dataset := r.URL.Query().Get("dataset")
|
|
snapshots, err := a.zfs.ListSnapshots(dataset)
|
|
if err != nil {
|
|
log.Printf("list snapshots error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, snapshots)
|
|
}
|
|
|
|
func (a *App) handleCreateSnapshot(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Dataset string `json:"dataset"`
|
|
Name string `json:"name"`
|
|
Recursive bool `json:"recursive,omitempty"`
|
|
}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
if req.Dataset == "" || req.Name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset and name are required"})
|
|
return
|
|
}
|
|
|
|
if err := a.zfs.CreateSnapshot(req.Dataset, req.Name, req.Recursive); err != nil {
|
|
log.Printf("create snapshot error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
snapshotName := fmt.Sprintf("%s@%s", req.Dataset, req.Name)
|
|
snap, err := a.zfs.GetSnapshot(snapshotName)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusCreated, map[string]string{"message": "snapshot created", "name": snapshotName})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusCreated, snap)
|
|
}
|
|
|
|
func (a *App) handleGetSnapshot(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/snapshots/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "snapshot name required"})
|
|
return
|
|
}
|
|
|
|
snap, err := a.zfs.GetSnapshot(name)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, snap)
|
|
}
|
|
|
|
func (a *App) handleDeleteSnapshot(w http.ResponseWriter, r *http.Request) {
|
|
name := pathParam(r, "/api/v1/snapshots/")
|
|
if name == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "snapshot name required"})
|
|
return
|
|
}
|
|
|
|
recursive := r.URL.Query().Get("recursive") == "true"
|
|
|
|
if err := a.zfs.DestroySnapshot(name, recursive); err != nil {
|
|
log.Printf("destroy snapshot error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "snapshot destroyed", "name": name})
|
|
}
|
|
|
|
// Snapshot Policy Handlers
|
|
func (a *App) handleListSnapshotPolicies(w http.ResponseWriter, r *http.Request) {
|
|
dataset := r.URL.Query().Get("dataset")
|
|
var policies []models.SnapshotPolicy
|
|
if dataset != "" {
|
|
policies = a.snapshotPolicy.ListForDataset(dataset)
|
|
} else {
|
|
policies = a.snapshotPolicy.List()
|
|
}
|
|
writeJSON(w, http.StatusOK, policies)
|
|
}
|
|
|
|
func (a *App) handleCreateSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
|
|
var policy models.SnapshotPolicy
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&policy); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
if policy.Dataset == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset is required"})
|
|
return
|
|
}
|
|
|
|
a.snapshotPolicy.Set(&policy)
|
|
writeJSON(w, http.StatusCreated, policy)
|
|
}
|
|
|
|
func (a *App) handleGetSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
|
|
dataset := pathParam(r, "/api/v1/snapshot-policies/")
|
|
if dataset == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
|
|
return
|
|
}
|
|
|
|
policy, err := a.snapshotPolicy.Get(dataset)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
if policy == nil {
|
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": "policy not found"})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, policy)
|
|
}
|
|
|
|
func (a *App) handleUpdateSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
|
|
dataset := pathParam(r, "/api/v1/snapshot-policies/")
|
|
if dataset == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
|
|
return
|
|
}
|
|
|
|
var policy models.SnapshotPolicy
|
|
if err := json.NewDecoder(r.Body).Decode(&policy); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
|
|
return
|
|
}
|
|
|
|
// Ensure dataset matches URL parameter
|
|
policy.Dataset = dataset
|
|
|
|
a.snapshotPolicy.Set(&policy)
|
|
writeJSON(w, http.StatusOK, policy)
|
|
}
|
|
|
|
func (a *App) handleDeleteSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
|
|
dataset := pathParam(r, "/api/v1/snapshot-policies/")
|
|
if dataset == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
|
|
return
|
|
}
|
|
|
|
if err := a.snapshotPolicy.Delete(dataset); err != nil {
|
|
log.Printf("delete snapshot policy error: %v", err)
|
|
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "policy deleted", "dataset": dataset})
|
|
}
|
|
|
|
// SMB Share Handlers
|
|
func (a *App) handleListSMBShares(w http.ResponseWriter, r *http.Request) {
|
|
shares := []models.SMBShare{} // Stub
|
|
writeJSON(w, http.StatusOK, shares)
|
|
}
|
|
|
|
func (a *App) handleCreateSMBShare(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented"})
|
|
}
|
|
|
|
func (a *App) handleGetSMBShare(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/shares/smb/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleUpdateSMBShare(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/shares/smb/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleDeleteSMBShare(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/shares/smb/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
// NFS Export Handlers
|
|
func (a *App) handleListNFSExports(w http.ResponseWriter, r *http.Request) {
|
|
exports := []models.NFSExport{} // Stub
|
|
writeJSON(w, http.StatusOK, exports)
|
|
}
|
|
|
|
func (a *App) handleCreateNFSExport(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented"})
|
|
}
|
|
|
|
func (a *App) handleGetNFSExport(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/exports/nfs/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleUpdateNFSExport(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/exports/nfs/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleDeleteNFSExport(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/exports/nfs/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
// iSCSI Handlers
|
|
func (a *App) handleListISCSITargets(w http.ResponseWriter, r *http.Request) {
|
|
targets := []models.ISCSITarget{} // Stub
|
|
writeJSON(w, http.StatusOK, targets)
|
|
}
|
|
|
|
func (a *App) handleCreateISCSITarget(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented"})
|
|
}
|
|
|
|
func (a *App) handleGetISCSITarget(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/iscsi/targets/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleUpdateISCSITarget(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/iscsi/targets/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleDeleteISCSITarget(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/iscsi/targets/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleAddLUN(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/iscsi/targets/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleRemoveLUN(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/iscsi/targets/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
// Job Handlers
|
|
func (a *App) handleListJobs(w http.ResponseWriter, r *http.Request) {
|
|
status := models.JobStatus(r.URL.Query().Get("status"))
|
|
jobs := a.jobManager.List(status)
|
|
writeJSON(w, http.StatusOK, jobs)
|
|
}
|
|
|
|
func (a *App) handleGetJob(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/jobs/")
|
|
if id == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "job id required"})
|
|
return
|
|
}
|
|
|
|
job, err := a.jobManager.Get(id)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, job)
|
|
}
|
|
|
|
func (a *App) handleCancelJob(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/jobs/")
|
|
if id == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "job id required"})
|
|
return
|
|
}
|
|
|
|
if err := a.jobManager.Cancel(id); err != nil {
|
|
log.Printf("cancel job error: %v", err)
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "job cancelled", "id": id})
|
|
}
|
|
|
|
// Auth Handlers (stubs)
|
|
func (a *App) handleLogin(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented"})
|
|
}
|
|
|
|
func (a *App) handleLogout(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "logged out"})
|
|
}
|
|
|
|
// User Handlers
|
|
func (a *App) handleListUsers(w http.ResponseWriter, r *http.Request) {
|
|
users := []models.User{} // Stub
|
|
writeJSON(w, http.StatusOK, users)
|
|
}
|
|
|
|
func (a *App) handleCreateUser(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented"})
|
|
}
|
|
|
|
func (a *App) handleGetUser(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/users/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleUpdateUser(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/users/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
func (a *App) handleDeleteUser(w http.ResponseWriter, r *http.Request) {
|
|
id := pathParam(r, "/api/v1/users/")
|
|
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
|
|
}
|
|
|
|
// Audit Log Handlers
|
|
func (a *App) handleListAuditLogs(w http.ResponseWriter, r *http.Request) {
|
|
logs := []models.AuditLog{} // Stub
|
|
writeJSON(w, http.StatusOK, logs)
|
|
}
|