initial add call

This commit is contained in:
Daniel 2024-07-25 09:37:27 -04:00
parent b3e7d107a8
commit 6928e2432c
6 changed files with 117 additions and 78 deletions

View file

@ -33,19 +33,19 @@ RETURNING id, submitter, system, talkgroup, call_date, audio_name, audio_blob, a
` `
type AddCallParams struct { type AddCallParams struct {
Submitter pgtype.Int4 Submitter *int32 `json:"submitter"`
System int32 System int `json:"system"`
Talkgroup int32 Talkgroup int `json:"talkgroup"`
CallDate pgtype.Timestamp CallDate pgtype.Timestamp `json:"call_date"`
AudioName pgtype.Text AudioName *string `json:"audio_name"`
AudioBlob []byte AudioBlob []byte `json:"audio_blob"`
AudioType pgtype.Text AudioType *string `json:"audio_type"`
AudioUrl pgtype.Text AudioUrl *string `json:"audio_url"`
Frequency pgtype.Int4 Frequency *int32 `json:"frequency"`
Frequencies []byte Frequencies []byte `json:"frequencies"`
Patches []byte Patches []byte `json:"patches"`
TgLabel pgtype.Text TgLabel *string `json:"tg_label"`
Source pgtype.Text Source *string `json:"source"`
} }
func (q *Queries) AddCall(ctx context.Context, arg AddCallParams) (Call, error) { func (q *Queries) AddCall(ctx context.Context, arg AddCallParams) (Call, error) {
@ -89,7 +89,7 @@ const setCallTranscript = `-- name: SetCallTranscript :exec
UPDATE calls SET transcript = $2 WHERE id = $1 UPDATE calls SET transcript = $2 WHERE id = $1
` `
func (q *Queries) SetCallTranscript(ctx context.Context, iD uuid.UUID, transcript pgtype.Text) error { func (q *Queries) SetCallTranscript(ctx context.Context, iD uuid.UUID, transcript *string) error {
_, err := q.db.Exec(ctx, setCallTranscript, iD, transcript) _, err := q.db.Exec(ctx, setCallTranscript, iD, transcript)
return err return err
} }

View file

@ -10,79 +10,79 @@ import (
) )
type ApiKey struct { type ApiKey struct {
ID int32 ID int32 `json:"id"`
Owner pgtype.Int4 Owner *int32 `json:"owner"`
CreatedAt pgtype.Timestamp CreatedAt pgtype.Timestamp `json:"created_at"`
Expires pgtype.Timestamp Expires pgtype.Timestamp `json:"expires"`
Disabled pgtype.Bool Disabled *bool `json:"disabled"`
ApiKey uuid.UUID ApiKey uuid.UUID `json:"api_key"`
} }
type Call struct { type Call struct {
ID uuid.UUID ID uuid.UUID `json:"id"`
Submitter pgtype.Int4 Submitter *int32 `json:"submitter"`
System int32 System int `json:"system"`
Talkgroup int32 Talkgroup int `json:"talkgroup"`
CallDate pgtype.Timestamp CallDate pgtype.Timestamp `json:"call_date"`
AudioName pgtype.Text AudioName *string `json:"audio_name"`
AudioBlob []byte AudioBlob []byte `json:"audio_blob"`
AudioType pgtype.Text AudioType *string `json:"audio_type"`
AudioUrl pgtype.Text AudioUrl *string `json:"audio_url"`
Frequency pgtype.Int4 Frequency *int32 `json:"frequency"`
Frequencies []byte Frequencies []byte `json:"frequencies"`
Patches []byte Patches []byte `json:"patches"`
TgLabel pgtype.Text TgLabel *string `json:"tg_label"`
Source pgtype.Text Source *string `json:"source"`
Transcript pgtype.Text Transcript *string `json:"transcript"`
} }
type Incident struct { type Incident struct {
ID uuid.UUID ID uuid.UUID `json:"id"`
Name string Name string `json:"name"`
Description pgtype.Text Description *string `json:"description"`
StartTime pgtype.Timestamp StartTime pgtype.Timestamp `json:"start_time"`
EndTime pgtype.Timestamp EndTime pgtype.Timestamp `json:"end_time"`
Location []byte Location []byte `json:"location"`
Metadata []byte Metadata []byte `json:"metadata"`
} }
type IncidentsCall struct { type IncidentsCall struct {
IncidentID uuid.UUID IncidentID uuid.UUID `json:"incident_id"`
CallID uuid.UUID CallID uuid.UUID `json:"call_id"`
Notes []byte Notes []byte `json:"notes"`
} }
type Setting struct { type Setting struct {
Name string Name string `json:"name"`
UpdatedBy pgtype.Int4 UpdatedBy *int32 `json:"updated_by"`
Value []byte Value []byte `json:"value"`
} }
type System struct { type System struct {
ID int32 ID int `json:"id"`
Name string Name string `json:"name"`
} }
type Talkgroup struct { type Talkgroup struct {
SystemID int32 SystemID int `json:"system_id"`
Tgid int32 Tgid int `json:"tgid"`
Name pgtype.Text Name *string `json:"name"`
Frequency pgtype.Int4 Frequency *int32 `json:"frequency"`
AutoCreated pgtype.Bool AutoCreated *bool `json:"auto_created"`
Metadata []byte Metadata []byte `json:"metadata"`
} }
type TalkgroupsTag struct { type TalkgroupsTag struct {
SystemID int32 SystemID int `json:"system_id"`
TalkgroupID int32 TalkgroupID int `json:"talkgroup_id"`
Tags []string Tags []string `json:"tags"`
} }
type User struct { type User struct {
ID int32 ID int32 `json:"id"`
Username string Username string `json:"username"`
Password string Password string `json:"password"`
Email string Email string `json:"email"`
IsAdmin pgtype.Bool IsAdmin *bool `json:"is_admin"`
Prefs []byte Prefs []byte `json:"prefs"`
} }

View file

@ -14,7 +14,7 @@ SELECT tags FROM talkgroups_tags
WHERE talkgroup_id = $1 WHERE talkgroup_id = $1
` `
func (q *Queries) GetTalkgroupTags(ctx context.Context, talkgroupID int32) ([]string, error) { func (q *Queries) GetTalkgroupTags(ctx context.Context, talkgroupID int) ([]string, error) {
row := q.db.QueryRow(ctx, getTalkgroupTags, talkgroupID) row := q.db.QueryRow(ctx, getTalkgroupTags, talkgroupID)
var tags []string var tags []string
err := row.Scan(&tags) err := row.Scan(&tags)
@ -27,8 +27,8 @@ WHERE tags && ARRAY[$1]
` `
type GetTalkgroupsWithAllTagsRow struct { type GetTalkgroupsWithAllTagsRow struct {
SystemID int32 SystemID int `json:"system_id"`
TalkgroupID int32 TalkgroupID int `json:"talkgroup_id"`
} }
func (q *Queries) GetTalkgroupsWithAllTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAllTagsRow, error) { func (q *Queries) GetTalkgroupsWithAllTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAllTagsRow, error) {
@ -57,8 +57,8 @@ WHERE tags @> ARRAY[$1]
` `
type GetTalkgroupsWithAnyTagsRow struct { type GetTalkgroupsWithAnyTagsRow struct {
SystemID int32 SystemID int `json:"system_id"`
TalkgroupID int32 TalkgroupID int `json:"talkgroup_id"`
} }
func (q *Queries) GetTalkgroupsWithAnyTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAnyTagsRow, error) { func (q *Queries) GetTalkgroupsWithAnyTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAnyTagsRow, error) {
@ -86,7 +86,7 @@ INSERT INTO talkgroups_tags(system_id, talkgroup_id, tags) VALUES($1, $2, $3)
ON CONFLICT (system_id, talkgroup_id) DO UPDATE SET tags = $3 ON CONFLICT (system_id, talkgroup_id) DO UPDATE SET tags = $3
` `
func (q *Queries) SetTalkgroupTags(ctx context.Context, systemID int32, talkgroupID int32, tags []string) error { func (q *Queries) SetTalkgroupTags(ctx context.Context, systemID int, talkgroupID int, tags []string) error {
_, err := q.db.Exec(ctx, setTalkgroupTags, systemID, talkgroupID, tags) _, err := q.db.Exec(ctx, setTalkgroupTags, systemID, talkgroupID, tags)
return err return err
} }

View file

@ -23,7 +23,7 @@ INSERT INTO api_keys(
RETURNING id, owner, created_at, expires, disabled, api_key RETURNING id, owner, created_at, expires, disabled, api_key
` `
func (q *Queries) CreateAPIKey(ctx context.Context, owner pgtype.Int4, expires pgtype.Timestamp, disabled pgtype.Bool) (ApiKey, error) { func (q *Queries) CreateAPIKey(ctx context.Context, owner *int32, expires pgtype.Timestamp, disabled *bool) (ApiKey, error) {
row := q.db.QueryRow(ctx, createAPIKey, owner, expires, disabled) row := q.db.QueryRow(ctx, createAPIKey, owner, expires, disabled)
var i ApiKey var i ApiKey
err := row.Scan( err := row.Scan(
@ -48,10 +48,10 @@ RETURNING id, username, password, email, is_admin, prefs
` `
type CreateUserParams struct { type CreateUserParams struct {
Username string Username string `json:"username"`
Password string Password string `json:"password"`
Email string Email string `json:"email"`
IsAdmin pgtype.Bool IsAdmin *bool `json:"is_admin"`
} }
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) { func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) {

View file

@ -11,6 +11,8 @@ import (
"dynatron.me/x/stillbox/pkg/gordio/database" "dynatron.me/x/stillbox/pkg/gordio/database"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jackc/pgtype"
"github.com/rs/zerolog/log"
) )
type callUploadRequest struct { type callUploadRequest struct {
@ -32,6 +34,29 @@ type callUploadRequest struct {
TalkgroupTag string `form:"talkgroupTag"` TalkgroupTag string `form:"talkgroupTag"`
} }
type AddCallParams struct {
Submitter pgtype.Int4 `json:"submitter"`
System int32 `json:"system"`
Talkgroup int32 `json:"talkgroup"`
CallDate pgtype.Timestamp `json:"call_date"`
AudioName pgtype.Text `json:"audio_name"`
AudioBlob []byte `json:"audio_blob"`
AudioType pgtype.Text `json:"audio_type"`
AudioUrl pgtype.Text `json:"audio_url"`
Frequency pgtype.Int4 `json:"frequency"`
Frequencies []byte `json:"frequencies"`
Patches []byte `json:"patches"`
TgLabel pgtype.Text `json:"tg_label"`
Source pgtype.Text `json:"source"`
}
func (car *callUploadRequest) ToAddCallParams(submitter int) database.AddCallParams {
return database.AddCallParams{
Submitter: submitter,
System: car.System,
}
}
func (s *Server) routeCallUpload(w http.ResponseWriter, r *http.Request) { func (s *Server) routeCallUpload(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(1024 * 1024 * 2) // 2MB err := r.ParseMultipartForm(1024 * 1024 * 2) // 2MB
if err != nil { if err != nil {
@ -44,7 +69,8 @@ func (s *Server) routeCallUpload(w http.ResponseWriter, r *http.Request) {
http.Error(w, "cannot parse key "+err.Error(), http.StatusBadRequest) http.Error(w, "cannot parse key "+err.Error(), http.StatusBadRequest)
return return
} }
apik, err := s.db.GetAPIKey(r.Context(), keyUuid) db := database.FromCtx(r.Context())
apik, err := db.GetAPIKey(r.Context(), keyUuid)
if err != nil { if err != nil {
if database.IsNoRows(err) { if database.IsNoRows(err) {
http.Error(w, "bad key", http.StatusUnauthorized) http.Error(w, "bad key", http.StatusUnauthorized)
@ -57,6 +83,7 @@ func (s *Server) routeCallUpload(w http.ResponseWriter, r *http.Request) {
if apik.Disabled.Bool || (apik.Expires.Valid && time.Now().After(apik.Expires.Time)) { if apik.Disabled.Bool || (apik.Expires.Valid && time.Now().After(apik.Expires.Time)) {
http.Error(w, "disabled", http.StatusUnauthorized) http.Error(w, "disabled", http.StatusUnauthorized)
log.Error().Str("key", apik.ApiKey.String()).Msg("key disabled")
return return
} }
@ -67,7 +94,12 @@ func (s *Server) routeCallUpload(w http.ResponseWriter, r *http.Request) {
return return
} }
w.Write([]byte(fmt.Sprintf("%#v", call))) dbCall, err := db.AddCall(r.Context(), call.ToAddCallParams())
if err != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
log.Error().Err(err).Msg("add call")
return
}
} }
func (car *callUploadRequest) fill(r *http.Request) error { func (car *callUploadRequest) fill(r *http.Request) error {

View file

@ -9,9 +9,16 @@ sql:
out: "../pkg/gordio/database" out: "../pkg/gordio/database"
sql_package: "pgx/v5" sql_package: "pgx/v5"
query_parameter_limit: 3 query_parameter_limit: 3
emit_json_tags: true
emit_pointers_for_null_types: true
overrides: overrides:
- db_type: "uuid" - db_type: "uuid"
go_type: go_type:
import: "github.com/google/uuid" import: "github.com/google/uuid"
type: "UUID" type: "UUID"
- db_type: "pg_catalog.int4"
go_type: "int"
- db_type: "pg_catalog.serial4"
go_type: "int"