/* * 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 ( "net/http" "mstore/app/descr" "mstore/app/operator" "mstore/app/router" ) func (hand *Handler) ManifestExists(rctx *router.Context) { name, _ := rctx.GetSubpath("name") reference, _ := rctx.GetSubpath("reference") params := &operator.ManifestExistsParams{ Name: name, Reference: reference, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, descr.RightReadImages, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() res, code, err := hand.oper.ManifestExists(ctx, params) if err != nil { hand.logg.Errorf("ManifestExist error: %v", err) } else if code == http.StatusOK { rctx.SetHeader("Content-Length", res.ContentLength) rctx.SetHeader("Content-Type", res.ContentType) rctx.SetHeader("Docker-Content-Digest", res.DockerContentDigest) } rctx.SetStatus(code) } // PUT /v2//manifests/ 201 404 func (hand *Handler) PutManifest(rctx *router.Context) { //hand.DumpHeaders("PutManifest headers", rctx) contentType := rctx.GetHeader("Content-Type") contentLength := rctx.GetHeader("Content-Length") name, _ := rctx.GetSubpath("name") reference, _ := rctx.GetSubpath("reference") params := &operator.PutManifestParams{ ContentType: contentType, ContentLength: contentLength, Name: name, Reference: reference, Reader: rctx.Request.Body, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, descr.RightWriteImages, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() res, code, err := hand.oper.PutManifest(ctx, params) if err != nil { hand.logg.Errorf("PutManifest error: %v", err) } else { rctx.SetHeader("Location", res.Location) } rctx.SetStatus(code) } // GET /v2//manifests/ 200 404 func (hand *Handler) GetManifest(rctx *router.Context) { name, _ := rctx.GetSubpath("name") reference, _ := rctx.GetSubpath("reference") params := &operator.GetManifestParams{ Name: name, Reference: reference, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, descr.RightReadImages, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() res, code, err := hand.oper.GetManifest(ctx, params) if err != nil { hand.logg.Errorf("GetManifest error: %v", err) rctx.SetStatus(code) return } if code == http.StatusOK { rctx.SetHeader("Content-Length", res.ContentLength) rctx.SetHeader("Content-Type", res.ContentType) rctx.SetHeader("Docker-Content-Digest", res.DockerContentDigest) rctx.SendBytes(code, []byte(res.Payload)) return } rctx.SetStatus(code) } // DELETE /v2//manifests/ 200 404 func (hand *Handler) DeleteManifest(rctx *router.Context) { name, _ := rctx.GetSubpath("name") reference, _ := rctx.GetSubpath("reference") params := &operator.DeleteManifestParams{ Name: name, Reference: reference, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, descr.RightWriteImages, "") 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.DeleteManifest(ctx, params) if err != nil { hand.logg.Errorf("DeleteManifest error: %v", err) } rctx.SetStatus(code) } // GET /v2//referrers/ 200 404/400 // GET /v2//referrers/?artifactType= 200 404/400 func (hand *Handler) GetReferer(rctx *router.Context) { name, _ := rctx.GetSubpath("name") digest, _ := rctx.GetSubpath("digest") params := &operator.GetRefererParams{ Name: name, Digest: digest, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, descr.RightReadImages, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation res, code, err := hand.oper.GetReferer(rctx.Ctx, params) if err != nil { hand.logg.Errorf("GetReferer error: %v", err) } rctx.SendText(code, res.Reference) } // GET /v2//tags/list 200 404 // GET /v2//tags/list?n=&last= func (hand *Handler) GetTags(rctx *router.Context) { name, _ := rctx.GetSubpath("name") params := &operator.GetTagsParams{ Name: name, } // Rigth checking operatorID, _ := rctx.GetString(userTag) opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, descr.RightReadImages, "") if err != nil { rctx.SetStatus(http.StatusInternalServerError) return } if !opEnable { rctx.SetStatus(http.StatusMethodNotAllowed) return } // Execution of the operation ctx := rctx.GetContext() res, code, err := hand.oper.GetTags(ctx, params) if err != nil { hand.logg.Errorf("GetTags error: %v", err) } rctx.SendJSON(code, res.TagDescr) }