/* * Copyright 2026 Oleg Borodin * * This work is published and licensed under a Creative Commons * Attribution-NonCommercial-NoDerivatives 4.0 International License. * * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ package handler import ( "io" "net/http" "mstore/app/operator" "mstore/app/router" "mstore/pkg/terms" ) const zeroContentLength = "0" func (hand *Handler) FileInfo(rctx *router.Context) { filepath, _ := rctx.GetSubpath("filepath") params := &operator.FileInfoParams{ Filepath: filepath, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadFiles, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() code, res, err := hand.oper.FileInfo(ctx, operatorID, params) if err != nil { hand.logg.Errorf("FileInfo error: %v", err) rctx.SetStatus(code) return } rctx.SetHeader("Content-Collection", res.ContentCollection) rctx.SetHeader("Content-Name", res.ContentName) rctx.SetHeader("Content-Type", res.ContentType) rctx.SetHeader("Content-Size", res.ContentSize) rctx.SetHeader("Content-Digest", res.ContentDigest) rctx.SetHeader("Content-CreatedAt", res.ContentCreatedAt) rctx.SetHeader("Content-CreatedBy", res.ContentCreatedBy) rctx.SetHeader("Content-UpdatedAt", res.ContentUpdatedAt) rctx.SetHeader("Content-UpdatedBy", res.ContentUpdatedBy) rctx.SetHeader("Content-Length", zeroContentLength) rctx.SetStatus(code) } func (hand *Handler) PutFile(rctx *router.Context) { contentSize := rctx.GetHeader("Content-Size") contentType := rctx.GetHeader("Content-Type") filepath, _ := rctx.GetSubpath("filepath") params := &operator.PutFileParams{ Filepath: filepath, ContentType: contentType, ContentSize: contentSize, Source: rctx.Request.Body, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightWriteFiles, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() code, _, err := hand.oper.PutFile(ctx, operatorID, params) if err != nil { hand.logg.Errorf("PutFile error: %v", err) rctx.SetStatus(code) return } rctx.SetStatus(code) } func (hand *Handler) GetFile(rctx *router.Context) { filepath, _ := rctx.GetSubpath("filepath") params := &operator.GetFileParams{ Filepath: filepath, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadFiles, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() code, res, err := hand.oper.GetFile(ctx, operatorID, params) if err != nil { hand.logg.Errorf("PutFile error: %v", err) rctx.SetStatus(code) return } rctx.SetHeader("Content-Type", res.ContentType) rctx.SetHeader("Content-Size", res.ContentSize) rctx.SetHeader("Content-Digest", res.ContentDigest) rctx.SetHeader("Content-Length", res.ContentSize) rctx.SetHeader("Content-CreatedAt", res.ContentCreatedAt) rctx.SetHeader("Content-CreatedBy", res.ContentCreatedBy) rctx.SetHeader("Content-UpdatedAt", res.ContentUpdatedAt) rctx.SetHeader("Content-UpdatedBy", res.ContentUpdatedBy) rctx.SetStatus(code) if res.Source != nil { defer res.Source.Close() _, err = io.Copy(rctx.Writer, res.Source) if err != nil { hand.logg.Errorf("GetFile error: %v", err) return } } } func (hand *Handler) DeleteFile(rctx *router.Context) { filepath, _ := rctx.GetSubpath("filepath") params := &operator.DeleteFileParams{ Filepath: filepath, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightWriteFiles, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() code, _, err := hand.oper.DeleteFile(ctx, operatorID, params) if err != nil { hand.logg.Errorf("DeleteFIle error: %v", err) } rctx.SetStatus(code) } func (hand *Handler) ListFiles(rctx *router.Context) { filepath, _ := rctx.GetSubpath("filepath") if filepath == "" { filepath = "/" } params := &operator.ListFilesParams{ Filepath: filepath, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadFiles, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() code, res, err := hand.oper.ListFiles(ctx, operatorID, params) if err != nil { hand.logg.Errorf("ListFiles error: %v", err) rctx.SetStatus(code) return } rctx.SendJSON(code, res.Files) } func (hand *Handler) ListCollections(rctx *router.Context) { cpath, _ := rctx.GetSubpath("path") if cpath == "" { cpath = "/" } params := &operator.ListCollectionsParams{ Path: cpath, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadFiles, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() code, res, err := hand.oper.ListCollections(ctx, operatorID, params) if err != nil { hand.logg.Errorf("ListCollections error: %v", err) rctx.SetStatus(code) return } rctx.SendJSON(code, res.Collections) } func (hand *Handler) DeleteCollection(rctx *router.Context) { cpath, _ := rctx.GetSubpath("path") if cpath == "" { cpath = "/" } params := &operator.DeleteColletionParams{ Path: cpath, } err := rctx.BindQuery(params) if err != nil { hand.logg.Errorf("DeleteColletion binding error: %v", err) rctx.SetStatus(http.StatusInternalServerError) return } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadFiles, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() code, res, err := hand.oper.DeleteColletion(ctx, operatorID, params) if err != nil { hand.logg.Errorf("DeleteColletion error: %v", err) rctx.SetStatus(code) return } rctx.SendJSON(code, res.Files) }