Get rid of using headers to identify share type
This commit is contained in:
parent
493913112d
commit
1232b6887a
8 changed files with 96 additions and 48 deletions
|
@ -185,7 +185,7 @@ func (as *alerter) eval(ctx context.Context, now time.Time, testMode bool) ([]al
|
|||
continue
|
||||
}
|
||||
|
||||
if!tgr.Talkgroup.Alert {
|
||||
if !tgr.Talkgroup.Alert {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -395,4 +395,4 @@ func (*noopAlerter) SinkType() string { return "noopA
|
|||
func (*noopAlerter) Call(_ context.Context, _ *calls.Call) error { return nil }
|
||||
func (*noopAlerter) Go(_ context.Context) {}
|
||||
func (*noopAlerter) Enabled() bool { return false }
|
||||
func (*noopAlerter) HUP(_ *config.Config) { }
|
||||
func (*noopAlerter) HUP(_ *config.Config) {}
|
||||
|
|
|
@ -145,7 +145,7 @@ func (s *store) CallAudio(ctx context.Context, id uuid.UUID) (*calls.CallAudio,
|
|||
}
|
||||
|
||||
func (s *store) Call(ctx context.Context, id uuid.UUID) (*calls.Call, error) {
|
||||
_, err := rbac.Check(ctx, rbac.UseResource(entities.ResourceCall), rbac.WithActions(entities.ActionRead))
|
||||
_, err := rbac.Check(ctx, &calls.Call{ID: id}, rbac.WithActions(entities.ActionRead))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ var Policy = &restrict.PolicyDefinition{
|
|||
},
|
||||
entities.RoleAdmin: {
|
||||
Description: "A superuser",
|
||||
Parents: []string{entities.RoleUser},
|
||||
Parents: []string{entities.RoleUser},
|
||||
Grants: restrict.GrantsMap{
|
||||
entities.ResourceIncident: {
|
||||
&restrict.Permission{Action: entities.ActionRead},
|
||||
|
@ -109,7 +109,7 @@ var Policy = &restrict.PolicyDefinition{
|
|||
},
|
||||
entities.RoleSystem: {
|
||||
Description: "A system service",
|
||||
Parents: []string{entities.RoleAdmin},
|
||||
Parents: []string{entities.RoleAdmin},
|
||||
},
|
||||
entities.RolePublic: {
|
||||
/*
|
||||
|
|
|
@ -51,8 +51,9 @@ func New(baseURL url.URL) *api {
|
|||
s.shares = newShareAPI(&baseURL,
|
||||
ShareHandlers{
|
||||
ShareRequestCall: s.calls.shareCallRoute,
|
||||
ShareRequestCallInfo: respondShareHandler(s.calls.getCallInfo),
|
||||
ShareRequestCallDL: s.calls.shareCallDLRoute,
|
||||
ShareRequestIncident: s.incidents.getIncident,
|
||||
ShareRequestIncident: respondShareHandler(s.incidents.getIncident),
|
||||
ShareRequestIncidentM3U: s.incidents.getCallsM3U,
|
||||
ShareRequestTalkgroups: s.tgs.getTGsShareRoute,
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime"
|
||||
|
@ -11,7 +12,6 @@ import (
|
|||
"dynatron.me/x/stillbox/internal/forms"
|
||||
"dynatron.me/x/stillbox/pkg/calls/callstore"
|
||||
"dynatron.me/x/stillbox/pkg/database"
|
||||
"dynatron.me/x/stillbox/pkg/shares"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
|
@ -102,7 +102,12 @@ func (ca *callsAPI) getAudio(p getAudioParams, w http.ResponseWriter, r *http.Re
|
|||
_, _ = w.Write(call.AudioBlob)
|
||||
}
|
||||
|
||||
func (ca *callsAPI) shareCallRoute(id ID, _ *shares.Share, w http.ResponseWriter, r *http.Request) {
|
||||
func (ca *callsAPI) getCallInfo(ctx context.Context, id ID) (SharedItem, error) {
|
||||
cs := callstore.FromCtx(ctx)
|
||||
return cs.Call(ctx, id.(uuid.UUID))
|
||||
}
|
||||
|
||||
func (ca *callsAPI) shareCallRoute(id ID, w http.ResponseWriter, r *http.Request) {
|
||||
p := getAudioParams{
|
||||
CallID: common.PtrTo(id.(uuid.UUID)),
|
||||
}
|
||||
|
@ -110,7 +115,7 @@ func (ca *callsAPI) shareCallRoute(id ID, _ *shares.Share, w http.ResponseWriter
|
|||
ca.getAudio(p, w, r)
|
||||
}
|
||||
|
||||
func (ca *callsAPI) shareCallDLRoute(id ID, _ *shares.Share, w http.ResponseWriter, r *http.Request) {
|
||||
func (ca *callsAPI) shareCallDLRoute(id ID, w http.ResponseWriter, r *http.Request) {
|
||||
p := getAudioParams{
|
||||
CallID: common.PtrTo(id.(uuid.UUID)),
|
||||
Download: common.PtrTo("download"),
|
||||
|
|
|
@ -2,6 +2,7 @@ package rest
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -12,7 +13,6 @@ import (
|
|||
"dynatron.me/x/stillbox/internal/jsontypes"
|
||||
"dynatron.me/x/stillbox/pkg/incidents"
|
||||
"dynatron.me/x/stillbox/pkg/incidents/incstore"
|
||||
"dynatron.me/x/stillbox/pkg/shares"
|
||||
"dynatron.me/x/stillbox/pkg/talkgroups/tgstore"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
@ -91,22 +91,22 @@ func (ia *incidentsAPI) createIncident(w http.ResponseWriter, r *http.Request) {
|
|||
func (ia *incidentsAPI) getIncidentRoute(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := idOnlyParam(w, r)
|
||||
if err != nil {
|
||||
wErr(w, r, autoError(err))
|
||||
return
|
||||
}
|
||||
|
||||
ia.getIncident(id, nil, w, r)
|
||||
}
|
||||
|
||||
func (ia *incidentsAPI) getIncident(id ID, share *shares.Share, w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
incs := incstore.FromCtx(ctx)
|
||||
inc, err := incs.Incident(ctx, id.(uuid.UUID))
|
||||
e, err := ia.getIncident(r.Context(), id)
|
||||
if err != nil {
|
||||
wErr(w, r, autoError(err))
|
||||
return
|
||||
}
|
||||
|
||||
respond(w, r, inc)
|
||||
respond(w, r, e)
|
||||
}
|
||||
|
||||
func (ia *incidentsAPI) getIncident(ctx context.Context, id ID) (SharedItem, error) {
|
||||
incs := incstore.FromCtx(ctx)
|
||||
return incs.Incident(ctx, id.(uuid.UUID))
|
||||
}
|
||||
|
||||
func (ia *incidentsAPI) updateIncident(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -195,10 +195,10 @@ func (ia *incidentsAPI) getCallsM3URoute(w http.ResponseWriter, r *http.Request)
|
|||
return
|
||||
}
|
||||
|
||||
ia.getCallsM3U(id, nil, w, r)
|
||||
ia.getCallsM3U(id, w, r)
|
||||
}
|
||||
|
||||
func (ia *incidentsAPI) getCallsM3U(id ID, share *shares.Share, w http.ResponseWriter, r *http.Request) {
|
||||
func (ia *incidentsAPI) getCallsM3U(id ID, w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
incs := incstore.FromCtx(ctx)
|
||||
tgst := tgstore.FromCtx(ctx)
|
||||
|
@ -214,6 +214,7 @@ func (ia *incidentsAPI) getCallsM3U(id ID, share *shares.Share, w http.ResponseW
|
|||
callUrl := common.PtrTo(*ia.baseURL)
|
||||
urlRoot := "/api/call"
|
||||
filename := inc.PlaylistFilename()
|
||||
share := ShareFrom(ctx)
|
||||
if share != nil {
|
||||
urlRoot = fmt.Sprintf("/share/%s/call/", share.ID)
|
||||
filename += "_" + share.ID
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -23,6 +24,7 @@ type ShareRequestType string
|
|||
|
||||
const (
|
||||
ShareRequestCall ShareRequestType = "call"
|
||||
ShareRequestCallInfo ShareRequestType = "callinfo"
|
||||
ShareRequestCallDL ShareRequestType = "callDL"
|
||||
ShareRequestIncident ShareRequestType = "incident"
|
||||
ShareRequestIncidentM3U ShareRequestType = "m3u"
|
||||
|
@ -31,7 +33,7 @@ const (
|
|||
|
||||
func (rt ShareRequestType) IsValid() bool {
|
||||
switch rt {
|
||||
case ShareRequestCall, ShareRequestCallDL, ShareRequestIncident,
|
||||
case ShareRequestCall, ShareRequestCallInfo, ShareRequestCallDL, ShareRequestIncident,
|
||||
ShareRequestIncidentM3U, ShareRequestTalkgroups:
|
||||
return true
|
||||
}
|
||||
|
@ -39,25 +41,59 @@ func (rt ShareRequestType) IsValid() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (rt ShareRequestType) IsValidSubtype() bool {
|
||||
switch rt {
|
||||
case ShareRequestCall, ShareRequestCallDL, ShareRequestTalkgroups:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type ID interface {
|
||||
}
|
||||
|
||||
type HandlerFunc func(id ID, share *shares.Share, w http.ResponseWriter, r *http.Request)
|
||||
type ShareHandlers map[ShareRequestType]HandlerFunc
|
||||
type ShareHandlerFunc func(id ID, w http.ResponseWriter, r *http.Request)
|
||||
type ShareHandlers map[ShareRequestType]ShareHandlerFunc
|
||||
type shareAPI struct {
|
||||
baseURL *url.URL
|
||||
shnd ShareHandlers
|
||||
}
|
||||
|
||||
type EntityFunc func(ctx context.Context, id ID) (SharedItem, error)
|
||||
type SharedItem interface {
|
||||
}
|
||||
|
||||
type shareResponse struct {
|
||||
ID ID `json:"id"`
|
||||
Type shares.EntityType `json:"type"`
|
||||
Item SharedItem `json:"item,omitempty"`
|
||||
}
|
||||
|
||||
func ShareFrom(ctx context.Context) *shares.Share {
|
||||
if share, hasShare := entities.SubjectFrom(ctx).(*shares.Share); hasShare {
|
||||
return share
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func respondShareHandler(ie EntityFunc) ShareHandlerFunc {
|
||||
return func(id ID, w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
share := ShareFrom(ctx)
|
||||
if share == nil {
|
||||
wErr(w, r, autoError(ErrBadShare))
|
||||
return
|
||||
}
|
||||
|
||||
res, err := ie(r.Context(), id)
|
||||
if err != nil {
|
||||
wErr(w, r, autoError(err))
|
||||
return
|
||||
}
|
||||
|
||||
sRes := shareResponse{
|
||||
ID: id,
|
||||
Type: share.Type,
|
||||
Item: res,
|
||||
}
|
||||
|
||||
respond(w, r, sRes)
|
||||
}
|
||||
}
|
||||
|
||||
func newShareAPI(baseURL *url.URL, shnd ShareHandlers) *shareAPI {
|
||||
return &shareAPI{
|
||||
baseURL: baseURL,
|
||||
|
@ -135,12 +171,11 @@ func (sa *shareAPI) routeShare(w http.ResponseWriter, r *http.Request) {
|
|||
} else {
|
||||
switch sh.Type {
|
||||
case shares.EntityCall:
|
||||
rType = ShareRequestCall
|
||||
rType = ShareRequestCallInfo
|
||||
params.SubID = common.PtrTo(sh.EntityID.String())
|
||||
case shares.EntityIncident:
|
||||
rType = ShareRequestIncident
|
||||
}
|
||||
w.Header().Set("X-Share-Type", string(rType))
|
||||
}
|
||||
|
||||
if !rType.IsValid() {
|
||||
|
@ -158,21 +193,22 @@ func (sa *shareAPI) routeShare(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
switch rType {
|
||||
case ShareRequestTalkgroups:
|
||||
sa.shnd[rType](nil, sh, w, r)
|
||||
case ShareRequestCall, ShareRequestCallDL:
|
||||
if params.SubID == nil {
|
||||
wErr(w, r, autoError(ErrBadShare))
|
||||
return
|
||||
sa.shnd[rType](nil, w, r)
|
||||
case ShareRequestCall, ShareRequestCallInfo, ShareRequestCallDL:
|
||||
var subIDU uuid.UUID
|
||||
if params.SubID != nil {
|
||||
subIDU, err = uuid.Parse(*params.SubID)
|
||||
if err != nil {
|
||||
wErr(w, r, badRequest(err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
subIDU = sh.EntityID
|
||||
}
|
||||
|
||||
subIDU, err := uuid.Parse(*params.SubID)
|
||||
if err != nil {
|
||||
wErr(w, r, badRequest(err))
|
||||
return
|
||||
}
|
||||
sa.shnd[rType](subIDU, sh, w, r)
|
||||
sa.shnd[rType](subIDU, w, r)
|
||||
case ShareRequestIncident, ShareRequestIncidentM3U:
|
||||
sa.shnd[rType](sh.EntityID, sh, w, r)
|
||||
sa.shnd[rType](sh.EntityID, w, r)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"dynatron.me/x/stillbox/internal/forms"
|
||||
"dynatron.me/x/stillbox/pkg/database"
|
||||
"dynatron.me/x/stillbox/pkg/incidents/incstore"
|
||||
"dynatron.me/x/stillbox/pkg/shares"
|
||||
"dynatron.me/x/stillbox/pkg/talkgroups"
|
||||
"dynatron.me/x/stillbox/pkg/talkgroups/tgstore"
|
||||
"dynatron.me/x/stillbox/pkg/talkgroups/xport"
|
||||
|
@ -161,10 +160,16 @@ func (tga *talkgroupAPI) postPaginated(w http.ResponseWriter, r *http.Request) {
|
|||
respond(w, r, res)
|
||||
}
|
||||
|
||||
func (tga *talkgroupAPI) getTGsShareRoute(_ ID, share *shares.Share, w http.ResponseWriter, r *http.Request) {
|
||||
func (tga *talkgroupAPI) getTGsShareRoute(_ ID, w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
tgs := tgstore.FromCtx(ctx)
|
||||
|
||||
share := ShareFrom(ctx)
|
||||
if share == nil {
|
||||
wErr(w, r, autoError(ErrBadShare))
|
||||
return
|
||||
}
|
||||
|
||||
tgIDs, err := incstore.FromCtx(ctx).TGsIn(ctx, share.EntityID)
|
||||
if err != nil {
|
||||
wErr(w, r, autoError(err))
|
||||
|
|
Loading…
Reference in a new issue