Files
codevault/internal/api/handlers.go
Aleksei Sokol 094112af97 Version 0.2.0
Changes:
- forbid to overwrite secrets of other users
- add some logs of success
- add validation on code (length 50)
- use same limiter for POST requests
2026-08-17 18:12:57 +03:00

73 lines
2.6 KiB
Go

package api
import (
"context"
"errors"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.uber.org/zap"
"github.com/kanootoko/codevault/internal/db"
"github.com/kanootoko/codevault/internal/observability/logging"
"github.com/kanootoko/codevault/internal/observability/metrics"
)
// StrictHandler implements StrictServerInterface.
type StrictHandler struct {
Secrets *db.SecretsRepository
Metrics metrics.ValueMetrics
}
func NewHandler(secrets *db.SecretsRepository, m metrics.ValueMetrics) *StrictHandler {
return &StrictHandler{Secrets: secrets, Metrics: m}
}
func (h *StrictHandler) GetValue(ctx context.Context, request GetValueRequestObject) (GetValueResponseObject, error) {
if request.Body == nil || request.Body.Code == "" || len(request.Body.Code) > 50 {
return GetValue400Response{}, nil
}
value, err := h.Secrets.Get(ctx, request.Body.Code)
if errors.Is(err, db.ErrNotFound) {
h.Metrics.GetFailedTotal.Add(ctx, 1, metric.WithAttributes(attribute.String("reason", "not_found")))
return GetValue404Response{}, nil
}
if err != nil {
return nil, err
}
logger := logging.LoggerMustFromContext(ctx)
h.Metrics.GetSuccessTotal.Add(ctx, 1, metric.WithAttributes(attribute.String("code", request.Body.Code)))
ip, _ := IPFromContext(ctx)
logger.Info("get value succeeded", zap.String("code", request.Body.Code), zap.String("ip", ip))
return GetValue200JSONResponse{Value: value}, nil
}
func (h *StrictHandler) SetValue(ctx context.Context, request SetValueRequestObject) (SetValueResponseObject, error) {
if request.Body == nil || request.Body.Code == "" || len(request.Body.Code) > 50 ||
request.Body.Value == "" || len(request.Body.Value) > 10*1024*1024 {
h.Metrics.SetFailedTotal.Add(ctx, 1, metric.WithAttributes(attribute.String("reason", "bad_request")))
return SetValue400Response{}, nil
}
login, _ := LoginFromContext(ctx)
ip, _ := IPFromContext(ctx)
logger := logging.LoggerMustFromContext(ctx)
if err := h.Secrets.Set(ctx, request.Body.Code, request.Body.Value, login); err != nil {
if errors.Is(err, db.ErrForbidden) {
h.Metrics.SetFailedTotal.Add(ctx, 1, metric.WithAttributes(attribute.String("reason", "forbidden")))
logger.Warn("set value forbidden", zap.String("code", request.Body.Code), zap.String("ip", ip), zap.String("user", login))
return SetValue403Response{}, nil
}
return nil, err
}
h.Metrics.SetSuccessTotal.Add(ctx, 1, metric.WithAttributes(attribute.String("user", login)))
logger.Info("set value succeeded", zap.String("code", request.Body.Code), zap.String("ip", ip), zap.String("user", login))
return SetValue204Response{}, nil
}