// Copyright (C) 2023 Marius Schellenberger package server import ( "encoding/json" "net/http" "git.giftfish.de/ston1th/keyctl/pkg/api/types" "git.giftfish.de/ston1th/keyctl/pkg/api/v1/schema" "git.giftfish.de/ston1th/keyctl/pkg/store" ) func local(h types.CtxHandler) types.CtxHandler { return func(ctx *types.Context) { ip := ctx.ClientIP() if ip == "@" { h(ctx) return } ctx.Err(types.ErrForbidden) } } func newHandler(ctx *types.Context) { if ctx.Method() == "POST" { b, err := ctx.ReadBody() if err != nil { ctx.Log.Error(err, "error reading request body") ctx.Err(types.ErrISE) return } var newKey schema.NewKey err = json.Unmarshal(b, &newKey) if err != nil { ctx.Log.Error(err, "error decoding request body") ctx.Err(types.ErrInvalid) return } err = newKey.Validate() if err != nil { ctx.Log.Error(err, "error empty name for new key") ctx.Err(types.ErrInvalid) return } key, err := ctx.DB().CreateKey( newKey.Name, newKey.Existing, newKey.Size, newKey.Encoding, newKey.Type, ) if err != nil { ctx.Log.Error(err, "error writing key", "name", newKey.Name) ctx.Err(types.ErrISE) return } ctx.JSON(schema.Key(key)) } } func keyHandler(ctx *types.Context) { id := ctx.Var("id") ip := ctx.ClientIP() db := ctx.DB() k, err := db.GetKey(id) if err != nil { ctx.Log.Error(err, "error reading key", "id", id) if err == store.ErrKeyNotFound { ctx.Err(types.ErrKeyNotFound) return } ctx.Err(types.ErrISE) return } switch ctx.Method() { case "GET": a := ctx.Approver() aid := ctx.Var("aid") if aid == "" { aid, err = a.New(id, k.Name, ip) if err != nil { ctx.Log.Error(err, "error creating approval", "id", id, "name", k.Name) ctx.Err(types.ErrTooManyApprovals) return } ctx.Redirect(schema.ApproveURL(id, aid), http.StatusFound) return } s := a.Status(id, aid, ip) switch s { case types.Pending: ctx.Redirect(schema.ApproveURL(id, aid), http.StatusFound) return case types.Rejected: ctx.Err(types.ErrKeyRequestRejected) return case types.NotFound: ctx.Err(types.ErrReqNotFound) return } k, err := db.GetKeyWithSecret(id) if err != nil { ctx.Log.Error(err, "error reading key", "id", id) if err == store.ErrKeyNotFound { ctx.Err(types.ErrNotFound) return } ctx.Err(types.ErrISE) return } ctx.JSON(schema.Key(k)) case "DELETE": err = db.DeleteKey(id) if err != nil { ctx.Log.Error(err, "error deleting key", "id", id, "name", k.Name) if err == store.ErrKeyNotFound { ctx.Err(types.ErrNotFound) return } ctx.Err(types.ErrISE) return } ctx.OK() } } func reqListHandler(ctx *types.Context) { l := ctx.Approver().List() ctx.JSON(schema.NewApprovals(l)) } func keyListHandler(ctx *types.Context) { k, err := ctx.DB().GetKeys() if err != nil { ctx.Log.Error(err, "error reading keys") ctx.Err(types.ErrISE) return } ctx.JSON(schema.NewKeys(k)) } func reqHandler(ctx *types.Context) { id := ctx.Var("id") status := types.Pending switch ctx.Method() { case "PUT": status = types.Approved case "DELETE": status = types.Rejected } err := ctx.Approver().Update(id, status) if err != nil { ctx.Log.Error(err, "error updating key request") ctx.Err(types.ErrReqNotFound) return } ctx.OK() }