stillbox/pkg/rest/share.go

132 lines
2.5 KiB
Go
Raw Normal View History

package rest
import (
2025-01-19 21:51:39 -05:00
"errors"
"net/http"
"net/url"
2025-01-19 21:51:39 -05:00
"time"
"dynatron.me/x/stillbox/internal/forms"
2025-01-19 21:51:39 -05:00
"dynatron.me/x/stillbox/pkg/rbac"
"dynatron.me/x/stillbox/pkg/shares"
"github.com/go-chi/chi/v5"
2025-01-20 20:28:25 -05:00
"github.com/google/uuid"
)
2025-01-19 21:51:39 -05:00
var (
ErrBadShare = errors.New("bad share request type")
)
type ShareRequestType string
const (
ShareRequestCall ShareRequestType = "call"
2025-01-20 20:28:25 -05:00
ShareRequestCallDL ShareRequestType = "callDL"
2025-01-19 21:51:39 -05:00
ShareRequestIncident ShareRequestType = "incident"
ShareRequestIncidentM3U ShareRequestType = "m3u"
)
func (rt ShareRequestType) IsValid() bool {
switch rt {
case ShareRequestCall, ShareRequestIncident, ShareRequestIncidentM3U:
return true
}
return false
}
2025-01-20 20:28:25 -05:00
type HandlerFunc func(uuid.UUID, http.ResponseWriter, *http.Request)
type ShareHandlers map[ShareRequestType]HandlerFunc
type shareAPI struct {
baseURL *url.URL
2025-01-20 20:28:25 -05:00
shnd ShareHandlers
2025-01-20 16:31:43 -05:00
}
2025-01-19 21:51:39 -05:00
2025-01-20 20:28:25 -05:00
func newShareAPI(baseURL *url.URL, shnd ShareHandlers) *shareAPI {
2025-01-19 21:51:39 -05:00
return &shareAPI{
baseURL: baseURL,
2025-01-20 20:28:25 -05:00
shnd: shnd,
2025-01-19 21:51:39 -05:00
}
}
2025-01-19 21:51:39 -05:00
func (sa *shareAPI) Subrouter() http.Handler {
r := chi.NewMux()
2025-01-19 21:51:39 -05:00
r.Post(`/create`, sa.createShare)
r.Delete(`/{id:[A-Za-z0-9_-]{20,}}`, sa.deleteShare)
return r
}
2025-01-20 20:28:25 -05:00
func (sa *shareAPI) RootRouter() http.Handler {
r := chi.NewMux()
r.Get("/{type}/{shareId:[A-Za-z0-9_-]{20,}}", sa.routeShare)
return r
}
2025-01-19 21:51:39 -05:00
func (sa *shareAPI) createShare(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2025-01-19 21:51:39 -05:00
shs := shares.FromCtx(ctx)
p := shares.CreateShareParams{}
err := forms.Unmarshal(r, &p, forms.WithTag("json"), forms.WithAcceptBlank(), forms.WithOmitEmpty())
if err != nil {
wErr(w, r, badRequest(err))
return
}
2025-01-19 21:51:39 -05:00
sh, err := shs.NewShare(ctx, p)
if err != nil {
wErr(w, r, autoError(err))
return
}
2025-01-19 21:51:39 -05:00
respond(w, r, sh)
}
2025-01-20 20:28:25 -05:00
func (sa *shareAPI) routeShare(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
2025-01-19 21:51:39 -05:00
shs := shares.FromCtx(ctx)
2025-01-20 16:31:43 -05:00
params := struct {
Type string `param:"type"`
ID string `param:"shareId"`
}{}
err := decodeParams(&params, r)
if err != nil {
2025-01-20 20:28:25 -05:00
wErr(w, r, autoError(err))
return
}
2025-01-20 16:31:43 -05:00
rType := ShareRequestType(params.Type)
id := params.ID
2025-01-19 21:51:39 -05:00
if !rType.IsValid() {
2025-01-20 20:28:25 -05:00
wErr(w, r, autoError(ErrBadShare))
return
}
2025-01-19 21:51:39 -05:00
sh, err := shs.GetShare(ctx, id)
if err != nil {
2025-01-20 20:28:25 -05:00
wErr(w, r, autoError(err))
return
}
2025-01-19 21:51:39 -05:00
if sh.Expiration != nil && sh.Expiration.Time().Before(time.Now()) {
2025-01-20 20:28:25 -05:00
wErr(w, r, autoError(shares.ErrNoShare))
return
}
2025-01-19 21:51:39 -05:00
ctx = rbac.CtxWithSubject(ctx, sh)
r = r.WithContext(ctx)
2025-01-20 20:28:25 -05:00
sa.shnd[rType](sh.EntityID, w, r)
}
2025-01-20 20:28:25 -05:00
func (sa *shareAPI) deleteShare(w http.ResponseWriter, r *http.Request) {
}