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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if!tgr.Talkgroup.Alert {
|
if !tgr.Talkgroup.Alert {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,4 +395,4 @@ func (*noopAlerter) SinkType() string { return "noopA
|
||||||
func (*noopAlerter) Call(_ context.Context, _ *calls.Call) error { return nil }
|
func (*noopAlerter) Call(_ context.Context, _ *calls.Call) error { return nil }
|
||||||
func (*noopAlerter) Go(_ context.Context) {}
|
func (*noopAlerter) Go(_ context.Context) {}
|
||||||
func (*noopAlerter) Enabled() bool { return false }
|
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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,9 @@ func New(baseURL url.URL) *api {
|
||||||
s.shares = newShareAPI(&baseURL,
|
s.shares = newShareAPI(&baseURL,
|
||||||
ShareHandlers{
|
ShareHandlers{
|
||||||
ShareRequestCall: s.calls.shareCallRoute,
|
ShareRequestCall: s.calls.shareCallRoute,
|
||||||
|
ShareRequestCallInfo: respondShareHandler(s.calls.getCallInfo),
|
||||||
ShareRequestCallDL: s.calls.shareCallDLRoute,
|
ShareRequestCallDL: s.calls.shareCallDLRoute,
|
||||||
ShareRequestIncident: s.incidents.getIncident,
|
ShareRequestIncident: respondShareHandler(s.incidents.getIncident),
|
||||||
ShareRequestIncidentM3U: s.incidents.getCallsM3U,
|
ShareRequestIncidentM3U: s.incidents.getCallsM3U,
|
||||||
ShareRequestTalkgroups: s.tgs.getTGsShareRoute,
|
ShareRequestTalkgroups: s.tgs.getTGsShareRoute,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package rest
|
package rest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"mime"
|
"mime"
|
||||||
|
@ -11,7 +12,6 @@ import (
|
||||||
"dynatron.me/x/stillbox/internal/forms"
|
"dynatron.me/x/stillbox/internal/forms"
|
||||||
"dynatron.me/x/stillbox/pkg/calls/callstore"
|
"dynatron.me/x/stillbox/pkg/calls/callstore"
|
||||||
"dynatron.me/x/stillbox/pkg/database"
|
"dynatron.me/x/stillbox/pkg/database"
|
||||||
"dynatron.me/x/stillbox/pkg/shares"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -102,7 +102,12 @@ func (ca *callsAPI) getAudio(p getAudioParams, w http.ResponseWriter, r *http.Re
|
||||||
_, _ = w.Write(call.AudioBlob)
|
_, _ = 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{
|
p := getAudioParams{
|
||||||
CallID: common.PtrTo(id.(uuid.UUID)),
|
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)
|
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{
|
p := getAudioParams{
|
||||||
CallID: common.PtrTo(id.(uuid.UUID)),
|
CallID: common.PtrTo(id.(uuid.UUID)),
|
||||||
Download: common.PtrTo("download"),
|
Download: common.PtrTo("download"),
|
||||||
|
|
|
@ -2,6 +2,7 @@ package rest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -12,7 +13,6 @@ import (
|
||||||
"dynatron.me/x/stillbox/internal/jsontypes"
|
"dynatron.me/x/stillbox/internal/jsontypes"
|
||||||
"dynatron.me/x/stillbox/pkg/incidents"
|
"dynatron.me/x/stillbox/pkg/incidents"
|
||||||
"dynatron.me/x/stillbox/pkg/incidents/incstore"
|
"dynatron.me/x/stillbox/pkg/incidents/incstore"
|
||||||
"dynatron.me/x/stillbox/pkg/shares"
|
|
||||||
"dynatron.me/x/stillbox/pkg/talkgroups/tgstore"
|
"dynatron.me/x/stillbox/pkg/talkgroups/tgstore"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"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) {
|
func (ia *incidentsAPI) getIncidentRoute(w http.ResponseWriter, r *http.Request) {
|
||||||
id, err := idOnlyParam(w, r)
|
id, err := idOnlyParam(w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
wErr(w, r, autoError(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ia.getIncident(id, nil, w, r)
|
e, err := ia.getIncident(r.Context(), id)
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wErr(w, r, autoError(err))
|
wErr(w, r, autoError(err))
|
||||||
return
|
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) {
|
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
|
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()
|
ctx := r.Context()
|
||||||
incs := incstore.FromCtx(ctx)
|
incs := incstore.FromCtx(ctx)
|
||||||
tgst := tgstore.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)
|
callUrl := common.PtrTo(*ia.baseURL)
|
||||||
urlRoot := "/api/call"
|
urlRoot := "/api/call"
|
||||||
filename := inc.PlaylistFilename()
|
filename := inc.PlaylistFilename()
|
||||||
|
share := ShareFrom(ctx)
|
||||||
if share != nil {
|
if share != nil {
|
||||||
urlRoot = fmt.Sprintf("/share/%s/call/", share.ID)
|
urlRoot = fmt.Sprintf("/share/%s/call/", share.ID)
|
||||||
filename += "_" + share.ID
|
filename += "_" + share.ID
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package rest
|
package rest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -23,6 +24,7 @@ type ShareRequestType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ShareRequestCall ShareRequestType = "call"
|
ShareRequestCall ShareRequestType = "call"
|
||||||
|
ShareRequestCallInfo ShareRequestType = "callinfo"
|
||||||
ShareRequestCallDL ShareRequestType = "callDL"
|
ShareRequestCallDL ShareRequestType = "callDL"
|
||||||
ShareRequestIncident ShareRequestType = "incident"
|
ShareRequestIncident ShareRequestType = "incident"
|
||||||
ShareRequestIncidentM3U ShareRequestType = "m3u"
|
ShareRequestIncidentM3U ShareRequestType = "m3u"
|
||||||
|
@ -31,7 +33,7 @@ const (
|
||||||
|
|
||||||
func (rt ShareRequestType) IsValid() bool {
|
func (rt ShareRequestType) IsValid() bool {
|
||||||
switch rt {
|
switch rt {
|
||||||
case ShareRequestCall, ShareRequestCallDL, ShareRequestIncident,
|
case ShareRequestCall, ShareRequestCallInfo, ShareRequestCallDL, ShareRequestIncident,
|
||||||
ShareRequestIncidentM3U, ShareRequestTalkgroups:
|
ShareRequestIncidentM3U, ShareRequestTalkgroups:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -39,25 +41,59 @@ func (rt ShareRequestType) IsValid() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt ShareRequestType) IsValidSubtype() bool {
|
|
||||||
switch rt {
|
|
||||||
case ShareRequestCall, ShareRequestCallDL, ShareRequestTalkgroups:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type ID interface {
|
type ID interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandlerFunc func(id ID, share *shares.Share, w http.ResponseWriter, r *http.Request)
|
type ShareHandlerFunc func(id ID, w http.ResponseWriter, r *http.Request)
|
||||||
type ShareHandlers map[ShareRequestType]HandlerFunc
|
type ShareHandlers map[ShareRequestType]ShareHandlerFunc
|
||||||
type shareAPI struct {
|
type shareAPI struct {
|
||||||
baseURL *url.URL
|
baseURL *url.URL
|
||||||
shnd ShareHandlers
|
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 {
|
func newShareAPI(baseURL *url.URL, shnd ShareHandlers) *shareAPI {
|
||||||
return &shareAPI{
|
return &shareAPI{
|
||||||
baseURL: baseURL,
|
baseURL: baseURL,
|
||||||
|
@ -135,12 +171,11 @@ func (sa *shareAPI) routeShare(w http.ResponseWriter, r *http.Request) {
|
||||||
} else {
|
} else {
|
||||||
switch sh.Type {
|
switch sh.Type {
|
||||||
case shares.EntityCall:
|
case shares.EntityCall:
|
||||||
rType = ShareRequestCall
|
rType = ShareRequestCallInfo
|
||||||
params.SubID = common.PtrTo(sh.EntityID.String())
|
params.SubID = common.PtrTo(sh.EntityID.String())
|
||||||
case shares.EntityIncident:
|
case shares.EntityIncident:
|
||||||
rType = ShareRequestIncident
|
rType = ShareRequestIncident
|
||||||
}
|
}
|
||||||
w.Header().Set("X-Share-Type", string(rType))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !rType.IsValid() {
|
if !rType.IsValid() {
|
||||||
|
@ -158,21 +193,22 @@ func (sa *shareAPI) routeShare(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
switch rType {
|
switch rType {
|
||||||
case ShareRequestTalkgroups:
|
case ShareRequestTalkgroups:
|
||||||
sa.shnd[rType](nil, sh, w, r)
|
sa.shnd[rType](nil, w, r)
|
||||||
case ShareRequestCall, ShareRequestCallDL:
|
case ShareRequestCall, ShareRequestCallInfo, ShareRequestCallDL:
|
||||||
if params.SubID == nil {
|
var subIDU uuid.UUID
|
||||||
wErr(w, r, autoError(ErrBadShare))
|
if params.SubID != nil {
|
||||||
return
|
subIDU, err = uuid.Parse(*params.SubID)
|
||||||
}
|
|
||||||
|
|
||||||
subIDU, err := uuid.Parse(*params.SubID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wErr(w, r, badRequest(err))
|
wErr(w, r, badRequest(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sa.shnd[rType](subIDU, sh, w, r)
|
} else {
|
||||||
|
subIDU = sh.EntityID
|
||||||
|
}
|
||||||
|
|
||||||
|
sa.shnd[rType](subIDU, w, r)
|
||||||
case ShareRequestIncident, ShareRequestIncidentM3U:
|
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/internal/forms"
|
||||||
"dynatron.me/x/stillbox/pkg/database"
|
"dynatron.me/x/stillbox/pkg/database"
|
||||||
"dynatron.me/x/stillbox/pkg/incidents/incstore"
|
"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"
|
||||||
"dynatron.me/x/stillbox/pkg/talkgroups/tgstore"
|
"dynatron.me/x/stillbox/pkg/talkgroups/tgstore"
|
||||||
"dynatron.me/x/stillbox/pkg/talkgroups/xport"
|
"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)
|
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()
|
ctx := r.Context()
|
||||||
tgs := tgstore.FromCtx(ctx)
|
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)
|
tgIDs, err := incstore.FromCtx(ctx).TGsIn(ctx, share.EntityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wErr(w, r, autoError(err))
|
wErr(w, r, autoError(err))
|
||||||
|
|
Loading…
Reference in a new issue