diff --git a/api/routes.go b/api/routes.go index ff26c10e..8d736037 100644 --- a/api/routes.go +++ b/api/routes.go @@ -107,6 +107,8 @@ func AddRoutesSync(r *mux.Router) { r.Handle("/compliance-request/mailer", authenticatedHandlerJSONPost(compliance_request.CreateMailer)).Methods("POST") //r.HandleFunc("/compliance-request/image/pool/{public_id}", getComplianceRequestImagePool).Methods("GET") r.Handle("/configuration/integration/arcgis", authenticatedHandlerJSONPost(postConfigurationIntegrationArcgis)).Methods("POST") + email := resource.Email(router) + r.Handle("/email/{id}", authenticatedHandlerJSON(email.Get)).Methods("GET").Name("email.ByIDGet") r.Handle("/events", auth.NewEnsureAuth(streamEvents)).Methods("GET") r.Handle("/image/{uuid}", auth.NewEnsureAuth(apiImagePost)).Methods("POST") r.Handle("/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentGet)).Methods("GET") @@ -148,6 +150,8 @@ func AddRoutesSync(r *mux.Router) { r.Handle("/sudo/email", authenticatedHandlerJSONPost(postSudoEmail)).Methods("POST") r.Handle("/sudo/sms", authenticatedHandlerJSONPost(postSudoSMS)).Methods("POST") r.Handle("/sudo/sse", authenticatedHandlerJSONPost(postSudoSSE)).Methods("POST") + text := resource.Text(router) + r.Handle("/text/{id}", authenticatedHandlerJSON(text.Get)).Methods("GET").Name("text.ByIDGet") r.Handle("/trap-data", auth.NewEnsureAuth(apiTrapData)).Methods("GET") r.Handle("/tile/{z}/{y}/{x}", auth.NewEnsureAuth(getTile)).Methods("GET") upload := resource.Upload(r) diff --git a/db/query/comms/email_log.go b/db/query/comms/email_log.go index 5771a499..832995d3 100644 --- a/db/query/comms/email_log.go +++ b/db/query/comms/email_log.go @@ -18,21 +18,6 @@ func CommunicationInsert(ctx context.Context, txn db.Tx, m model.Communication) RETURNING(table.Communication.AllColumns) return db.ExecuteOneTx[model.Communication](ctx, txn, statement) } -func CommunicationFromID(ctx context.Context, comm_id int64) (model.Communication, error) { - statement := table.Communication.SELECT( - table.Communication.AllColumns, - ).FROM(table.Communication). - WHERE(table.Communication.ID.EQ(postgres.Int(comm_id))) - return db.ExecuteOne[model.Communication](ctx, statement) -} -func CommunicationsFromOrganization(ctx context.Context, org_id int64) ([]model.Communication, error) { - statement := table.Communication.SELECT( - table.Communication.AllColumns, - ).FROM(table.Communication). - WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id))). - ORDER_BY(table.Communication.Created.DESC()) - return db.ExecuteMany[model.Communication](ctx, statement) -} func CommunicationSetStatus(ctx context.Context, txn db.Tx, org_id int64, comm_id int64, status model.Communicationstatus) error { statement := table.Communication.UPDATE(). SET( @@ -51,3 +36,11 @@ func EmailLogFromID(ctx context.Context, id int64) (model.EmailLog, error) { WHERE(table.EmailLog.ID.EQ(postgres.Int(id))) return db.ExecuteOne[model.EmailLog](ctx, statement) } +func EmailLogsFromAddress(ctx context.Context, address string) ([]model.EmailLog, error) { + statement := table.EmailLog.SELECT( + table.EmailLog.AllColumns, + ).FROM(table.EmailLog). + WHERE(table.EmailLog.Source.EQ(postgres.String(address)).OR( + table.EmailLog.Destination.EQ(postgres.String(address)))) + return db.ExecuteMany[model.EmailLog](ctx, statement) +} diff --git a/db/query/comms/text_log.go b/db/query/comms/text_log.go index 85a81509..1bfbf18a 100644 --- a/db/query/comms/text_log.go +++ b/db/query/comms/text_log.go @@ -16,3 +16,11 @@ func TextLogFromID(ctx context.Context, id int64) (model.TextLog, error) { WHERE(table.TextLog.ID.EQ(postgres.Int(id))) return db.ExecuteOne[model.TextLog](ctx, statement) } +func TextLogsFromPhoneNumber(ctx context.Context, number string) ([]model.TextLog, error) { + statement := table.TextLog.SELECT( + table.TextLog.AllColumns, + ).FROM(table.TextLog). + WHERE(table.TextLog.Source.EQ(postgres.String(number)).OR( + table.TextLog.Destination.EQ(postgres.String(number)))) + return db.ExecuteMany[model.TextLog](ctx, statement) +} diff --git a/db/query/publicreport/report.go b/db/query/publicreport/report.go index 7236b8ac..349d1b31 100644 --- a/db/query/publicreport/report.go +++ b/db/query/publicreport/report.go @@ -28,6 +28,14 @@ func ReportInsert(ctx context.Context, txn db.Ex, m model.Report) (model.Report, RETURNING(table.Report.AllColumns) return db.ExecuteOneTx[model.Report](ctx, txn, statement) } +func ReportsFromAddressID(ctx context.Context, txn db.Ex, org_id int64, address_id int64) ([]model.Report, error) { + statement := table.Report.SELECT( + table.Report.AllColumns, + ).FROM(table.Report). + WHERE(table.Report.AddressID.EQ(postgres.Int(address_id)).AND( + table.Report.OrganizationID.EQ(postgres.Int(org_id)))) + return db.ExecuteManyTx[model.Report](ctx, txn, statement) +} func ReportFromID(ctx context.Context, report_id int64) (model.Report, error) { statement := table.Report.SELECT( table.Report.AllColumns, @@ -87,6 +95,14 @@ func ReportFromPublicIDForOrg(ctx context.Context, txn db.Ex, public_id string, } return &result, nil } +func ReportsFromReporterName(ctx context.Context, txn db.Ex, org_id int64, name string) ([]model.Report, error) { + statement := table.Report.SELECT( + table.Report.AllColumns, + ).FROM(table.Report). + WHERE(table.Report.ReporterName.EQ(postgres.String(name)).AND( + table.Report.OrganizationID.EQ(postgres.Int(org_id)))) + return db.ExecuteManyTx[model.Report](ctx, txn, statement) +} func ReportsUnreviewedForOrganization(ctx context.Context, txn db.Ex, org_id int64) ([]model.Report, error) { statement := table.Report.SELECT( table.Report.AllColumns, diff --git a/platform/communication.go b/platform/communication.go index cc4d2e28..c21bc960 100644 --- a/platform/communication.go +++ b/platform/communication.go @@ -7,7 +7,8 @@ import ( "time" "github.com/Gleipnir-Technology/nidus-sync/db" - "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" querycomms "github.com/Gleipnir-Technology/nidus-sync/db/query/comms" querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public" querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport" @@ -16,12 +17,37 @@ import ( "github.com/rs/zerolog/log" ) -type RelatedRecord struct { - ID int32 - Type string +type RelatedRecordType int + +const ( + RelatedRecordTypeUnknown RelatedRecordType = iota + RelatedRecordTypeEmail + RelatedRecordTypeReportCompliance + RelatedRecordTypeReportNuisance + RelatedRecordTypeReportWater + RelatedRecordTypeText +) + +func recordTypeFromReportType(t modelpublicreport.Reporttype) RelatedRecordType { + switch t { + case modelpublicreport.Reporttype_Compliance: + return RelatedRecordTypeReportCompliance + case modelpublicreport.Reporttype_Nuisance: + return RelatedRecordTypeReportNuisance + case modelpublicreport.Reporttype_Water: + return RelatedRecordTypeReportWater + default: + return RelatedRecordTypeUnknown + } } -func CommunicationRelatedRecords(ctx context.Context, user User, comm *model.Communication) ([]RelatedRecord, error) { +type RelatedRecord struct { + Created time.Time + ID string + Type RelatedRecordType +} + +func CommunicationRelatedRecords(ctx context.Context, user User, comm *modelpublic.Communication) ([]RelatedRecord, error) { // Gather associated records // * address // * phone number @@ -33,28 +59,72 @@ func CommunicationRelatedRecords(ctx context.Context, user User, comm *model.Com if err != nil { return result, fmt.Errorf("email log from ID: %w", err) } - log.Debug().Int32("id", email_log.ID).Send() - } - if comm.SourceTextLogID != nil { + email_logs, err := querycomms.EmailLogsFromAddress(ctx, email_log.Source) + if err != nil { + return result, fmt.Errorf("email log from ID: %w", err) + } + for _, log := range email_logs { + result = append(result, RelatedRecord{ + Created: log.Created, + ID: strconv.Itoa(int(log.ID)), + Type: RelatedRecordTypeEmail, + }) + } + } else if comm.SourceTextLogID != nil { text_log, err := querycomms.TextLogFromID(ctx, int64(*comm.SourceTextLogID)) if err != nil { return result, fmt.Errorf("text log from ID: %w", err) } - log.Debug().Int32("id", text_log.ID).Send() - } - if comm.SourceReportID != nil { + text_logs, err := querycomms.EmailLogsFromAddress(ctx, text_log.Source) + if err != nil { + return result, fmt.Errorf("text log from ID: %w", err) + } + for _, log := range text_logs { + result = append(result, RelatedRecord{ + Created: log.Created, + ID: strconv.Itoa(int(log.ID)), + Type: RelatedRecordTypeText, + }) + } + } else if comm.SourceReportID != nil { report, err := querypublicreport.ReportFromID(ctx, int64(*comm.SourceReportID)) if err != nil { return result, fmt.Errorf("report from ID: %w", err) } - log.Debug().Int32("id", report.ID).Send() + if report.ReporterName != "" { + reports_by_name, err := querypublicreport.ReportsFromReporterName(ctx, db.PGInstance.PGXPool, int64(user.Organization.ID), report.ReporterName) + if err != nil { + return result, fmt.Errorf("reports from reporter name '%s': %w", report.ReporterName, err) + } + for _, r := range reports_by_name { + record_type := recordTypeFromReportType(r.ReportType) + result = append(result, RelatedRecord{ + Created: r.Created, + ID: r.PublicID, + Type: record_type, + }) + } + } + if report.AddressID != nil { + reports_by_address, err := querypublicreport.ReportsFromAddressID(ctx, db.PGInstance.PGXPool, int64(user.Organization.ID), int64(*report.AddressID)) + if err != nil { + return result, fmt.Errorf("reports from reporter name '%s': %w", report.ReporterName, err) + } + for _, r := range reports_by_address { + record_type := recordTypeFromReportType(r.ReportType) + result = append(result, RelatedRecord{ + ID: r.PublicID, + Type: record_type, + }) + } + } } return result, nil } -func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]model.Communication, error) { +func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]modelpublic.Communication, error) { return querypublic.CommunicationsFromOrganization(ctx, org_id) } -func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*model.Communication, error) { +func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*modelpublic.Communication, error) { comm, err := querypublic.CommunicationFromID(ctx, comm_id) if err != nil { return nil, err @@ -65,19 +135,19 @@ func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*model. return &comm, nil } func CommunicationMarkInvalid(ctx context.Context, user User, comm_id int32) error { - return communicationMark(ctx, user, comm_id, model.Communicationstatus_Invalid, model.Communicationlogentry_StatusInvalidated) + return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_Invalid, modelpublic.Communicationlogentry_StatusInvalidated) } func CommunicationMarkPendingResponse(ctx context.Context, user User, comm_id int32) error { - return communicationMark(ctx, user, comm_id, model.Communicationstatus_Pending, model.Communicationlogentry_StatusPending) + return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_Pending, modelpublic.Communicationlogentry_StatusPending) } func CommunicationMarkPossibleIssue(ctx context.Context, user User, comm_id int32) error { - return communicationMark(ctx, user, comm_id, model.Communicationstatus_PossibleIssue, model.Communicationlogentry_StatusPossibleIssue) + return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_PossibleIssue, modelpublic.Communicationlogentry_StatusPossibleIssue) } func CommunicationMarkPossibleResolved(ctx context.Context, user User, comm_id int32) error { - return communicationMark(ctx, user, comm_id, model.Communicationstatus_PossibleResolved, model.Communicationlogentry_StatusPossibleResolved) + return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_PossibleResolved, modelpublic.Communicationlogentry_StatusPossibleResolved) } -func communicationMark(ctx context.Context, user User, comm_id int32, status model.Communicationstatus, log_type model.Communicationlogentry) error { +func communicationMark(ctx context.Context, user User, comm_id int32, status modelpublic.Communicationstatus, log_type modelpublic.Communicationlogentry) error { txn, err := db.BeginTxn(ctx) if err != nil { return fmt.Errorf("begin txn: %w", err) @@ -88,7 +158,7 @@ func communicationMark(ctx context.Context, user User, comm_id int32, status mod return fmt.Errorf("mark: %w", err) } user_id := int32(user.ID) - log_entry := model.CommunicationLogEntry{ + log_entry := modelpublic.CommunicationLogEntry{ CommunicationID: comm_id, Created: time.Now(), Type: log_type, diff --git a/resource/communication.go b/resource/communication.go index e3a0f537..05789fcb 100644 --- a/resource/communication.go +++ b/resource/communication.go @@ -2,6 +2,7 @@ package resource import ( "context" + "fmt" "net/http" "strconv" "time" @@ -10,8 +11,7 @@ import ( modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/Gleipnir-Technology/nidus-sync/platform" - "github.com/gorilla/mux" - //"github.com/rs/zerolog/log" + "github.com/rs/zerolog/log" ) type communicationR struct { @@ -24,45 +24,58 @@ func Communication(r *router) *communicationR { } } +type communicationLogType string +type communicationType string + +const ( + communicationTypeUnknown communicationType = "unknown" + communicationTypeReportCompliance = "publicreport.compliance" + communicationTypeReportNuisance = "publicreport.nuisance" + communicationTypeReportWater = "publicreport.water" +) + type communicationLog struct { - Created time.Time `json:"created"` - ID string `json:"id"` - Type string `json:"type"` - User string `json:"user"` + Created time.Time `json:"created"` + ID string `json:"id"` + Type communicationLogType `json:"type"` + User string `json:"user"` } type communication struct { - Context []resourceStub `json:"context"` Created time.Time `json:"created"` ID string `json:"id"` Log []communicationLog `json:"log"` + Related []resourceStub `json:"related"` Response string `json:"response"` Source string `json:"source"` Status string `json:"status"` - Type string `json:"type"` + Type communicationType `json:"type"` URI string `json:"uri"` } -type communicationStub struct { - Created time.Time `json:"created"` - ID string `json:"id"` - Source string `json:"source"` - Status string `json:"status"` - Type string `json:"type"` - URI string `json:"uri"` -} +type resourceType string + +const ( + resourceTypeUnknown resourceType = "unknown" + resourceTypeEmail = "email" + resourceTypeReportCompliance = "publicreport.compliance" + resourceTypeReportNuisance = "publicreport.nuisance" + resourceTypeReportWater = "publicreport.water" + resourceTypeText = "text" +) + type resourceStub struct { - Created time.Time `json:"created"` - Type string `json:"type"` - URI string `json:"uri"` + Created time.Time `json:"created"` + Type resourceType `json:"type"` + URI string `json:"uri"` } func (res *communicationR) Get(ctx context.Context, r *http.Request, user platform.User, query QueryParams) (communication, *nhttp.ErrorWithStatus) { - comm_id, error_with_status := communicationIDFromMux(r) + comm_id, error_with_status := res.router.IDFromMux(r) if error_with_status != nil { return communication{}, error_with_status } return res.hydratedCommunicationFromID(ctx, user, int32(comm_id)) } -func (res *communicationR) List(ctx context.Context, r *http.Request, user platform.User, query QueryParams) ([]communicationStub, *nhttp.ErrorWithStatus) { +func (res *communicationR) List(ctx context.Context, r *http.Request, user platform.User, query QueryParams) ([]communication, *nhttp.ErrorWithStatus) { comms, err := platform.CommunicationsForOrganization(ctx, int64(user.Organization.ID)) if err != nil { return nil, nhttp.NewError("nuisance report query: %w", err) @@ -81,13 +94,17 @@ func (res *communicationR) List(ctx context.Context, r *http.Request, user platf for _, pr := range public_reports { public_report_id_to_report[pr.ID] = pr } - result := make([]communicationStub, len(comms)) + result := make([]communication, len(comms)) for i, comm := range comms { public_report, ok := public_report_id_to_report[*comm.SourceReportID] if !ok { return nil, nhttp.NewError("lookup report id %d failed", comm.SourceReportID) } - c, e := res.hydrateCommunicationStub(comm, &public_report) + related_records, err := platform.CommunicationRelatedRecords(ctx, user, &comm) + if err != nil { + return nil, nhttp.NewError("related records: %w", err) + } + c, e := res.hydrateCommunication(comm, related_records, &public_report) if e != nil { return nil, e } @@ -110,59 +127,89 @@ func (res *communicationR) MarkPossibleIssue(ctx context.Context, r *http.Reques func (res *communicationR) MarkPossibleResolved(ctx context.Context, r *http.Request, user platform.User, cmr communicationMarkRequest) (communication, *nhttp.ErrorWithStatus) { return res.markCommunication(ctx, r, user, "possible-resolved", platform.CommunicationMarkPossibleResolved) } -func (res *communicationR) hydrateCommunication(comm modelpublic.Communication, public_report *modelpublicreport.Report) (communication, *nhttp.ErrorWithStatus) { - stub, e := res.hydrateCommunicationStub(comm, public_report) - if e != nil { - return communication{}, e +func (res *communicationR) hydrateCommunication(comm modelpublic.Communication, related_records []platform.RelatedRecord, public_report *modelpublicreport.Report) (communication, *nhttp.ErrorWithStatus) { + var err error + source_uri := "unknown" + type_ := communicationTypeUnknown + if comm.SourceReportID != nil && public_report != nil { + source_uri, err = reportURI(res.router, "", public_report.PublicID) + if err != nil { + return communication{}, nhttp.NewError("gen report URI: %w", err) + } + switch public_report.ReportType { + case modelpublicreport.Reporttype_Compliance: + type_ = communicationTypeReportCompliance + case modelpublicreport.Reporttype_Nuisance: + type_ = communicationTypeReportNuisance + case modelpublicreport.Reporttype_Water: + type_ = communicationTypeReportWater + default: + type_ = communicationTypeUnknown + } + } else if comm.SourceEmailLogID != nil { + source_uri, err = emailURI(*res.router, *comm.SourceEmailLogID) + if err != nil { + return communication{}, nhttp.NewError("gen email URI: %w", err) + } + type_ = "email" + } else if comm.SourceTextLogID != nil { + source_uri, err = textURI(*res.router, *comm.SourceTextLogID) + if err != nil { + return communication{}, nhttp.NewError("gen email URI: %w", err) + } + source_uri = "text" + } + uri, err := res.router.IDToURI("communication.ByIDGet", int(comm.ID)) + if err != nil { + return communication{}, nhttp.NewError("gen comm uri: %w", err) + } + related := make([]resourceStub, len(related_records)) + for i, rr := range related_records { + var uri string + var r_type resourceType + switch rr.Type { + case platform.RelatedRecordTypeEmail: + r_type = resourceTypeEmail + uri, err = res.router.IDStrToURI("email.GetByID", rr.ID) + case platform.RelatedRecordTypeReportCompliance: + r_type = resourceTypeReportCompliance + uri, err = res.router.IDStrToURI("publicreport.compliance.GetByID", rr.ID) + case platform.RelatedRecordTypeReportNuisance: + r_type = resourceTypeReportNuisance + uri, err = res.router.IDStrToURI("publicreport.nuisance.GetByID", rr.ID) + case platform.RelatedRecordTypeReportWater: + r_type = resourceTypeReportWater + uri, err = res.router.IDStrToURI("publicreport.water.GetByID", rr.ID) + case platform.RelatedRecordTypeText: + r_type = resourceTypeText + uri, err = res.router.IDStrToURI("text.GetByID", rr.ID) + default: + r_type = resourceTypeUnknown + err = fmt.Errorf("unrecognized related record type '%s'", rr.Type) + } + if err != nil { + return communication{}, nhttp.NewError("related record hydration: %w", err) + } + related[i] = resourceStub{ + Created: rr.Created, + Type: r_type, + URI: uri, + } + log.Debug().Str("created", rr.Created.String()).Str("id", rr.ID).Str("uri", uri).Msg("related record") } response, err := responseURI(*res.router, comm) if err != nil { return communication{}, nhttp.NewError("gen response URI: %w", err) } return communication{ - Created: stub.Created, - ID: stub.ID, + Created: comm.Created, + ID: strconv.Itoa(int(comm.ID)), + Related: related, Response: response, - Source: stub.Source, - Status: stub.Status, - Type: stub.Type, - URI: stub.URI, - }, nil -} -func (res *communicationR) hydrateCommunicationStub(comm modelpublic.Communication, public_report *modelpublicreport.Report) (communicationStub, *nhttp.ErrorWithStatus) { - var err error - source_uri := "unknown" - type_ := "unknown" - if comm.SourceReportID != nil && public_report != nil { - source_uri, err = reportURI(res.router, "", public_report.PublicID) - if err != nil { - return communicationStub{}, nhttp.NewError("gen report URI: %w", err) - } - type_ = "publicreport." + public_report.ReportType.String() - } else if comm.SourceEmailLogID != nil { - source_uri, err = emailURI(*res.router, *comm.SourceEmailLogID) - if err != nil { - return communicationStub{}, nhttp.NewError("gen email URI: %w", err) - } - type_ = "email" - } else if comm.SourceTextLogID != nil { - source_uri, err = textURI(*res.router, *comm.SourceTextLogID) - if err != nil { - return communicationStub{}, nhttp.NewError("gen email URI: %w", err) - } - source_uri = "text" - } - uri, err := res.router.IDToURI("communication.ByIDGet", int(comm.ID)) - if err != nil { - return communicationStub{}, nhttp.NewError("gen comm uri: %w", err) - } - return communicationStub{ - Created: comm.Created, - ID: strconv.Itoa(int(comm.ID)), - Source: source_uri, - Status: comm.Status.String(), - Type: type_, - URI: uri, + Source: source_uri, + Status: comm.Status.String(), + Type: type_, + URI: uri, }, nil } @@ -184,14 +231,18 @@ func (res *communicationR) hydratedCommunicationFromID(ctx context.Context, user } public_report = public_reports[0] } + related_records, err := platform.CommunicationRelatedRecords(ctx, user, comm) + if err != nil { + return communication{}, nhttp.NewError("related records: %w", err) + } - return res.hydrateCommunication(*comm, &public_report) + return res.hydrateCommunication(*comm, related_records, &public_report) } type markFunc = func(context.Context, platform.User, int32) error func (res *communicationR) markCommunication(ctx context.Context, r *http.Request, user platform.User, status string, m markFunc) (communication, *nhttp.ErrorWithStatus) { - comm_id, err_with_status := communicationIDFromMux(r) + comm_id, err_with_status := res.router.IDFromMux(r) if err_with_status != nil { return communication{}, err_with_status } @@ -201,18 +252,6 @@ func (res *communicationR) markCommunication(ctx context.Context, r *http.Reques } return res.hydratedCommunicationFromID(ctx, user, int32(comm_id)) } -func communicationIDFromMux(r *http.Request) (int, *nhttp.ErrorWithStatus) { - vars := mux.Vars(r) - comm_id_str := vars["id"] - if comm_id_str == "" { - return 0, nhttp.NewBadRequest("no id provided") - } - comm_id, err := strconv.Atoi(comm_id_str) - if err != nil { - return 0, nhttp.NewBadRequest("can't turn report ID into an int: %w", err) - } - return comm_id, nil -} func responseURI(r router, comm modelpublic.Communication) (string, error) { if comm.ResponseEmailLogID != nil { return emailURI(r, *comm.ResponseEmailLogID) @@ -229,4 +268,3 @@ func emailURI(r router, id int32) (string, error) { func textURI(r router, id int32) (string, error) { return "fake text uri", nil } - diff --git a/resource/email.go b/resource/email.go new file mode 100644 index 00000000..68bd5d29 --- /dev/null +++ b/resource/email.go @@ -0,0 +1,35 @@ +package resource + +import ( + "context" + "net/http" + + //modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + //modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + nhttp "github.com/Gleipnir-Technology/nidus-sync/http" + "github.com/Gleipnir-Technology/nidus-sync/platform" + //"github.com/gorilla/mux" + //"github.com/rs/zerolog/log" +) + +type emailR struct { + router *router +} + +func Email(r *router) *emailR { + return &emailR{ + router: r, + } +} + +type email struct { + ID int +} + +func (res *emailR) Get(ctx context.Context, r *http.Request, user platform.User, query QueryParams) (email, *nhttp.ErrorWithStatus) { + email_id, error_with_status := res.router.IDFromMux(r) + if error_with_status != nil { + return email{}, error_with_status + } + return email{ID: email_id}, nil +} diff --git a/resource/router.go b/resource/router.go index 2e4adeb1..f496bc67 100644 --- a/resource/router.go +++ b/resource/router.go @@ -5,6 +5,7 @@ import ( "net/http" "strconv" + nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/google/uuid" "github.com/gorilla/mux" "github.com/rs/zerolog/log" @@ -19,6 +20,18 @@ func NewRouter(r *mux.Router) *router { router: r, } } +func (r *router) IDFromMux(req *http.Request) (int, *nhttp.ErrorWithStatus) { + vars := mux.Vars(req) + comm_id_str := vars["id"] + if comm_id_str == "" { + return 0, nhttp.NewBadRequest("no id provided") + } + comm_id, err := strconv.Atoi(comm_id_str) + if err != nil { + return 0, nhttp.NewBadRequest("can't turn report ID into an int: %w", err) + } + return comm_id, nil +} func (r *router) IDFromURI(route string, uri string) (*int, error) { var match mux.RouteMatch req, _ := http.NewRequest("GET", uri, nil) diff --git a/resource/text.go b/resource/text.go new file mode 100644 index 00000000..cd31ae54 --- /dev/null +++ b/resource/text.go @@ -0,0 +1,35 @@ +package resource + +import ( + "context" + "net/http" + + //modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model" + //modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model" + nhttp "github.com/Gleipnir-Technology/nidus-sync/http" + "github.com/Gleipnir-Technology/nidus-sync/platform" + //"github.com/gorilla/mux" + //"github.com/rs/zerolog/log" +) + +type textR struct { + router *router +} + +func Text(r *router) *textR { + return &textR{ + router: r, + } +} + +type textResource struct { + ID int +} + +func (res *textR) Get(ctx context.Context, r *http.Request, user platform.User, query QueryParams) (textResource, *nhttp.ErrorWithStatus) { + text_id, error_with_status := res.router.IDFromMux(r) + if error_with_status != nil { + return textResource{}, error_with_status + } + return textResource{ID: text_id}, nil +}