Files
mstore/app/handler/manifest.go
T
2026-02-23 00:07:38 +02:00

242 lines
6.7 KiB
Go

/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
* 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/operator"
"mstore/app/router"
"mstore/pkg/terms"
)
func (hand *Handler) ManifestExists(rctx *router.Context) {
name, _ := rctx.GetSubpath("name")
reference, _ := rctx.GetSubpath("reference")
//hand.DumpHeaders("ManigestExists:\n", rctx)
params := &operator.ManifestExistsParams{
Name: name,
Reference: reference,
}
// Rigth checking
operatorID, _ := rctx.GetString(userTag)
opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadImages, params.Name)
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/<name>/manifests/<reference> 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, terms.RightWriteImages, params.Name)
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/<name>/manifests/<reference> 200 404
func (hand *Handler) GetManifest(rctx *router.Context) {
name, _ := rctx.GetSubpath("name")
reference, _ := rctx.GetSubpath("reference")
//hand.DumpHeaders("GetManigest", rctx)
params := &operator.GetManifestParams{
Name: name,
Reference: reference,
}
// Rigth checking
operatorID, _ := rctx.GetString(userTag)
opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadImages, params.Name)
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 {
//hand.logg.Debugf("GetManifest type: %s", res.ContentType)
//hand.logg.Debugf("GetManifest payload: %s", res.Payload)
rctx.SetHeader("Content-Length", res.ContentLength)
//rctx.SetHeader("Content-Type", res.ContentType)
rctx.SetHeader("Docker-Content-Digest", res.DockerContentDigest)
rctx.SendBytes(code, res.ContentType, []byte(res.Payload))
return
}
rctx.SetStatus(code)
}
// DELETE /v2/<name>/manifests/<reference> 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, terms.RightWriteImages, params.Name)
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/<name>/referrers/<digest> 200 404/400
// GET /v2/<name>/referrers/<digest>?artifactType=<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, terms.RightReadImages, params.Name)
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/<name>/tags/list 200 404
// GET /v2/<name>/tags/list?n=<integer>&last=<integer>
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, terms.RightReadImages, params.Name)
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)
}
// GET /v2/_catalog?n=1000 200 404
func (hand *Handler) ListManifests(rctx *router.Context) {
params := &operator.ListManifestsParams{}
// Rigth checking
operatorID, _ := rctx.GetString(userTag)
opEnable, err := hand.CheckRight(rctx.Ctx, operatorID, terms.RightReadImages, "_catalog")
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.ListManifests(ctx, params)
if err != nil {
hand.logg.Errorf("ListManifests error: %v", err)
}
rctx.SendJSON(code, res)
}