Update api docs

This commit is contained in:
2024-12-03 21:50:16 +01:00
parent c400d81c87
commit e413e955c5
17 changed files with 331 additions and 261 deletions

View File

@@ -5,6 +5,7 @@ import (
"io"
"net/http"
"os"
"time"
"novamd/internal/context"
"novamd/internal/storage"
@@ -12,6 +13,28 @@ import (
"github.com/go-chi/chi/v5"
)
// LookupResponse represents a response to a file lookup request
type LookupResponse struct {
Paths []string `json:"paths"`
}
// SaveFileResponse represents a response to a save file request
type SaveFileResponse struct {
FilePath string `json:"filePath"`
Size int64 `json:"size"`
UpdatedAt time.Time `json:"updatedAt"`
}
// LastOpenedFileResponse represents a response to a last opened file request
type LastOpenedFileResponse struct {
LastOpenedFilePath string `json:"lastOpenedFilePath"`
}
// UpdateLastOpenedFileRequest represents a request to update the last opened file
type UpdateLastOpenedFileRequest struct {
FilePath string `json:"filePath"`
}
// ListFiles godoc
// @Summary List files
// @Description Lists all files in the user's workspace
@@ -20,8 +43,8 @@ import (
// @Security BearerAuth
// @Produce json
// @Param workspace_name path string true "Workspace name"
// @Success 200 {array} string
// @Failure 500 {string} string "Failed to list files"
// @Success 200 {array} storage.FileNode
// @Failure 500 {object} ErrorResponse "Failed to list files"
// @Router /workspaces/{workspace_name}/files [get]
func (h *Handler) ListFiles() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -32,7 +55,7 @@ func (h *Handler) ListFiles() http.HandlerFunc {
files, err := h.Storage.ListFilesRecursively(ctx.UserID, ctx.Workspace.ID)
if err != nil {
http.Error(w, "Failed to list files", http.StatusInternalServerError)
respondError(w, "Failed to list files", http.StatusInternalServerError)
return
}
@@ -49,9 +72,9 @@ func (h *Handler) ListFiles() http.HandlerFunc {
// @Produce json
// @Param workspace_name path string true "Workspace name"
// @Param filename query string true "File name"
// @Success 200 {object} map[string][]string
// @Failure 400 {string} string "Filename is required"
// @Failure 404 {string} string "File not found"
// @Success 200 {object} LookupResponse
// @Failure 400 {object} ErrorResponse "Filename is required"
// @Failure 404 {object} ErrorResponse "File not found"
// @Router /workspaces/{workspace_name}/files/lookup [get]
func (h *Handler) LookupFileByName() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -62,17 +85,17 @@ func (h *Handler) LookupFileByName() http.HandlerFunc {
filename := r.URL.Query().Get("filename")
if filename == "" {
http.Error(w, "Filename is required", http.StatusBadRequest)
respondError(w, "Filename is required", http.StatusBadRequest)
return
}
filePaths, err := h.Storage.FindFileByName(ctx.UserID, ctx.Workspace.ID, filename)
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
respondError(w, "File not found", http.StatusNotFound)
return
}
respondJSON(w, map[string][]string{"paths": filePaths})
respondJSON(w, &LookupResponse{Paths: filePaths})
}
}
@@ -86,10 +109,10 @@ func (h *Handler) LookupFileByName() http.HandlerFunc {
// @Param workspace_name path string true "Workspace name"
// @Param file_path path string true "File path"
// @Success 200 {string} "File content"
// @Failure 400 {string} string "Invalid file path"
// @Failure 404 {string} string "File not found"
// @Failure 500 {string} string "Failed to read file"
// @Failure 500 {string} string "Failed to write response"
// @Failure 400 {object} ErrorResponse "Invalid file path"
// @Failure 404 {object} ErrorResponse "File not found"
// @Failure 500 {object} ErrorResponse "Failed to read file"
// @Failure 500 {object} ErrorResponse "Failed to write response"
// @Router /workspaces/{workspace_name}/files/* [get]
func (h *Handler) GetFileContent() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -103,23 +126,23 @@ func (h *Handler) GetFileContent() http.HandlerFunc {
if err != nil {
if storage.IsPathValidationError(err) {
http.Error(w, "Invalid file path", http.StatusBadRequest)
respondError(w, "Invalid file path", http.StatusBadRequest)
return
}
if os.IsNotExist(err) {
http.Error(w, "File not found", http.StatusNotFound)
respondError(w, "File not found", http.StatusNotFound)
return
}
http.Error(w, "Failed to read file", http.StatusInternalServerError)
respondError(w, "Failed to read file", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/plain")
_, err = w.Write(content)
if err != nil {
http.Error(w, "Failed to write response", http.StatusInternalServerError)
respondError(w, "Failed to write response", http.StatusInternalServerError)
return
}
}
@@ -135,10 +158,10 @@ func (h *Handler) GetFileContent() http.HandlerFunc {
// @Produce json
// @Param workspace_name path string true "Workspace name"
// @Param file_path path string true "File path"
// @Success 200 {string} "File saved successfully"
// @Failure 400 {string} string "Failed to read request body"
// @Failure 400 {string} string "Invalid file path"
// @Failure 500 {string} string "Failed to save file"
// @Success 200 {object} SaveFileResponse
// @Failure 400 {object} ErrorResponse "Failed to read request body"
// @Failure 400 {object} ErrorResponse "Invalid file path"
// @Failure 500 {object} ErrorResponse "Failed to save file"
// @Router /workspaces/{workspace_name}/files/* [post]
func (h *Handler) SaveFile() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -150,22 +173,29 @@ func (h *Handler) SaveFile() http.HandlerFunc {
filePath := chi.URLParam(r, "*")
content, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusBadRequest)
respondError(w, "Failed to read request body", http.StatusBadRequest)
return
}
err = h.Storage.SaveFile(ctx.UserID, ctx.Workspace.ID, filePath, content)
if err != nil {
if storage.IsPathValidationError(err) {
http.Error(w, "Invalid file path", http.StatusBadRequest)
respondError(w, "Invalid file path", http.StatusBadRequest)
return
}
http.Error(w, "Failed to save file", http.StatusInternalServerError)
respondError(w, "Failed to save file", http.StatusInternalServerError)
return
}
respondJSON(w, map[string]string{"message": "File saved successfully"})
response := SaveFileResponse{
FilePath: filePath,
Size: int64(len(content)),
UpdatedAt: time.Now().UTC(),
}
w.WriteHeader(http.StatusOK)
respondJSON(w, response)
}
}
@@ -178,11 +208,11 @@ func (h *Handler) SaveFile() http.HandlerFunc {
// @Produce string
// @Param workspace_name path string true "Workspace name"
// @Param file_path path string true "File path"
// @Success 200 {string} "File deleted successfully"
// @Failure 400 {string} string "Invalid file path"
// @Failure 404 {string} string "File not found"
// @Failure 500 {string} string "Failed to delete file"
// @Failure 500 {string} string "Failed to write response"
// @Success 204 "No Content - File deleted successfully"
// @Failure 400 {object} ErrorResponse "Invalid file path"
// @Failure 404 {object} ErrorResponse "File not found"
// @Failure 500 {object} ErrorResponse "Failed to delete file"
// @Failure 500 {object} ErrorResponse "Failed to write response"
// @Router /workspaces/{workspace_name}/files/* [delete]
func (h *Handler) DeleteFile() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -195,25 +225,20 @@ func (h *Handler) DeleteFile() http.HandlerFunc {
err := h.Storage.DeleteFile(ctx.UserID, ctx.Workspace.ID, filePath)
if err != nil {
if storage.IsPathValidationError(err) {
http.Error(w, "Invalid file path", http.StatusBadRequest)
respondError(w, "Invalid file path", http.StatusBadRequest)
return
}
if os.IsNotExist(err) {
http.Error(w, "File not found", http.StatusNotFound)
respondError(w, "File not found", http.StatusNotFound)
return
}
http.Error(w, "Failed to delete file", http.StatusInternalServerError)
respondError(w, "Failed to delete file", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
_, err = w.Write([]byte("File deleted successfully"))
if err != nil {
http.Error(w, "Failed to write response", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusNoContent)
}
}
@@ -225,9 +250,9 @@ func (h *Handler) DeleteFile() http.HandlerFunc {
// @Security BearerAuth
// @Produce json
// @Param workspace_name path string true "Workspace name"
// @Success 200 {object} map[string]string
// @Failure 400 {string} string "Invalid file path"
// @Failure 500 {string} string "Failed to get last opened file"
// @Success 200 {object} LastOpenedFileResponse
// @Failure 400 {object} ErrorResponse "Invalid file path"
// @Failure 500 {object} ErrorResponse "Failed to get last opened file"
// @Router /workspaces/{workspace_name}/files/last [get]
func (h *Handler) GetLastOpenedFile() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -238,16 +263,16 @@ func (h *Handler) GetLastOpenedFile() http.HandlerFunc {
filePath, err := h.DB.GetLastOpenedFile(ctx.Workspace.ID)
if err != nil {
http.Error(w, "Failed to get last opened file", http.StatusInternalServerError)
respondError(w, "Failed to get last opened file", http.StatusInternalServerError)
return
}
if _, err := h.Storage.ValidatePath(ctx.UserID, ctx.Workspace.ID, filePath); err != nil {
http.Error(w, "Invalid file path", http.StatusBadRequest)
respondError(w, "Invalid file path", http.StatusBadRequest)
return
}
respondJSON(w, map[string]string{"lastOpenedFilePath": filePath})
respondJSON(w, &LastOpenedFileResponse{LastOpenedFilePath: filePath})
}
}
@@ -260,11 +285,12 @@ func (h *Handler) GetLastOpenedFile() http.HandlerFunc {
// @Accept json
// @Produce json
// @Param workspace_name path string true "Workspace name"
// @Success 200 {object} map[string]string
// @Failure 400 {string} string "Invalid request body"
// @Failure 400 {string} string "Invalid file path"
// @Failure 404 {string} string "File not found"
// @Failure 500 {string} string "Failed to update file"
// @Param body body UpdateLastOpenedFileRequest true "Update last opened file request"
// @Success 204 "No Content - Last opened file updated successfully"
// @Failure 400 {object} ErrorResponse "Invalid request body"
// @Failure 400 {object} ErrorResponse "Invalid file path"
// @Failure 404 {object} ErrorResponse "File not found"
// @Failure 500 {object} ErrorResponse "Failed to update file"
// @Router /workspaces/{workspace_name}/files/last [put]
func (h *Handler) UpdateLastOpenedFile() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -273,12 +299,10 @@ func (h *Handler) UpdateLastOpenedFile() http.HandlerFunc {
return
}
var requestBody struct {
FilePath string `json:"filePath"`
}
var requestBody UpdateLastOpenedFileRequest
if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
respondError(w, "Invalid request body", http.StatusBadRequest)
return
}
@@ -287,25 +311,25 @@ func (h *Handler) UpdateLastOpenedFile() http.HandlerFunc {
_, err := h.Storage.GetFileContent(ctx.UserID, ctx.Workspace.ID, requestBody.FilePath)
if err != nil {
if storage.IsPathValidationError(err) {
http.Error(w, "Invalid file path", http.StatusBadRequest)
respondError(w, "Invalid file path", http.StatusBadRequest)
return
}
if os.IsNotExist(err) {
http.Error(w, "File not found", http.StatusNotFound)
respondError(w, "File not found", http.StatusNotFound)
return
}
http.Error(w, "Failed to update last opened file", http.StatusInternalServerError)
respondError(w, "Failed to update last opened file", http.StatusInternalServerError)
return
}
}
if err := h.DB.UpdateLastOpenedFile(ctx.Workspace.ID, requestBody.FilePath); err != nil {
http.Error(w, "Failed to update last opened file", http.StatusInternalServerError)
respondError(w, "Failed to update last opened file", http.StatusInternalServerError)
return
}
respondJSON(w, map[string]string{"message": "Last opened file updated successfully"})
w.WriteHeader(http.StatusNoContent)
}
}