151 lines
3.3 KiB
Go
151 lines
3.3 KiB
Go
// 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.Data.DB.CreateKey(newKey.Name, 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()
|
|
k, err := ctx.Data.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":
|
|
aid := ctx.Var("aid")
|
|
if aid == "" {
|
|
aid, err = ctx.Data.Approver.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 := ctx.Data.Approver.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 := ctx.Data.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 = ctx.Data.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.Data.Approver.List()
|
|
ctx.JSON(schema.NewApprovals(l))
|
|
}
|
|
|
|
func keyListHandler(ctx *types.Context) {
|
|
k, err := ctx.Data.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.Data.Approver.Update(id, status)
|
|
if err != nil {
|
|
ctx.Log.Error(err, "error updating key request")
|
|
ctx.Err(types.ErrReqNotFound)
|
|
return
|
|
}
|
|
ctx.OK()
|
|
}
|