From f04a49f08c32fea3d6d1200d3175e0b635e60e7f Mon Sep 17 00:00:00 2001 From: Dennis Smith Date: Fri, 16 Jan 2026 16:55:55 -0500 Subject: [PATCH 1/2] chore: fix various staticcheck warnings and style reccommendations --- api/cmd/midas-api/main.go | 6 +- api/cmd/midas-sql/main.go | 4 +- api/internal/alertscheduler/alertscheduler.go | 7 ++- api/internal/cloud/api.go | 12 ++-- api/internal/cloud/cloud.go | 2 + api/internal/cloud/dcsloader.go | 2 +- api/internal/config/api.go | 18 +++--- api/internal/config/config.go | 1 + api/internal/config/dcsloader.go | 2 +- api/internal/config/server.go | 2 +- api/internal/config/telemetry.go | 2 +- api/internal/config/thinglogix.go | 2 +- api/internal/ctxkey/ctxkey.go | 1 + api/internal/db/overrides.go | 7 ++- api/internal/dto/dto.go | 2 + api/internal/dto/worker_alert_schedule.go | 2 + api/internal/email/ses/ses.go | 1 + api/internal/email/smtp/smtp.go | 1 + api/internal/handler/alert.go | 2 +- api/internal/handler/alert_config.go | 2 +- api/internal/handler/alert_subscription.go | 2 +- api/internal/handler/alert_test.go | 2 - api/internal/handler/api.go | 57 +++++++++---------- api/internal/handler/arcgis.go | 4 +- api/internal/handler/autocomplete.go | 2 +- api/internal/handler/aware.go | 2 +- api/internal/handler/collection_groups.go | 2 +- api/internal/handler/datalogger.go | 2 +- api/internal/handler/datalogger_proxy.go | 8 +-- api/internal/handler/datalogger_telemetry.go | 6 +- api/internal/handler/dcsloader.go | 10 ++-- api/internal/handler/dcsloader_test.go | 16 ++---- api/internal/handler/district_rollup.go | 2 +- api/internal/handler/domain.go | 2 +- api/internal/handler/equivalency_table.go | 2 +- api/internal/handler/evaluation.go | 2 +- api/internal/handler/formula.go | 2 +- api/internal/handler/handler.go | 3 +- api/internal/handler/handler_test.go | 6 +- api/internal/handler/heartbeat.go | 2 +- api/internal/handler/home.go | 2 +- api/internal/handler/instrument.go | 2 +- api/internal/handler/instrument_assign.go | 2 +- api/internal/handler/instrument_group.go | 2 +- api/internal/handler/instrument_incl.go | 2 +- api/internal/handler/instrument_ipi.go | 2 +- api/internal/handler/instrument_note.go | 2 +- api/internal/handler/instrument_saa.go | 2 +- api/internal/handler/instrument_seis.go | 2 +- api/internal/handler/instrument_status.go | 2 +- api/internal/handler/measurement.go | 2 +- api/internal/handler/media.go | 2 +- api/internal/handler/plot_config.go | 2 +- api/internal/handler/plot_config_bullseye.go | 2 +- api/internal/handler/plot_config_contour.go | 2 +- api/internal/handler/plot_config_profile.go | 2 +- .../handler/plot_config_scatter_line.go | 2 +- api/internal/handler/profile.go | 4 +- api/internal/handler/project.go | 2 +- api/internal/handler/project_role.go | 2 +- api/internal/handler/report_config.go | 4 +- api/internal/handler/submittal.go | 2 +- api/internal/handler/survey123.go | 2 +- api/internal/handler/survey123_proxy.go | 6 +- api/internal/handler/telemetry.go | 6 +- api/internal/handler/timeseries.go | 2 +- api/internal/handler/timeseries_cwms.go | 2 +- api/internal/handler/timeseries_process.go | 6 +- api/internal/handler/uploader.go | 2 +- api/internal/httperr/httperr.go | 3 +- api/internal/logger/logger.go | 1 + api/internal/middleware/audit.go | 2 +- api/internal/middleware/ip_whitelist.go | 6 +- api/internal/middleware/key.go | 10 ++-- api/internal/middleware/middleware.go | 7 ++- api/internal/migrate/migrate.go | 5 +- api/internal/mseed/mseed.go | 9 +-- api/internal/mseed/parse.go | 6 +- api/internal/mseed/types.go | 4 +- api/internal/mseed/unpack.go | 4 +- api/internal/mseed/utils.go | 4 +- api/internal/password/password.go | 1 + api/internal/pgqueue/batcher.go | 2 +- api/internal/pgqueue/pgqueue.go | 1 + api/internal/service/alert_check_event.go | 8 +-- api/internal/service/alert_config_schedule.go | 3 + api/internal/service/datalogger_telemetry.go | 6 +- api/internal/service/db.go | 1 + api/internal/service/dcsloader.go | 16 +++--- api/internal/service/instrument_incl.go | 6 +- api/internal/service/instrument_ipi.go | 6 +- api/internal/service/instrument_saa.go | 6 +- api/internal/service/plot_config_contour.go | 4 ++ .../service/plot_config_scatter_line.go | 7 ++- api/internal/service/profile.go | 8 +-- api/internal/service/project.go | 5 -- api/internal/service/survey123.go | 2 - api/internal/service/thinglogix.go | 40 ++++++------- api/internal/timewindow/timewindow.go | 1 + api/internal/tz/tz.go | 3 +- api/internal/upload/upload.go | 3 +- api/internal/util/redactor.go | 2 + api/internal/util/util.go | 2 + api/internal/worker/worker.go | 1 + 104 files changed, 252 insertions(+), 229 deletions(-) create mode 100644 api/internal/cloud/cloud.go create mode 100644 api/internal/dto/dto.go create mode 100644 api/internal/util/util.go diff --git a/api/cmd/midas-api/main.go b/api/cmd/midas-api/main.go index c2e07c32..a95cd912 100644 --- a/api/cmd/midas-api/main.go +++ b/api/cmd/midas-api/main.go @@ -13,7 +13,7 @@ import ( func main() { ctx := context.Background() - cfg := config.NewApiConfig() + cfg := config.NewAPIConfig() l := logger.NewLogger(&cfg.LoggerConfig) if err := run(ctx, cfg, l); err != nil { @@ -22,8 +22,8 @@ func main() { } } -func run(ctx context.Context, cfg *config.ApiConfig, l *logger.Logger) (err error) { - h, err := handler.NewApi(ctx, cfg, l) +func run(ctx context.Context, cfg *config.APIConfig, l *logger.Logger) (err error) { + h, err := handler.NewAPI(ctx, cfg, l) if err != nil { return err } diff --git a/api/cmd/midas-sql/main.go b/api/cmd/midas-sql/main.go index c9b73903..1589ed76 100644 --- a/api/cmd/midas-sql/main.go +++ b/api/cmd/midas-sql/main.go @@ -57,9 +57,9 @@ func main() { } func migrateDBConfig(cfg *config.MigrateConfig) migrate.DBConfig { - dbUrl := strings.TrimPrefix(cfg.DBUrl, "jdbc:postgresql://") + DBUrl := strings.TrimPrefix(cfg.DBUrl, "jdbc:postgresql://") - dd := strings.Split(dbUrl, "/") + dd := strings.Split(DBUrl, "/") if len(dd) == 0 { log.Fatal("invalid database url") diff --git a/api/internal/alertscheduler/alertscheduler.go b/api/internal/alertscheduler/alertscheduler.go index 983de436..30c16b51 100644 --- a/api/internal/alertscheduler/alertscheduler.go +++ b/api/internal/alertscheduler/alertscheduler.go @@ -1,3 +1,4 @@ +// Package alertscheduler provides functionality to schedule alert notification jobs for submittals. package alertscheduler import ( @@ -41,7 +42,7 @@ func New(queuer pgqueue.PGQueueClient, dbtx db.DBTX, querier db.Querier, opts .. return a } -// JobAddForSubmittal adds a job to be scheduled for a Submittal and given NotificationType. It does not insert the job to the queue (see InsertJobs). +// PrepareSubmittalJob adds a job to be scheduled for a Submittal and given NotificationType. It does not insert the job to the queue (see InsertJobs). // // For each alert config id that is a "reminder" type, we want to ensure the job does not run more than once in a 24 hour period. func (a *AlertScheduler) PrepareSubmittalJob(ctx context.Context, sub db.VSubmittal, nt dto.NotificationType) error { @@ -84,7 +85,7 @@ func (a *AlertScheduler) PrepareSubmittalJob(ctx context.Context, sub db.VSubmit return nil } -// JobInsertForSubmittal inserts jobs added with JobAddForSubmittal into the queue. It does not commit the transaction. +// InsertPreparedSubmittalJobs inserts jobs added with JobAddForSubmittal into the queue. It does not commit the transaction. func (a *AlertScheduler) InsertPreparedSubmittalJobs(ctx context.Context, sub db.VSubmittal) error { if a.disabled || len(a.jobs) == 0 { return nil @@ -131,7 +132,7 @@ func (a *AlertScheduler) CancelJobsForAlertConfig(ctx context.Context, acID uuid return nil } -// SubmittalCreateWithAlertScheduleJobs creates a new submittal and schedules jobs for the alert config. +// SubmittalCreateAndPrepareJobs creates a new submittal and schedules jobs for the alert config. // // The new submittal due date is calculated based on the "createAt" date passed + the schedule interval. // NOTE: Tx must be commited by the caller. diff --git a/api/internal/cloud/api.go b/api/internal/cloud/api.go index e55215e3..b05005af 100644 --- a/api/internal/cloud/api.go +++ b/api/internal/cloud/api.go @@ -12,8 +12,8 @@ import ( _ "gocloud.dev/pubsub/awssnssqs" ) -// ApiServices provides services for the API -type ApiServices struct { +// APIServices provides services for the API +type APIServices struct { // MediaBucket reads and writes application media to and from a bucket MediaBucket *blob.Bucket // ReportTaskPub publishes report jobs to a queue that are sent to an async PDF report renderer @@ -24,8 +24,8 @@ type ApiServices struct { AlertEventBatcherSub *pubsub.Subscription } -// NewApiServices creates a new ApiServices instance -func NewApiServices(ctx context.Context, cfg *config.ApiConfig) (*ApiServices, error) { +// NewAPIServices creates a new ApiServices instance +func NewAPIServices(ctx context.Context, cfg *config.APIConfig) (*APIServices, error) { mediaBucket, err := blob.OpenBucket(ctx, cfg.MediaBucketURI) if err != nil { return nil, err @@ -47,7 +47,7 @@ func NewApiServices(ctx context.Context, cfg *config.ApiConfig) (*ApiServices, e return nil, err } - return &ApiServices{ + return &APIServices{ MediaBucket: mediaBucket, ReportTaskPub: reportTaskPub, AlertEventBatcherPub: alertEventBatcherPub, @@ -56,7 +56,7 @@ func NewApiServices(ctx context.Context, cfg *config.ApiConfig) (*ApiServices, e } // Shutdown closes the ApiServices and its resources -func (s *ApiServices) Shutdown(ctx context.Context) error { +func (s *APIServices) Shutdown(ctx context.Context) error { errs := make([]error, 0) if a := s.MediaBucket; a != nil { errs = append(errs, a.Close()) diff --git a/api/internal/cloud/cloud.go b/api/internal/cloud/cloud.go new file mode 100644 index 00000000..a827f02e --- /dev/null +++ b/api/internal/cloud/cloud.go @@ -0,0 +1,2 @@ +// Package cloud provides cloud-related utilities and abstractions. +package cloud diff --git a/api/internal/cloud/dcsloader.go b/api/internal/cloud/dcsloader.go index e224ba91..e9b19805 100644 --- a/api/internal/cloud/dcsloader.go +++ b/api/internal/cloud/dcsloader.go @@ -54,7 +54,7 @@ func (s *DcsLoaderServices) Shutdown(ctx context.Context) error { return errors.Join(errs...) } -// messageToS3Event converts a pubsub message to an S3 event +// MessageToS3Event converts a pubsub message to an S3 event func MessageToS3Event(ctx context.Context, msg *pubsub.Message, l *logger.Logger) (events.S3Event, error) { var evt events.S3Event diff --git a/api/internal/config/api.go b/api/internal/config/api.go index e3b76744..92ab7a7a 100644 --- a/api/internal/config/api.go +++ b/api/internal/config/api.go @@ -7,8 +7,8 @@ import ( "github.com/USACE/instrumentation-api/api/v4/internal/tz" ) -// Config stores configuration information stored in environment variables -type ApiConfig struct { +// APIConfig stores configuration information stored in environment variables +type APIConfig struct { LoggerConfig DBConfig ServerConfig @@ -25,9 +25,9 @@ type ApiConfig struct { CwmsProxyURL string `env:"CWMS_PROXY_URL" envDefault:"https://cwms-data.usace.army.mil/cwms-data/"` } -// GetConfig returns environment variable config -func NewApiConfig() *ApiConfig { - var cfg ApiConfig +// NewAPIConfig returns environment variable config +func NewAPIConfig() *APIConfig { + var cfg APIConfig cfg.BuildTag = os.Getenv("BUILD_TAG") if err := parsePrefix("INSTRUMENTATION_", &cfg); err != nil { panic(err) @@ -35,13 +35,13 @@ func NewApiConfig() *ApiConfig { switch cfg.BuildTag { case "local": - cfg.ServerBaseUrl = "http://localhost:8080" + cfg.ServerBaseURL = "http://localhost:8080" case "develop": - cfg.ServerBaseUrl = "https://develop-midas-api.rsgis.dev" + cfg.ServerBaseURL = "https://develop-midas-api.rsgis.dev" case "test": - cfg.ServerBaseUrl = "https://midas-test.cwbi.us/api" + cfg.ServerBaseURL = "https://midas-test.cwbi.us/api" case "prod": - cfg.ServerBaseUrl = "https://midas.sec.usace.army.mil/api" + cfg.ServerBaseURL = "https://midas.sec.usace.army.mil/api" default: } diff --git a/api/internal/config/config.go b/api/internal/config/config.go index 7ad2dd05..a3c4d21a 100644 --- a/api/internal/config/config.go +++ b/api/internal/config/config.go @@ -1,3 +1,4 @@ +// Package config provides functionality to parse environment variables into configuration structs with a specified prefix. package config import ( diff --git a/api/internal/config/dcsloader.go b/api/internal/config/dcsloader.go index bd3f1958..26ddd080 100644 --- a/api/internal/config/dcsloader.go +++ b/api/internal/config/dcsloader.go @@ -4,7 +4,7 @@ package config // Note awsSQSQueueURL private variable. Public method is AWSSQSQueueURL() type DcsLoaderConfig struct { LoggerConfig - ApiHost string `env:"API_HOST"` + APIHost string `env:"API_HOST"` APIKey string `env:"API_KEY"` MaxConcurrentHandlers int `env:"MAX_CONCURRENT_HANDLERS" envDefault:"10"` IncomingDataBucketURI string `env:"INCOMING_DATA_BUCKET_URI"` diff --git a/api/internal/config/server.go b/api/internal/config/server.go index 83ce7a25..42a46ec6 100644 --- a/api/internal/config/server.go +++ b/api/internal/config/server.go @@ -15,7 +15,7 @@ type ServerConfig struct { ReportDownloadJobMocked bool `env:"REPORT_DOWNLOAD_JOB_MOCKED"` RequestLoggerEnabled bool `env:"REQUEST_LOGGER_ENABLED"` RoutePrefix string `env:"ROUTE_PREFIX"` - ServerBaseUrl string `env:"SERVER_BASE_URL"` + ServerBaseURL string `env:"SERVER_BASE_URL"` StackSizeKB int `env:"STACK_SIZE_KB" envDefault:"1"` AvailableTimezones []string } diff --git a/api/internal/config/telemetry.go b/api/internal/config/telemetry.go index dcaf9111..c7ddd7bf 100644 --- a/api/internal/config/telemetry.go +++ b/api/internal/config/telemetry.go @@ -3,7 +3,7 @@ package config type TelemetryConfig struct { LoggerConfig ServerConfig - ApiHost string `env:"API_HOST"` + APIHost string `env:"API_HOST"` } func NewTelemetryConfig() *TelemetryConfig { diff --git a/api/internal/config/thinglogix.go b/api/internal/config/thinglogix.go index a71babe0..31cdd5e9 100644 --- a/api/internal/config/thinglogix.go +++ b/api/internal/config/thinglogix.go @@ -3,7 +3,7 @@ package config type ThinglogixConfig struct { ThinglogixCognitoPool string `env:"THINGLOGIX_COGNITO_POOL"` ThinglogixProviderName string `env:"THINGLOGIX_PROVIDER_NAME"` - ThinglogixApiGatewayEndpoint string `env:"THINGLOGIX_API_GATEWAY_ENDPOINT"` + ThinglogixAPIGatewayEndpoint string `env:"THINGLOGIX_API_GATEWAY_ENDPOINT"` ThinglogixUser string `env:"THINGLOGIX_USER"` ThinglogixPassword string `env:"THINGLOGIX_PASSWORD"` ThinglogixAccountID string `env:"THINGLOGIX_ACCOUNT_ID"` diff --git a/api/internal/ctxkey/ctxkey.go b/api/internal/ctxkey/ctxkey.go index b7fc620a..dfa493f4 100644 --- a/api/internal/ctxkey/ctxkey.go +++ b/api/internal/ctxkey/ctxkey.go @@ -1,3 +1,4 @@ +// Package ctxkey defines context keys used throughout the application. package ctxkey type ContextKey string diff --git a/api/internal/db/overrides.go b/api/internal/db/overrides.go index 56c1ef66..79a71e7b 100644 --- a/api/internal/db/overrides.go +++ b/api/internal/db/overrides.go @@ -1,7 +1,8 @@ -package db - -// database overrides for scanning json into nested structs +// Package db contains type-safe sql query bindings generated by sqlc +// +// This file contains database overrides for scanning json into nested structs // see sqlc.generate.yaml overrides +package db // NOTE: use internal FloatNanInf type instead of float64 to // avoid errors with json.Marshal/Unmarshal with NaN and Inf values diff --git a/api/internal/dto/dto.go b/api/internal/dto/dto.go new file mode 100644 index 00000000..5a208e8e --- /dev/null +++ b/api/internal/dto/dto.go @@ -0,0 +1,2 @@ +// Package dto contains data transfer objects used to bind to request bodies. +package dto diff --git a/api/internal/dto/worker_alert_schedule.go b/api/internal/dto/worker_alert_schedule.go index 120037b7..d3f59906 100644 --- a/api/internal/dto/worker_alert_schedule.go +++ b/api/internal/dto/worker_alert_schedule.go @@ -14,6 +14,8 @@ type WorkerAlertCheckScheduleV1Args struct{} func (WorkerAlertCheckScheduleV1Args) Kind() string { return "AlertCheckScheduleV1" } +// WorkerAlertCheckScheduleV2Args defines the arguments for the AlertCheckScheduleV2 worker. +// // NotificationType and AlertConfigID are used as unique keys for the "reminder" NotificationType // to ensure duplicate reminders are not sent for the same AlertConfigID. type WorkerAlertCheckScheduleV2Args struct { diff --git a/api/internal/email/ses/ses.go b/api/internal/email/ses/ses.go index 872b83ef..766e84d5 100644 --- a/api/internal/email/ses/ses.go +++ b/api/internal/email/ses/ses.go @@ -1,3 +1,4 @@ +// Package ses provides an email client that sends emails using AWS Simple Email Service (SES). package ses import ( diff --git a/api/internal/email/smtp/smtp.go b/api/internal/email/smtp/smtp.go index 6b1d3201..6b1eb578 100644 --- a/api/internal/email/smtp/smtp.go +++ b/api/internal/email/smtp/smtp.go @@ -1,3 +1,4 @@ +// Package smtp implements an email client that sends emails using the SMTP protocol. package smtp import ( diff --git a/api/internal/handler/alert.go b/api/internal/handler/alert.go index c1e944c8..26dd2b43 100644 --- a/api/internal/handler/alert.go +++ b/api/internal/handler/alert.go @@ -18,7 +18,7 @@ type AlertIDParam struct { AlertID UUID `path:"alert_id"` } -func (h *ApiHandler) RegisterAlert(api huma.API) { +func (h *APIHandler) RegisterAlert(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "alert-list-for-instrument", diff --git a/api/internal/handler/alert_config.go b/api/internal/handler/alert_config.go index b2a515c6..8cf16184 100644 --- a/api/internal/handler/alert_config.go +++ b/api/internal/handler/alert_config.go @@ -31,7 +31,7 @@ type AlertTypeParam struct { AlertType string `path:"alert_type" example:"thresholds" oneOf:"thresholds,changes,"` } -func (h *ApiHandler) RegisterAlertConfig(api huma.API) { +func (h *APIHandler) RegisterAlertConfig(api huma.API) { registry := api.OpenAPI().Components.Schemas // TODO: for now it's fine to use the DTO types, would prefer composite types over // json if available: https://github.com/sqlc-dev/sqlc/issues/2760 diff --git a/api/internal/handler/alert_subscription.go b/api/internal/handler/alert_subscription.go index 78c0d6ad..7ed78da9 100644 --- a/api/internal/handler/alert_subscription.go +++ b/api/internal/handler/alert_subscription.go @@ -18,7 +18,7 @@ type AlertSubscriptionIDParam struct { AlertSubscriptionID UUID `path:"alert_subscription_id" example:"a7540f69-c41e-43b3-b655-6e44097edb7e"` } -func (h *ApiHandler) RegisterAlertSubscription(api huma.API) { +func (h *APIHandler) RegisterAlertSubscription(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Private, Security: privateSecurity, diff --git a/api/internal/handler/alert_test.go b/api/internal/handler/alert_test.go index 3a0a6b1c..6910c5c5 100644 --- a/api/internal/handler/alert_test.go +++ b/api/internal/handler/alert_test.go @@ -130,8 +130,6 @@ const alertConfigSchemaTemplate = `{ var alertConfigSchema = fmt.Sprintf(alertConfigSchemaTemplate, alertConfigTimeseriesSchema, alertConfigInstrumentSchema, alertConfigEmailSchema, alertConfigScheduleOptsSchema) -var alertConfigObjectLoader = gojsonschema.NewStringLoader(alertConfigSchema) - var alertConfigArrayLoader = gojsonschema.NewStringLoader(fmt.Sprintf(`{ "type": "array", "items": %s diff --git a/api/internal/handler/api.go b/api/internal/handler/api.go index db501f66..5b927b52 100644 --- a/api/internal/handler/api.go +++ b/api/internal/handler/api.go @@ -28,13 +28,11 @@ import ( "github.com/riverqueue/river" ) -// TODO: make this a build tag -const API_VERSION = "4.1.3" -const API_VERSION_PREFIX = "/v4" - const ( - bearerAuth = "bearer" - keyAuth = "apiKey" + APIVersion = "4.1.3" + APIVersionPrefix = "/v4" + bearerAuth = "bearer" + keyAuth = "apiKey" ) const ( @@ -49,18 +47,17 @@ type Router struct { *echo.Echo } -type ApiHandler struct { +type APIHandler struct { DBService *service.DBService - CloudServices *cloud.ApiServices + CloudServices *cloud.APIServices HTTPClient *http.Client - Config *config.ApiConfig + Config *config.APIConfig Logger *logger.Logger httperr *httperr.Service - router *Router apiMiddlewares } -func NewApi(ctx context.Context, cfg *config.ApiConfig, l *logger.Logger) (*ApiHandler, error) { +func NewAPI(ctx context.Context, cfg *config.APIConfig, l *logger.Logger) (*APIHandler, error) { dbpool, err := service.NewDBPool(ctx, cfg.DBConfig) if err != nil { return nil, err @@ -80,18 +77,18 @@ func NewApi(ctx context.Context, cfg *config.ApiConfig, l *logger.Logger) (*ApiH dbService := service.NewDBServiceFromPool(dbpool, l, &cfg.FeatureFlags) dbService.PGQueue = pgq - cloudServices, err := cloud.NewApiServices(ctx, cfg) + cloudServices, err := cloud.NewAPIServices(ctx, cfg) if err != nil { return nil, err } l.Info(ctx, "Cloud services initialized") - httpClient := NewHttpClient() + httpClient := NewHTTPClient() es := httperr.NewService( httperr.WithLogger(l.Slogger()), httperr.WithDebugResponseBody(cfg.Debug), - httperr.WithUrlRedactor(func(u *url.URL) { + httperr.WithURLRedactor(func(u *url.URL) { util.RedactQueryParams(u, "key") }), // this isn't ideal, but works for making logs more readable for some noisy endpoints. @@ -99,7 +96,7 @@ func NewApi(ctx context.Context, cfg *config.ApiConfig, l *logger.Logger) (*ApiH // is the one we want to suppress. httperr.WithLogSkipper(func(remoteAddr, method string, u *url.URL, status int) bool { switch { - case u.Path == API_VERSION_PREFIX+"/timeseries_measurements" && + case u.Path == APIVersionPrefix+"/timeseries_measurements" && method == http.MethodPost && status == http.StatusBadRequest: return true @@ -109,7 +106,7 @@ func NewApi(ctx context.Context, cfg *config.ApiConfig, l *logger.Logger) (*ApiH }), ) - return &ApiHandler{ + return &APIHandler{ DBService: dbService, CloudServices: cloudServices, HTTPClient: httpClient, @@ -119,7 +116,7 @@ func NewApi(ctx context.Context, cfg *config.ApiConfig, l *logger.Logger) (*ApiH }, nil } -func (h *ApiHandler) Shutdown(ctx context.Context) error { +func (h *APIHandler) Shutdown(ctx context.Context) error { h.DBService.Close() if err := h.CloudServices.Shutdown(ctx); err != nil { return err @@ -163,7 +160,7 @@ var appAdminSecurity = security{{ keyAuth: {appAdminScope}, }} -func NewApiRouter(ctx context.Context, h *ApiHandler) *Router { +func NewAPIRouter(ctx context.Context, h *APIHandler) *Router { if err := validateStruct(h); err != nil { panic(err) } @@ -172,9 +169,9 @@ func NewApiRouter(ctx context.Context, h *ApiHandler) *Router { huma.NewErrorWithContext = h.httperr.NewHumaErrorWithContextHandler() e.HTTPErrorHandler = h.httperr.NewEchoHTTPErrorHandler() - g := e.Group(h.Config.RoutePrefix + API_VERSION_PREFIX) + g := e.Group(h.Config.RoutePrefix + APIVersionPrefix) - mw := middleware.NewApiMiddleware(&h.Config.ServerConfig, h.DBService, h.httperr, h.Logger) + mw := middleware.NewAPIMiddleware(&h.Config.ServerConfig, h.DBService, h.httperr, h.Logger) g.Use(mw.CORS, mw.GZIP, mw.RequestID, mw.NewRequestLoggerMiddleware(h.Logger)) @@ -202,8 +199,8 @@ func NewApiRouter(ctx context.Context, h *ApiHandler) *Router { h.Cac = huma.Middlewares{mw.JWT, mw.AttachClaims, mw.RequireClaims} h.InternalApp = huma.Middlewares{mw.AppKeyAuth} - humaCfg := huma.DefaultConfig("MIDAS API", API_VERSION) - humaCfg.Servers = append(humaCfg.Servers, &huma.Server{URL: h.Config.ServerBaseUrl + API_VERSION_PREFIX}) + humaCfg := huma.DefaultConfig("MIDAS API", APIVersion) + humaCfg.Servers = append(humaCfg.Servers, &huma.Server{URL: h.Config.ServerBaseURL + APIVersionPrefix}) bearerAuthScheme := &huma.SecurityScheme{ Type: "http", @@ -257,7 +254,7 @@ func NewApiRouter(ctx context.Context, h *ApiHandler) *Router { g.GET("/docs", func(c echo.Context) error { c.Response().Header().Set("Content-Type", "text/html") - body := fmt.Sprintf(docsHtmlTmpl, h.Config.ServerBaseUrl+API_VERSION_PREFIX, authOptions) + body := fmt.Sprintf(docsHTMLTmpl, h.Config.ServerBaseURL+APIVersionPrefix, authOptions) c.Response().Write([]byte(body)) return nil }) @@ -310,7 +307,7 @@ func NewApiRouter(ctx context.Context, h *ApiHandler) *Router { return &Router{e} } -func (h *ApiHandler) startAlertEventBatcher(ctx context.Context) <-chan error { +func (h *APIHandler) startAlertEventBatcher(ctx context.Context) <-chan error { decode := func(b []byte) (dto.WorkerAlertEventArgs, error) { var ev dto.WorkerAlertEventArgs return ev, json.Unmarshal(b, &ev) @@ -350,14 +347,14 @@ func (h *ApiHandler) startAlertEventBatcher(ctx context.Context) <-chan error { }) } - var err error + var batchErr error h.DBService.InsertRiverJobCreateOrUpdateMeasurementEvent(ctx, params).Exec(func(i int, err error) { if err != nil { - err = errors.Join(err, fmt.Errorf("InsertRiverJobCreateOrUpdateMeasurementEvent query failed: %w; params: %v", err, params[i])) + batchErr = errors.Join(batchErr, fmt.Errorf("InsertRiverJobCreateOrUpdateMeasurementEvent query failed: %w; params: %v", err, params[i])) } }) - return err + return batchErr } b := pgqueue.NewBatcher( @@ -373,12 +370,12 @@ func (h *ApiHandler) startAlertEventBatcher(ctx context.Context) <-chan error { return b.Run(ctx) } -func (h *ApiHandler) Run(ctx context.Context) error { +func (h *APIHandler) Run(ctx context.Context) error { h.Logger.Info(ctx, "Starting MIDAS API service...") batchErrCh := h.startAlertEventBatcher(ctx) - router := NewApiRouter(ctx, h) + router := NewAPIRouter(ctx, h) srv := &http.Server{ Addr: ":80", Handler: router, @@ -416,7 +413,7 @@ func (h *ApiHandler) Run(ctx context.Context) error { } } -var docsHtmlTmpl = ` +var docsHTMLTmpl = ` MIDAS API Reference diff --git a/api/internal/handler/arcgis.go b/api/internal/handler/arcgis.go index c758db1f..fcc1c07a 100644 --- a/api/internal/handler/arcgis.go +++ b/api/internal/handler/arcgis.go @@ -83,7 +83,7 @@ type ResourceInfo struct { CacheInfo CacheInfo `json:"cacheInfo"` } -func (h *ApiHandler) RegisterArcGIS(api huma.API) { +func (h *APIHandler) RegisterArcGIS(api huma.API) { huma.Register(api, huma.Operation{ Hidden: true, Middlewares: h.Public, @@ -103,7 +103,7 @@ func (h *ApiHandler) RegisterArcGIS(api huma.API) { Capabilities: "TilesOnly,Tilemap", Type: "indexedVector", TileMap: "tilemap", - Tiles: []string{fmt.Sprintf("%s/instruments/mvt/{z}/{x}/{y}.pbf", h.Config.ServerBaseUrl)}, + Tiles: []string{fmt.Sprintf("%s/instruments/mvt/{z}/{x}/{y}.pbf", h.Config.ServerBaseURL)}, ExportTilesAllowed: true, InitialExtent: InitialExtent{ Xmin: -180, diff --git a/api/internal/handler/autocomplete.go b/api/internal/handler/autocomplete.go index c5564036..eefb5b81 100644 --- a/api/internal/handler/autocomplete.go +++ b/api/internal/handler/autocomplete.go @@ -12,7 +12,7 @@ import ( var emailAutocompleteTags = []string{"Autocomplete Results"} -func (h *ApiHandler) RegisterAutocomplete(api huma.API) { +func (h *APIHandler) RegisterAutocomplete(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "email-autocomplete-list-for-search", diff --git a/api/internal/handler/aware.go b/api/internal/handler/aware.go index 8b0b8512..4c939a11 100644 --- a/api/internal/handler/aware.go +++ b/api/internal/handler/aware.go @@ -12,7 +12,7 @@ import ( var awareTags = []string{"Aware Parameters"} -func (h *ApiHandler) RegisterAware(api huma.API) { +func (h *APIHandler) RegisterAware(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "aware-parameter-list", diff --git a/api/internal/handler/collection_groups.go b/api/internal/handler/collection_groups.go index 4b2ee06d..5c109a18 100644 --- a/api/internal/handler/collection_groups.go +++ b/api/internal/handler/collection_groups.go @@ -18,7 +18,7 @@ type CollectionGroupIDParam struct { CollectionGroupID UUID `path:"collection_group_id" example:"30b32cb1-0936-42c4-95d1-63a7832a57db"` } -func (h *ApiHandler) RegisterCollectionGroup(api huma.API) { +func (h *APIHandler) RegisterCollectionGroup(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "collection-group-list-for-project", diff --git a/api/internal/handler/datalogger.go b/api/internal/handler/datalogger.go index 29b1d10a..be614d59 100644 --- a/api/internal/handler/datalogger.go +++ b/api/internal/handler/datalogger.go @@ -31,7 +31,7 @@ type RowIDParam struct { RowID UUID `path:"row_id" example:"2f1f7c3d-8b6f-4b11-917e-8f049eb6c62b"` } -func (h *ApiHandler) RegisterDatalogger(api huma.API) { +func (h *APIHandler) RegisterDatalogger(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "datalogger-list", diff --git a/api/internal/handler/datalogger_proxy.go b/api/internal/handler/datalogger_proxy.go index 4a42e9c3..965aa8d8 100644 --- a/api/internal/handler/datalogger_proxy.go +++ b/api/internal/handler/datalogger_proxy.go @@ -31,7 +31,7 @@ func (h *TelemetryHandler) RegisterDataloggerProxy(api huma.API) { }) (*ResponseWithStatus[any], error) { ctx := context.Background() // continue request in case of proxy server shutdown or slow cutover payloadBytes, err := json.Marshal(DataloggerTelemetryDTO{ - DataloggerApiKey: input.XApiKey, + DataloggerAPIKey: input.XApiKey, Payload: input.RawBody, DataloggerInfo: DataloggerInfo{ Model: input.DataloggerModel, @@ -42,12 +42,12 @@ func (h *TelemetryHandler) RegisterDataloggerProxy(api huma.API) { return nil, httperr.BadRequest(err) } - base, err := url.Parse(h.Config.ApiHost) + base, err := url.Parse(h.Config.APIHost) if err != nil { return nil, httperr.InternalServerError(fmt.Errorf("invalid api host: %w", err)) } - base.Path = API_VERSION_PREFIX + "/telemetry/dataloggers" + base.Path = APIVersionPrefix + "/telemetry/dataloggers" q := base.Query() q.Set("key", h.Config.ApplicationKey) base.RawQuery = q.Encode() @@ -123,7 +123,7 @@ func (h *TelemetryHandler) RegisterDataloggerProxy(api huma.API) { Description: "checks the health of the datalogger proxy server", Tags: healthcheckTags, }, func(ctx context.Context, input *struct{}) (*ResponseWithContentType[any], error) { - res, err := h.Client.Get(h.Config.ApiHost + API_VERSION_PREFIX + "/telemetry/health") + res, err := h.Client.Get(h.Config.APIHost + APIVersionPrefix + "/telemetry/health") if err != nil { return nil, httperr.InternalServerError(fmt.Errorf("request error %w", err)) } diff --git a/api/internal/handler/datalogger_telemetry.go b/api/internal/handler/datalogger_telemetry.go index 74813b64..151a501a 100644 --- a/api/internal/handler/datalogger_telemetry.go +++ b/api/internal/handler/datalogger_telemetry.go @@ -37,12 +37,12 @@ type DataloggerInfo struct { } type DataloggerTelemetryDTO struct { - DataloggerApiKey string `json:"datalogger_api_key"` + DataloggerAPIKey string `json:"datalogger_api_key"` Payload []byte `json:"payload"` DataloggerInfo } -func (h *ApiHandler) RegisterDataloggerTelemetry(api huma.API) { +func (h *APIHandler) RegisterDataloggerTelemetry(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.InternalApp, Hidden: true, @@ -63,7 +63,7 @@ func (h *ApiHandler) RegisterDataloggerTelemetry(api huma.API) { if err != nil { return nil, httperr.Unauthorized(errors.New("error querying datalogger hash: " + d.Model + " " + d.Sn)) } - match, err := password.ComparePasswordAndHash(d.DataloggerApiKey, hash) + match, err := password.ComparePasswordAndHash(d.DataloggerAPIKey, hash) if err != nil || !match { return nil, httperr.Unauthorized(errors.New("error validating datalogger hash: " + d.Model + " " + d.Sn)) } diff --git a/api/internal/handler/dcsloader.go b/api/internal/handler/dcsloader.go index 79009dc5..bc270be9 100644 --- a/api/internal/handler/dcsloader.go +++ b/api/internal/handler/dcsloader.go @@ -30,7 +30,7 @@ func NewDcsLoader(ctx context.Context, cfg *config.DcsLoaderConfig, l *logger.Lo return &DcsLoaderHandler{ Config: cfg, - DcsLoaderService: service.NewDcsLoaderService(NewHttpClient(), cfg, l), + DcsLoaderService: service.NewDcsLoaderService(NewHTTPClient(), cfg, l), CloudServices: cloudServices, Logger: l, }, nil @@ -40,7 +40,7 @@ func (h *DcsLoaderHandler) Shutdown(ctx context.Context) error { return h.CloudServices.Shutdown(ctx) } -// DcsLoaderHandler.handleCreateObjectEvents processes messages from the SNS on CreateObject events from DcsLoaderServices.IncomingDataBucket +// HandleCreateObjectEvent processes messages from the SNS on CreateObject events from DcsLoaderServices.IncomingDataBucket func (h *DcsLoaderHandler) HandleCreateObjectEvent(ctx context.Context, key string, r io.Reader) error { switch { case strings.HasPrefix(key, h.Config.OpenDcsKeyPrefix): @@ -52,7 +52,7 @@ func (h *DcsLoaderHandler) HandleCreateObjectEvent(ctx context.Context, key stri return fmt.Errorf("SlarchiveHandler %w", err) } default: - return fmt.Errorf("No matching prefix for key %s", key) + return fmt.Errorf("no matching prefix for key %s", key) } return nil } @@ -122,7 +122,7 @@ func (h *DcsLoaderHandler) OpenDcsHandler(ctx context.Context, r io.Reader) erro return httperr.BadRequest(err) } startPostTime := time.Now() - if err := h.DcsLoaderService.PostMeasurementCollectionToApi(ctx, mcs); err != nil { + if err := h.DcsLoaderService.PostMeasurementCollectionToAPI(ctx, mcs); err != nil { return httperr.InternalServerError(err) } h.Logger.Info(ctx, "success", @@ -139,7 +139,7 @@ func (h *DcsLoaderHandler) SlarchiveHandler(ctx context.Context, r io.Reader) er return httperr.BadRequest(fmt.Errorf("ParseMseedMeasurementCollection %w", err)) } startPostTime := time.Now() - if err := h.DcsLoaderService.PostSeisMeasurementCollectionToApi(ctx, mcs); err != nil { + if err := h.DcsLoaderService.PostSeisMeasurementCollectionToAPI(ctx, mcs); err != nil { return httperr.InternalServerError(fmt.Errorf("PostMeasurementCollectionToApi %w", err)) } h.Logger.Info(ctx, "success", diff --git a/api/internal/handler/dcsloader_test.go b/api/internal/handler/dcsloader_test.go index 46444145..b16bddef 100644 --- a/api/internal/handler/dcsloader_test.go +++ b/api/internal/handler/dcsloader_test.go @@ -1,10 +1,6 @@ package handler_test -import ( - "github.com/USACE/instrumentation-api/api/v4/internal/handler" -) - -var h *handler.DcsLoaderHandler +// var h *handler.DcsLoaderHandler // func TestMain(m *testing.M) { // ctx := context.Background() @@ -47,8 +43,8 @@ var h *handler.DcsLoaderHandler // assert.NoError(t, err) // } -const mockCSVData = `869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T15:30:00Z,27.6800 -869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T15:00:00Z,27.6200 -869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T14:30:00Z,27.5500 -869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T14:00:00Z,27.4400 -` +// const mockCSVData = `869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T15:30:00Z,27.6800 +// 869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T15:00:00Z,27.6200 +// 869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T14:30:00Z,27.5500 +// 869465fc-dc1e-445e-81f4-9979b5fadda9,2021-03-01T14:00:00Z,27.4400 +// ` diff --git a/api/internal/handler/district_rollup.go b/api/internal/handler/district_rollup.go index e6e40c45..8371fa92 100644 --- a/api/internal/handler/district_rollup.go +++ b/api/internal/handler/district_rollup.go @@ -20,7 +20,7 @@ type TimestampMonthQueryParams struct { ToTimestampMonth time.Time `query:"to_timestamp_month" required:"false"` } -func (h *ApiHandler) RegisterDistrictRollup(api huma.API) { +func (h *APIHandler) RegisterDistrictRollup(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "district-rollup-list-evaluation-for-project-alert-config", diff --git a/api/internal/handler/domain.go b/api/internal/handler/domain.go index e4c7f585..f1658aa2 100644 --- a/api/internal/handler/domain.go +++ b/api/internal/handler/domain.go @@ -13,7 +13,7 @@ import ( var domainTags []string = []string{"Domains"} -func (h *ApiHandler) RegisterDomain(api huma.API) { +func (h *APIHandler) RegisterDomain(api huma.API) { huma.Register(api, huma.Operation{ Deprecated: true, Middlewares: h.Public, diff --git a/api/internal/handler/equivalency_table.go b/api/internal/handler/equivalency_table.go index 66407e0a..7fb14b42 100644 --- a/api/internal/handler/equivalency_table.go +++ b/api/internal/handler/equivalency_table.go @@ -14,7 +14,7 @@ import ( var dataloggerTableTags []string = []string{"Datalogger Table Mappings"} -func (h *ApiHandler) RegisterDataloggerTableMapping(api huma.API) { +func (h *APIHandler) RegisterDataloggerTableMapping(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "datalogger-table-mapping-get", diff --git a/api/internal/handler/evaluation.go b/api/internal/handler/evaluation.go index 24144593..69c0f1d8 100644 --- a/api/internal/handler/evaluation.go +++ b/api/internal/handler/evaluation.go @@ -19,7 +19,7 @@ type EvaluationIDParam struct { EvaluationID UUID `path:"evaluation_id" example:"f7169aca-aa5f-4a0b-9fcc-609bb5c2bd7b"` } -func (h *ApiHandler) RegisterEvaluation(api huma.API) { +func (h *APIHandler) RegisterEvaluation(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "evaluation-list-for-project", diff --git a/api/internal/handler/formula.go b/api/internal/handler/formula.go index 7dcd48ad..b57413dd 100644 --- a/api/internal/handler/formula.go +++ b/api/internal/handler/formula.go @@ -16,7 +16,7 @@ type FormulaIDParam struct { FormulaID UUID `path:"formula_id" example:"5b6f4f37-7755-4cf9-bd02-94f1e9bc5984"` } -func (h *ApiHandler) RegisterFormulas(api huma.API) { +func (h *APIHandler) RegisterFormulas(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "formula-list", diff --git a/api/internal/handler/handler.go b/api/internal/handler/handler.go index 303a3a72..6cf1b422 100644 --- a/api/internal/handler/handler.go +++ b/api/internal/handler/handler.go @@ -1,3 +1,4 @@ +// Package handler contains common types and utilities for HTTP handlers. package handler import ( @@ -15,7 +16,7 @@ import ( const maxBodyBytes = 100 * 1024 * 1024 -func NewHttpClient() *http.Client { +func NewHTTPClient() *http.Client { client := http.DefaultClient client.Timeout = time.Minute * 5 client.CheckRedirect = func(*http.Request, []*http.Request) error { return nil } diff --git a/api/internal/handler/handler_test.go b/api/internal/handler/handler_test.go index fde1dde6..731c9478 100644 --- a/api/internal/handler/handler_test.go +++ b/api/internal/handler/handler_test.go @@ -57,9 +57,9 @@ func TestMain(m *testing.M) { var exitCode int func() { ctx := context.Background() - cfg := config.NewApiConfig() + cfg := config.NewAPIConfig() l := logger.NewLogger(&cfg.LoggerConfig) - h, err := handler.NewApi(ctx, cfg, l) + h, err := handler.NewAPI(ctx, cfg, l) if err != nil { l.Error(ctx, "Critical error; exiting", "error", err) os.Exit(1) @@ -70,7 +70,7 @@ func TestMain(m *testing.M) { os.Exit(1) } }() - router = handler.NewApiRouter(ctx, h) + router = handler.NewAPIRouter(ctx, h) exitCode = m.Run() }() os.Exit(exitCode) diff --git a/api/internal/handler/heartbeat.go b/api/internal/handler/heartbeat.go index c552f8cf..9cc1e164 100644 --- a/api/internal/handler/heartbeat.go +++ b/api/internal/handler/heartbeat.go @@ -12,7 +12,7 @@ import ( var healthcheckTags []string = []string{"Healthcheck"} -func (h *ApiHandler) RegisterHealthcheck(api huma.API) { +func (h *APIHandler) RegisterHealthcheck(api huma.API) { huma.Register(api, huma.Operation{ Hidden: true, Middlewares: h.Public, diff --git a/api/internal/handler/home.go b/api/internal/handler/home.go index 2e405f75..b17019ec 100644 --- a/api/internal/handler/home.go +++ b/api/internal/handler/home.go @@ -11,7 +11,7 @@ import ( var homeTags = []string{"Home"} -func (h *ApiHandler) RegisterHome(api huma.API) { +func (h *APIHandler) RegisterHome(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "home-get", diff --git a/api/internal/handler/instrument.go b/api/internal/handler/instrument.go index 901403b7..5535fce6 100644 --- a/api/internal/handler/instrument.go +++ b/api/internal/handler/instrument.go @@ -85,7 +85,7 @@ type InstrumentListQueryParams struct { BboxSrid int32 `query:"bbox_srid"` } -func (h *ApiHandler) RegisterInstrument(api huma.API) { +func (h *APIHandler) RegisterInstrument(api huma.API) { registry := api.OpenAPI().Components.Schemas vInstrumentSchema := huma.SchemaFromType(registry, vInstrumentType) diff --git a/api/internal/handler/instrument_assign.go b/api/internal/handler/instrument_assign.go index 60771376..780e0b22 100644 --- a/api/internal/handler/instrument_assign.go +++ b/api/internal/handler/instrument_assign.go @@ -20,7 +20,7 @@ type DryRunQueryParam struct { DryRun bool `query:"dry_run" default:"false"` } -func (h *ApiHandler) RegisterInstrumentAssign(api huma.API) { +func (h *APIHandler) RegisterInstrumentAssign(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.ProjectAdmin, Security: projectAdminSecurity, diff --git a/api/internal/handler/instrument_group.go b/api/internal/handler/instrument_group.go index 90e04a45..ed416e6f 100644 --- a/api/internal/handler/instrument_group.go +++ b/api/internal/handler/instrument_group.go @@ -18,7 +18,7 @@ type InstrumentGroupIDParam struct { InstrumentGroupID UUID `path:"instrument_group_id" example:"d0916e8a-39a6-4f2f-bd31-879881f8b40c"` } -func (h *ApiHandler) RegisterInstrumentGroup(api huma.API) { +func (h *APIHandler) RegisterInstrumentGroup(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "instrument-group-list", diff --git a/api/internal/handler/instrument_incl.go b/api/internal/handler/instrument_incl.go index af3c9a7a..2c0514e5 100644 --- a/api/internal/handler/instrument_incl.go +++ b/api/internal/handler/instrument_incl.go @@ -21,7 +21,7 @@ type TimeWindowInclQueryParams struct { EndsAt time.Time `query:"ends_at" description:"defaults to current timestamp"` } -func (h *ApiHandler) RegisterInstrumentIncl(api huma.API) { +func (h *APIHandler) RegisterInstrumentIncl(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "incl-segment-list-for-instrument", diff --git a/api/internal/handler/instrument_ipi.go b/api/internal/handler/instrument_ipi.go index c90a6897..e3f31c35 100644 --- a/api/internal/handler/instrument_ipi.go +++ b/api/internal/handler/instrument_ipi.go @@ -10,7 +10,7 @@ import ( "github.com/danielgtaylor/huma/v2" ) -func (h *ApiHandler) RegisterInstrumentIpi(api huma.API) { +func (h *APIHandler) RegisterInstrumentIpi(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "ipi-segment-list-for-instrument", diff --git a/api/internal/handler/instrument_note.go b/api/internal/handler/instrument_note.go index 6fdba22b..91afc3fc 100644 --- a/api/internal/handler/instrument_note.go +++ b/api/internal/handler/instrument_note.go @@ -18,7 +18,7 @@ type NoteIDParam struct { NoteID UUID `path:"note_id" example:"90a3f8de-de65-48a7-8286-024c13162958"` } -func (h *ApiHandler) RegisterInstrumentNote(api huma.API) { +func (h *APIHandler) RegisterInstrumentNote(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "instrument-note-list-for-instrument", diff --git a/api/internal/handler/instrument_saa.go b/api/internal/handler/instrument_saa.go index a1b1fc6b..fcf1bc0c 100644 --- a/api/internal/handler/instrument_saa.go +++ b/api/internal/handler/instrument_saa.go @@ -10,7 +10,7 @@ import ( "github.com/danielgtaylor/huma/v2" ) -func (h *ApiHandler) RegisterInstrumentSaa(api huma.API) { +func (h *APIHandler) RegisterInstrumentSaa(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "saa-segment-list-for-instrument", diff --git a/api/internal/handler/instrument_seis.go b/api/internal/handler/instrument_seis.go index 68b5cb99..c36f0115 100644 --- a/api/internal/handler/instrument_seis.go +++ b/api/internal/handler/instrument_seis.go @@ -24,7 +24,7 @@ type IrisStationQueryParams struct { NoData int `query:"nodata" required:"false"` } -func (h *ApiHandler) RegisterInstrumentSeis(api huma.API) { +func (h *APIHandler) RegisterInstrumentSeis(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "timeseries-seedlink-mapping-list-for-instrument", diff --git a/api/internal/handler/instrument_status.go b/api/internal/handler/instrument_status.go index e46d1983..db0003b6 100644 --- a/api/internal/handler/instrument_status.go +++ b/api/internal/handler/instrument_status.go @@ -16,7 +16,7 @@ type StatusIDParam struct { StatusID UUID `path:"status_id" example:"e26ba2ef-9b52-4c71-97df-9e4b6cf4174d"` } -func (h *ApiHandler) RegisterInstrumentStatus(api huma.API) { +func (h *APIHandler) RegisterInstrumentStatus(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "instrument-status-list-for-instrument", diff --git a/api/internal/handler/measurement.go b/api/internal/handler/measurement.go index 950727d2..a1de01ca 100644 --- a/api/internal/handler/measurement.go +++ b/api/internal/handler/measurement.go @@ -24,7 +24,7 @@ var ( timeseriesNotesCountForRangeType = reflect.TypeFor[service.TimeseriesNoteCountsByTimeseriesRange]() ) -func (h *ApiHandler) RegisterMeasurement(api huma.API) { +func (h *APIHandler) RegisterMeasurement(api huma.API) { registry := api.OpenAPI().Components.Schemas huma.Register(api, huma.Operation{ diff --git a/api/internal/handler/media.go b/api/internal/handler/media.go index fb2b6eae..be662c03 100644 --- a/api/internal/handler/media.go +++ b/api/internal/handler/media.go @@ -11,7 +11,7 @@ import ( var mediaTags = []string{"Media"} -func (h *ApiHandler) RegisterMedia(api huma.API) { +func (h *APIHandler) RegisterMedia(api huma.API) { mediaDownloadResponses := map[string]*huma.Response{ "200": {Description: "OK", Content: map[string]*huma.MediaType{ "image/jpeg": {Schema: &huma.Schema{Type: "string", Format: "binary"}}, diff --git a/api/internal/handler/plot_config.go b/api/internal/handler/plot_config.go index 84da75a1..b1a3ac17 100644 --- a/api/internal/handler/plot_config.go +++ b/api/internal/handler/plot_config.go @@ -22,7 +22,7 @@ type PlotConfigIDParam struct { PlotConfigID UUID `path:"plot_config_id" example:"f08a15fa-448c-4066-a81f-124d54712c62"` } -func (h *ApiHandler) RegisterPlotConfig(api huma.API) { +func (h *APIHandler) RegisterPlotConfig(api huma.API) { registry := api.OpenAPI().Components.Schemas schema := &huma.Schema{ AnyOf: []*huma.Schema{ diff --git a/api/internal/handler/plot_config_bullseye.go b/api/internal/handler/plot_config_bullseye.go index 48150dd3..757e2573 100644 --- a/api/internal/handler/plot_config_bullseye.go +++ b/api/internal/handler/plot_config_bullseye.go @@ -12,7 +12,7 @@ import ( "github.com/danielgtaylor/huma/v2" ) -func (h *ApiHandler) RegisterPlotConfigBullseye(api huma.API) { +func (h *APIHandler) RegisterPlotConfigBullseye(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.ProjectMember, Security: projectMemberSecurity, diff --git a/api/internal/handler/plot_config_contour.go b/api/internal/handler/plot_config_contour.go index 5cac4ced..7d2eb95a 100644 --- a/api/internal/handler/plot_config_contour.go +++ b/api/internal/handler/plot_config_contour.go @@ -13,7 +13,7 @@ import ( "github.com/danielgtaylor/huma/v2" ) -func (h *ApiHandler) RegisterPlotConfigContour(api huma.API) { +func (h *APIHandler) RegisterPlotConfigContour(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.ProjectMember, Security: projectMemberSecurity, diff --git a/api/internal/handler/plot_config_profile.go b/api/internal/handler/plot_config_profile.go index 893697ae..e5f032c8 100644 --- a/api/internal/handler/plot_config_profile.go +++ b/api/internal/handler/plot_config_profile.go @@ -12,7 +12,7 @@ import ( "github.com/danielgtaylor/huma/v2" ) -func (h *ApiHandler) RegisterPlotConfigProfile(api huma.API) { +func (h *APIHandler) RegisterPlotConfigProfile(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.ProjectMember, Security: projectMemberSecurity, diff --git a/api/internal/handler/plot_config_scatter_line.go b/api/internal/handler/plot_config_scatter_line.go index 0b1d03a5..ebe19832 100644 --- a/api/internal/handler/plot_config_scatter_line.go +++ b/api/internal/handler/plot_config_scatter_line.go @@ -12,7 +12,7 @@ import ( "github.com/danielgtaylor/huma/v2" ) -func (h *ApiHandler) RegisterPlotConfigScatterLine(api huma.API) { +func (h *APIHandler) RegisterPlotConfigScatterLine(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.ProjectMember, Security: projectMemberSecurity, diff --git a/api/internal/handler/profile.go b/api/internal/handler/profile.go index b8fe7619..0c9f8ac7 100644 --- a/api/internal/handler/profile.go +++ b/api/internal/handler/profile.go @@ -25,7 +25,7 @@ type TokenIDParam struct { TokenID string `path:"token_id"` } -func (h *ApiHandler) createProfile(ctx context.Context, claims dto.ProfileClaims) (db.ProfileCreateRow, error) { +func (h *APIHandler) createProfile(ctx context.Context, claims dto.ProfileClaims) (db.ProfileCreateRow, error) { var a db.ProfileCreateRow var err error if !claims.X509Presented { @@ -51,7 +51,7 @@ func (h *ApiHandler) createProfile(ctx context.Context, claims dto.ProfileClaims return a, nil } -func (h *ApiHandler) RegisterProfile(api huma.API) { +func (h *APIHandler) RegisterProfile(api huma.API) { registry := api.OpenAPI().Components.Schemas profileGetOrCreateResponses := map[string]*huma.Response{ diff --git a/api/internal/handler/project.go b/api/internal/handler/project.go index 08e8b612..d3664b93 100644 --- a/api/internal/handler/project.go +++ b/api/internal/handler/project.go @@ -25,7 +25,7 @@ type ProjectIDParam struct { ProjectID UUID `path:"project_id" example:"5b6f4f37-7755-4cf9-bd02-94f1e9bc5984"` } -func (h *ApiHandler) RegisterProject(api huma.API) { +func (h *APIHandler) RegisterProject(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "district-list", diff --git a/api/internal/handler/project_role.go b/api/internal/handler/project_role.go index d8c5244b..af4e2524 100644 --- a/api/internal/handler/project_role.go +++ b/api/internal/handler/project_role.go @@ -20,7 +20,7 @@ type RoleIDParam struct { RoleID UUID `path:"role_id" example:"37f14863-8f3b-44ca-8deb-4b74ce8a8a69"` } -func (h *ApiHandler) RegisterProjectRole(api huma.API) { +func (h *APIHandler) RegisterProjectRole(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Private, Security: privateSecurity, diff --git a/api/internal/handler/report_config.go b/api/internal/handler/report_config.go index c5166ad5..c710b873 100644 --- a/api/internal/handler/report_config.go +++ b/api/internal/handler/report_config.go @@ -29,7 +29,7 @@ type JobIDParam struct { JobID UUID `path:"job_id" example:"e90dbcc9-7bf4-4402-80ea-c0cdbbb91c6d"` } -func (h *ApiHandler) RegisterReportConfig(api huma.API) { +func (h *APIHandler) RegisterReportConfig(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "report-config-list", @@ -302,7 +302,7 @@ func (h *ApiHandler) RegisterReportConfig(api huma.API) { }) } -func (h *ApiHandler) runLambdaRIE(_ context.Context, body []byte) error { +func (h *APIHandler) runLambdaRIE(_ context.Context, body []byte) error { ctx := context.Background() type SQSRecord struct { Body json.RawMessage `json:"body"` diff --git a/api/internal/handler/submittal.go b/api/internal/handler/submittal.go index 1aafcc91..f7eb2489 100644 --- a/api/internal/handler/submittal.go +++ b/api/internal/handler/submittal.go @@ -15,7 +15,7 @@ type SubmittalIDParam struct { SubmittalID UUID `path:"submittal_id" example:"b8c1c297-d1d5-4cee-b949-72299b330617"` } -func (h *ApiHandler) RegisterSubmittal(api huma.API) { +func (h *APIHandler) RegisterSubmittal(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "submittal-list-for-project", diff --git a/api/internal/handler/survey123.go b/api/internal/handler/survey123.go index 87055da5..c16206ee 100644 --- a/api/internal/handler/survey123.go +++ b/api/internal/handler/survey123.go @@ -23,7 +23,7 @@ type Survey123IDParam struct { Survey123ID UUID `path:"survey123_id" example:"a2e19d85-4c64-4e99-b93a-4f4f56a718cf"` } -func (h *ApiHandler) RegisterSurvey123(api huma.API) { +func (h *APIHandler) RegisterSurvey123(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "survey123-list-for-project", diff --git a/api/internal/handler/survey123_proxy.go b/api/internal/handler/survey123_proxy.go index 0fe5e063..ae9b46b5 100644 --- a/api/internal/handler/survey123_proxy.go +++ b/api/internal/handler/survey123_proxy.go @@ -43,13 +43,13 @@ func (h *TelemetryHandler) RegisterSurvey123Proxy(api huma.API) { return nil, httperr.BadRequest(err) } - base, err := url.Parse(h.Config.ApiHost) + base, err := url.Parse(h.Config.APIHost) if err != nil { return nil, httperr.InternalServerError(fmt.Errorf("invalid api host: %w", err)) } - surveyID := input.Survey123IDParam.Survey123ID.UUID.String() - base.Path = fmt.Sprintf(API_VERSION_PREFIX+"/webhooks/survey123/%s/measurements", surveyID) + surveyID := input.Survey123ID.String() + base.Path = fmt.Sprintf(APIVersionPrefix+"/webhooks/survey123/%s/measurements", surveyID) q := base.Query() q.Set("key", h.Config.ApplicationKey) base.RawQuery = q.Encode() diff --git a/api/internal/handler/telemetry.go b/api/internal/handler/telemetry.go index c1ed0113..41e9e6b2 100644 --- a/api/internal/handler/telemetry.go +++ b/api/internal/handler/telemetry.go @@ -28,12 +28,12 @@ func NewTelemetry(ctx context.Context, cfg *config.TelemetryConfig, l *logger.Lo es := httperr.NewService( httperr.WithLogger(l.Slogger()), httperr.WithDebugResponseBody(cfg.Debug), - httperr.WithUrlRedactor(func(u *url.URL) { + httperr.WithURLRedactor(func(u *url.URL) { util.RedactQueryParams(u, "key") }), ) h := &TelemetryHandler{ - Client: NewHttpClient(), + Client: NewHTTPClient(), Config: cfg, Logger: l, httperr: es, @@ -72,7 +72,7 @@ func newTelemetryRouter(h *TelemetryHandler) *Router { pprof.Register(e) } - humaCfg := huma.DefaultConfig("MIDAS Telemetry API", API_VERSION) + humaCfg := huma.DefaultConfig("MIDAS Telemetry API", APIVersion) api := humaecho.NewWithGroup(e, g, humaCfg) humaCfg.Components.SecuritySchemes = map[string]*huma.SecurityScheme{ diff --git a/api/internal/handler/timeseries.go b/api/internal/handler/timeseries.go index b311fcfd..2c881d77 100644 --- a/api/internal/handler/timeseries.go +++ b/api/internal/handler/timeseries.go @@ -19,7 +19,7 @@ type TimeseriesIDParam struct { TimeseriesID UUID `path:"timeseries_id" example:"869465fc-dc1e-445e-81f4-9979b5fadda9"` } -func (h *ApiHandler) RegisterTimeseries(api huma.API) { +func (h *APIHandler) RegisterTimeseries(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "timeseries-get", diff --git a/api/internal/handler/timeseries_cwms.go b/api/internal/handler/timeseries_cwms.go index 3d376efa..7cee5292 100644 --- a/api/internal/handler/timeseries_cwms.go +++ b/api/internal/handler/timeseries_cwms.go @@ -12,7 +12,7 @@ import ( var timeseriesCwmsTags = []string{"Timeseries CWMS"} -func (h *ApiHandler) RegisterTimeseriesCWMS(api huma.API) { +func (h *APIHandler) RegisterTimeseriesCWMS(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "timeseries-cwms-list", diff --git a/api/internal/handler/timeseries_process.go b/api/internal/handler/timeseries_process.go index 16aedb3e..2cb0d718 100644 --- a/api/internal/handler/timeseries_process.go +++ b/api/internal/handler/timeseries_process.go @@ -16,7 +16,7 @@ type MeasurementListQueryParams struct { TimeWindowQueryParams } -func (h *ApiHandler) RegisterTimeseriesProcess(api huma.API) { +func (h *APIHandler) RegisterTimeseriesProcess(api huma.API) { measurementListForTimeseriesHandler := func(ctx context.Context, input *struct { TimeseriesIDParam MeasurementListQueryParams @@ -246,7 +246,7 @@ func (h *ApiHandler) RegisterTimeseriesProcess(api huma.API) { }) } -func (h *ApiHandler) measurementListStored(ctx context.Context, arg db.TimeseriesMeasurementCollectionGetForRangeParams) (db.MeasurementCollection, error) { +func (h *APIHandler) measurementListStored(ctx context.Context, arg db.TimeseriesMeasurementCollectionGetForRangeParams) (db.MeasurementCollection, error) { mc, err := h.DBService.TimeseriesMeasurementCollectionGetForRange(ctx, arg) if err != nil { return mc, err @@ -254,7 +254,7 @@ func (h *ApiHandler) measurementListStored(ctx context.Context, arg db.Timeserie return mc, nil } -func (h *ApiHandler) measurementListComputed(ctx context.Context, arg db.ProcessMeasurementFilter) (db.ProcessTimeseriesResponseCollection, error) { +func (h *APIHandler) measurementListComputed(ctx context.Context, arg db.ProcessMeasurementFilter) (db.ProcessTimeseriesResponseCollection, error) { mrc, err := h.DBService.ProcessMeasurementListDynamic(ctx, arg) if err != nil { return mrc, err diff --git a/api/internal/handler/uploader.go b/api/internal/handler/uploader.go index 4d15bf6a..9bd01cc2 100644 --- a/api/internal/handler/uploader.go +++ b/api/internal/handler/uploader.go @@ -19,7 +19,7 @@ type UploaderConfigIDParam struct { UploaderConfigID UUID `path:"uploader_config_id"` } -func (h *ApiHandler) RegisterUploader(api huma.API) { +func (h *APIHandler) RegisterUploader(api huma.API) { huma.Register(api, huma.Operation{ Middlewares: h.Public, OperationID: "uploader-config-list", diff --git a/api/internal/httperr/httperr.go b/api/internal/httperr/httperr.go index 01438b02..7bb8084b 100644 --- a/api/internal/httperr/httperr.go +++ b/api/internal/httperr/httperr.go @@ -1,3 +1,4 @@ +// Package httperr provides utilities for handling HTTP errors with configurable logging and debugging options. package httperr import ( @@ -36,7 +37,7 @@ func WithLogSkipper(skipper func(remoteAddr, method string, u *url.URL, status i } } -func WithUrlRedactor(urlRedactor func(u *url.URL)) httpErrOptsFunc { +func WithURLRedactor(urlRedactor func(u *url.URL)) httpErrOptsFunc { return func(o *httpErrOpts) { o.urlRedactor = urlRedactor } diff --git a/api/internal/logger/logger.go b/api/internal/logger/logger.go index 619690fd..49fa264c 100644 --- a/api/internal/logger/logger.go +++ b/api/internal/logger/logger.go @@ -1,3 +1,4 @@ +// Package logger provides a simple wrapper around slog for logging. package logger import ( diff --git a/api/internal/middleware/audit.go b/api/internal/middleware/audit.go index 2a642304..c2a584e5 100644 --- a/api/internal/middleware/audit.go +++ b/api/internal/middleware/audit.go @@ -56,7 +56,7 @@ func mapClaims(user *jwt.Token) (dto.ProfileClaims, error) { } x509, _ := claims["x509_presented"].(string) - x509Presented := false + var x509Presented bool if strings.ToLower(x509) == "true" { x509Presented = true } diff --git a/api/internal/middleware/ip_whitelist.go b/api/internal/middleware/ip_whitelist.go index ede0b920..4fbcfb9c 100644 --- a/api/internal/middleware/ip_whitelist.go +++ b/api/internal/middleware/ip_whitelist.go @@ -23,14 +23,14 @@ func (m *apiMw) NewWhitelistXFFMiddleware(trusted []url.URL) func(huma.Context, return func(ctx huma.Context, next func(huma.Context)) { xff := ctx.Header("X-Forwarded-For") if xff == "" { - m.httperr.SetResponse(ctx, httperr.Forbidden(errors.New("Missing X-Forwarded-For header"))) + m.httperr.SetResponse(ctx, httperr.Forbidden(errors.New("missing X-Forwarded-For header"))) return } clientIPStr := strings.TrimSpace(strings.Split(xff, ",")[0]) clientIP := net.ParseIP(clientIPStr) if clientIP == nil { - m.httperr.SetResponse(ctx, httperr.Forbidden(errors.New("Invalid IP in X-Forwarded-For header"))) + m.httperr.SetResponse(ctx, httperr.Forbidden(errors.New("invalid IP in X-Forwarded-For header"))) return } @@ -41,6 +41,6 @@ func (m *apiMw) NewWhitelistXFFMiddleware(trusted []url.URL) func(huma.Context, } } - m.httperr.SetResponse(ctx, httperr.Forbidden(errors.New("Client IP not in whitelist"))) + m.httperr.SetResponse(ctx, httperr.Forbidden(errors.New("client IP not in whitelist"))) } } diff --git a/api/internal/middleware/key.go b/api/internal/middleware/key.go index 217bb654..6cd441f1 100644 --- a/api/internal/middleware/key.go +++ b/api/internal/middleware/key.go @@ -22,7 +22,7 @@ func (m *apiMw) AppKeyAuth(ctx huma.Context, next func(huma.Context)) { } } - m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("Unauthorized: invalid or missing key"))) + m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("unauthorized: invalid or missing key"))) } type HashExtractorFunc func(keyID string) (string, error) @@ -43,23 +43,23 @@ func (m *apiMw) keyAuth(isDisabled bool, appKey string, h HashExtractorFunc) fun keyID := ctx.Query("key_id") if keyID == "" { - m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("Unauthorized: missing key_id"))) + m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("unauthorized: missing key_id"))) return } hashVal, err := h(keyID) if err != nil { - m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("Unauthorized: unable to lookup key hash"))) + m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("unauthorized: unable to lookup key hash"))) return } match, err := password.ComparePasswordAndHash(providedKey, hashVal) if err != nil { - m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("Unauthorized: "+err.Error()))) + m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("unauthorized: "+err.Error()))) return } if !match { - m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("Unauthorized: key mismatch"))) + m.httperr.SetResponse(ctx, httperr.Unauthorized(errors.New("unauthorized: key mismatch"))) return } diff --git a/api/internal/middleware/middleware.go b/api/internal/middleware/middleware.go index c6c14282..5f6004b4 100644 --- a/api/internal/middleware/middleware.go +++ b/api/internal/middleware/middleware.go @@ -1,3 +1,4 @@ +// Package middleware provides middleware implementations for the API server. package middleware import ( @@ -48,7 +49,7 @@ func NewEchoMiddeware(cfg *config.ServerConfig) *echoMw { return &echoMw{cfg} } -type ApiMiddleware interface { +type APIMiddleware interface { Middleware DBMiddleware EchoMiddleware @@ -62,9 +63,9 @@ type apiMw struct { httperr *httperr.Service } -var _ ApiMiddleware = (*apiMw)(nil) +var _ APIMiddleware = (*apiMw)(nil) -func NewApiMiddleware(cfg *config.ServerConfig, db *service.DBService, es *httperr.Service, l *logger.Logger) *apiMw { +func NewAPIMiddleware(cfg *config.ServerConfig, db *service.DBService, es *httperr.Service, l *logger.Logger) *apiMw { e := NewEchoMiddeware(cfg) return &apiMw{ echoMw: e, diff --git a/api/internal/migrate/migrate.go b/api/internal/migrate/migrate.go index bb0b5878..e777eee1 100644 --- a/api/internal/migrate/migrate.go +++ b/api/internal/migrate/migrate.go @@ -1,3 +1,4 @@ +// Package migrate provides database migration functionalities. package migrate import ( @@ -394,7 +395,7 @@ func ExtractVersion(s string) (*version.Version, error) { v, err := version.NewVersion(n) if err != nil { - return nil, fmt.Errorf("file %s could not be parsed: error %s; skipping...", s, err.Error()) + return nil, fmt.Errorf("file %s could not be parsed: %w", s, err) } return v, nil } @@ -419,7 +420,7 @@ func QuoteIdentifier(name string) string { if end > -1 { name = name[:end] } - return `"` + strings.Replace(name, `"`, `""`, -1) + `"` + return `"` + strings.ReplaceAll(name, `"`, `""`) + `"` } func ParseRepeatPrefix(filename string) (int, error) { diff --git a/api/internal/mseed/mseed.go b/api/internal/mseed/mseed.go index afa81fcd..6b7f07b3 100644 --- a/api/internal/mseed/mseed.go +++ b/api/internal/mseed/mseed.go @@ -22,6 +22,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +// Package mseed provides functionalities for parsing and handling MiniSEED waveform data. package mseed import ( @@ -68,10 +69,10 @@ func (m *MiniSeedData) Decode(reader io.Reader) error { ) // Parse fixed section - fsOffset := i + FIXED_SECTION_LENGTH + fsOffset := i + FixedSectionLength err := fs.Parse(data[i:fsOffset], bitOrder) if err != nil || - fs.SectionEndOffset != FIXED_SECTION_LENGTH || + fs.SectionEndOffset != FixedSectionLength || (fs.DataQuality != "D" && fs.DataQuality != "R" && fs.DataQuality != "Q" && fs.DataQuality != "M") { continue @@ -114,9 +115,9 @@ func (m *MiniSeedData) Decode(reader io.Reader) error { for i := 64; i < len(data); i += 64 { // Parse fixed section again var fs = FixedSection{} - var fsOffset = i + FIXED_SECTION_LENGTH + var fsOffset = i + FixedSectionLength err := fs.Parse(data[i:fsOffset], bitOrder) - if err == nil && fs.SectionEndOffset == FIXED_SECTION_LENGTH { + if err == nil && fs.SectionEndOffset == FixedSectionLength { initLength = i break } diff --git a/api/internal/mseed/parse.go b/api/internal/mseed/parse.go index 6dee411d..db21c793 100644 --- a/api/internal/mseed/parse.go +++ b/api/internal/mseed/parse.go @@ -29,11 +29,11 @@ import ( "reflect" ) -// f.Parse() parses MiniSeedData fixed section +// Parse parses MiniSeedData fixed section func (f *FixedSection) Parse(buffer []byte, bitOrder int) error { t := reflect.ValueOf(f).Elem() - for i, j := 0, 0; i < FIXED_SECTION_LENGTH; j++ { + for i, j := 0, 0; i < FixedSectionLength; j++ { var ( field = fixedSectionMap[j] fieldName = field.FieldName @@ -152,7 +152,7 @@ func (d *dataSection) Parse(buffer []byte, samples, blockette, encoding, bitOrde switch encoding { case ASCII: // ASCII text - d.Decoded = append(d.Decoded, unpackAscii(buffer)) + d.Decoded = append(d.Decoded, unpackASCII(buffer)) case INT16: // 16-bit integer result := unpackInt(buffer, samples, 16, bitOrder) for _, v := range result { diff --git a/api/internal/mseed/types.go b/api/internal/mseed/types.go index 590a8365..9cc0d296 100644 --- a/api/internal/mseed/types.go +++ b/api/internal/mseed/types.go @@ -30,8 +30,8 @@ import ( // The length of the fixed header section const ( - FIXED_SECTION_LENGTH = 48 - BLOCKETTE100X_SECTION_LENGTH = 16 + FixedSectionLength = 48 + Blockette100XSectionLength = 16 ) // First significant bit diff --git a/api/internal/mseed/unpack.go b/api/internal/mseed/unpack.go index a4e237e9..8d15af1d 100644 --- a/api/internal/mseed/unpack.go +++ b/api/internal/mseed/unpack.go @@ -28,8 +28,8 @@ import ( "fmt" ) -// unpackAscii unpacks ASCII data from buffer -func unpackAscii(buffer []byte) string { +// unpackASCII unpacks ASCII data from buffer +func unpackASCII(buffer []byte) string { return string(buffer) } diff --git a/api/internal/mseed/utils.go b/api/internal/mseed/utils.go index 84ff98a4..6fcd3cbf 100644 --- a/api/internal/mseed/utils.go +++ b/api/internal/mseed/utils.go @@ -76,12 +76,12 @@ func getBitOrder(buffer []byte) (int, error) { } bitOrder := assembleInt(buffer, 2, MSBFIRST) - if bitOrder == FIXED_SECTION_LENGTH { + if bitOrder == FixedSectionLength { return MSBFIRST, nil } bitOrder = assembleInt(buffer, 2, LSBFIRST) - if bitOrder == FIXED_SECTION_LENGTH { + if bitOrder == FixedSectionLength { return LSBFIRST, nil } diff --git a/api/internal/password/password.go b/api/internal/password/password.go index 6ea0a015..4b1f729e 100644 --- a/api/internal/password/password.go +++ b/api/internal/password/password.go @@ -1,3 +1,4 @@ +// Package password provides functions for creating and comparing package password import ( diff --git a/api/internal/pgqueue/batcher.go b/api/internal/pgqueue/batcher.go index 9d09db5c..997f2183 100644 --- a/api/internal/pgqueue/batcher.go +++ b/api/internal/pgqueue/batcher.go @@ -14,7 +14,7 @@ type BatcherConfig struct { FlushWorkers int } -// A generic batcher over any event type T. +// Batcher is a generic batcher over any event type T. type Batcher[T any] struct { cfg *BatcherConfig sub *pubsub.Subscription diff --git a/api/internal/pgqueue/pgqueue.go b/api/internal/pgqueue/pgqueue.go index a2b9f417..9a354d07 100644 --- a/api/internal/pgqueue/pgqueue.go +++ b/api/internal/pgqueue/pgqueue.go @@ -1,3 +1,4 @@ +// Package pgqueue implements a PostgreSQL-backed job queue using the riverqueue library. package pgqueue import ( diff --git a/api/internal/service/alert_check_event.go b/api/internal/service/alert_check_event.go index c3bf2b21..f34a204b 100644 --- a/api/internal/service/alert_check_event.go +++ b/api/internal/service/alert_check_event.go @@ -163,7 +163,7 @@ func (s DBService) DoAlertCheckEvent(ctx context.Context, batch []dto.WorkerAler return fmt.Errorf("MeasurementListBatchNeighborsForTimeseriesRange: %w", qerr) } - evals, err := s.Queries.AlertConfigEvalListForTimeseriesAlertTypes(ctx, db.AlertConfigEvalListForTimeseriesAlertTypesParams{ + evals, err := s.AlertConfigEvalListForTimeseriesAlertTypes(ctx, db.AlertConfigEvalListForTimeseriesAlertTypesParams{ TimeseriesIDs: tsIDs, AlertTypeIDs: []uuid.UUID{db.ThresholdAlertTypeID, db.RateOfChangeAlertTypeID}, }) @@ -187,8 +187,8 @@ func (s DBService) DoAlertCheckEvent(ctx context.Context, batch []dto.WorkerAler if !exists || len(mm) == 0 { continue } - last, _ := lastByTS[tsID] - next, _ := nextByTS[tsID] + last := lastByTS[tsID] + next := nextByTS[tsID] row := db.AlertConfigMeasurementListForTimeseriesRow{ TimeseriesID: tsID, @@ -332,7 +332,7 @@ func (s *DBService) doAlertEventChecks(ctx context.Context, acc []AlertConfigEve acIDs = append(acIDs, id) } - acEmailInfo, err := s.Queries.AlertConfigNotifyListForIDs(ctx, acIDs) + acEmailInfo, err := s.AlertConfigNotifyListForIDs(ctx, acIDs) if err != nil { return fmt.Errorf("AlertConfigNotifyListForIDs query error: %w", err) } diff --git a/api/internal/service/alert_config_schedule.go b/api/internal/service/alert_config_schedule.go index 38d2f113..9118aa6e 100644 --- a/api/internal/service/alert_config_schedule.go +++ b/api/internal/service/alert_config_schedule.go @@ -90,6 +90,9 @@ func (s *DBService) AlertConfigScheduleUpdate(ctx context.Context, ac dto.AlertC AlertConfigID: ac.ID, ShowIncompletePending: true, }) + if err != nil { + return a, fmt.Errorf("SubmittalListForAlertConfig %w", err) + } if len(ss) == 0 { return a, fmt.Errorf("no submittals found for alert config %s", ac.ID) } diff --git a/api/internal/service/datalogger_telemetry.go b/api/internal/service/datalogger_telemetry.go index cc89bd4a..4fd0bc30 100644 --- a/api/internal/service/datalogger_telemetry.go +++ b/api/internal/service/datalogger_telemetry.go @@ -16,14 +16,14 @@ import ( ) func (s *DBService) DataloggerTablePreviewCreate(ctx context.Context, prv dto.DataloggerTablePreviewDTO) error { - return s.Queries.DataloggerTablePreviewCreateOrUpdate(ctx, db.DataloggerTablePreviewCreateOrUpdateParams{ + return s.DataloggerTablePreviewCreateOrUpdate(ctx, db.DataloggerTablePreviewCreateOrUpdateParams{ DataloggerTableID: prv.DataloggerTableID, UpdatedAt: prv.UpdatedAt, Preview: prv.Preview, }) } -// UpdateDataloggerTablePreview attempts to update a table preview by datalogger_id and table_name, creates the +// DataloggerTablePreviewUpdate attempts to update a table preview by datalogger_id and table_name, creates the // datalogger table and corresponding preview if it doesn't exist func (s *DBService) DataloggerTablePreviewUpdate(ctx context.Context, dataloggerID uuid.UUID, tableName string, prv dto.DataloggerTablePreviewDTO) (uuid.UUID, error) { tx, err := s.db.Begin(ctx) @@ -103,7 +103,7 @@ func (s *DBService) DataloggerTableErrorUpdate(ctx context.Context, dataloggerID return tx.Commit(ctx) } -// ParseTOA5 parses a Campbell Scientific TOA5 data file that is simlar to a csv. +// TimeseriesMeasurementCreateOrUpdateDataloggerTOA5Upload parses a Campbell Scientific TOA5 data file that is simlar to a csv. // The unique properties of TOA5 are that the meatdata are stored in header of file (first 4 lines of csv) func (s *DBService) TimeseriesMeasurementCreateOrUpdateDataloggerTOA5Upload(ctx context.Context, r io.Reader) error { tx, err := s.db.Begin(ctx) diff --git a/api/internal/service/db.go b/api/internal/service/db.go index 3b3527d3..e51e0dda 100644 --- a/api/internal/service/db.go +++ b/api/internal/service/db.go @@ -1,3 +1,4 @@ +// Package service implements services that interact with the database and other dependencies. package service import ( diff --git a/api/internal/service/dcsloader.go b/api/internal/service/dcsloader.go index 3e8b5738..c3abe1cb 100644 --- a/api/internal/service/dcsloader.go +++ b/api/internal/service/dcsloader.go @@ -31,24 +31,24 @@ type DcsLoaderService struct { } const ( - API_VERSION_PREFIX = "/v4" + APIVersionPrefix = "/v4" ) func NewDcsLoaderService(apiClient *http.Client, cfg *config.DcsLoaderConfig, logger *logger.Logger) *DcsLoaderService { return &DcsLoaderService{apiClient, cfg, logger} } -func (s *DcsLoaderService) PostMeasurementCollectionToApi(ctx context.Context, mcs []dto.MeasurementCollectionDTO) error { +func (s *DcsLoaderService) PostMeasurementCollectionToAPI(ctx context.Context, mcs []dto.MeasurementCollectionDTO) error { requestBodyBytes, err := json.Marshal(mcs) if err != nil { return err } - base, err := url.Parse(s.cfg.ApiHost) + base, err := url.Parse(s.cfg.APIHost) if err != nil { return fmt.Errorf("invalid api host: %w", err) } - base.Path = API_VERSION_PREFIX + "/timeseries_measurements" + base.Path = APIVersionPrefix + "/timeseries_measurements" q := base.Query() q.Set("key", s.cfg.APIKey) base.RawQuery = q.Encode() @@ -99,7 +99,7 @@ func (s *DcsLoaderService) PostMeasurementCollectionToApi(ctx context.Context, m return nil } -func (s *DcsLoaderService) PostSeisMeasurementCollectionToApi(ctx context.Context, mcs []dto.SeisMeasurementCollectionDTO) error { +func (s *DcsLoaderService) PostSeisMeasurementCollectionToAPI(ctx context.Context, mcs []dto.SeisMeasurementCollectionDTO) error { if len(mcs) == 0 { log.Print("no measurements to post") return nil @@ -110,11 +110,11 @@ func (s *DcsLoaderService) PostSeisMeasurementCollectionToApi(ctx context.Contex return err } - base, err := url.Parse(s.cfg.ApiHost) + base, err := url.Parse(s.cfg.APIHost) if err != nil { return fmt.Errorf("invalid api host: %w", err) } - base.Path = API_VERSION_PREFIX + "/timeseries_measurements_seis" + base.Path = APIVersionPrefix + "/timeseries_measurements_seis" q := base.Query() q.Set("key", s.cfg.APIKey) base.RawQuery = q.Encode() @@ -309,7 +309,7 @@ func (s *DcsLoaderService) getSnclTimeseriesLookup(ctx context.Context, sncls [] if err != nil { return nil, err } - req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("%s/instruments/seis/mappings?key=%s", s.cfg.ApiHost, s.cfg.APIKey), bytes.NewReader(requestBodyBytes)) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("%s/instruments/seis/mappings?key=%s", s.cfg.APIHost, s.cfg.APIKey), bytes.NewReader(requestBodyBytes)) if err != nil { return nil, err } diff --git a/api/internal/service/instrument_incl.go b/api/internal/service/instrument_incl.go index 3fa6617e..46510fd0 100644 --- a/api/internal/service/instrument_incl.go +++ b/api/internal/service/instrument_incl.go @@ -42,7 +42,7 @@ func createInclOptsBatch(ctx context.Context, q *db.Queries, ii []dto.Instrument createTimeseriesBatchParams := make([][]db.TimeseriesCreateBatchParams, len(ii)) createInclSegmentBatchParams := make([][]db.InclSegmentCreateBatchParams, len(ii)) - createBottomElevationTsParams := make([]db.TimeseriesCreateBatchParams, len(ii)) + createBottomElevationTSParams := make([]db.TimeseriesCreateBatchParams, len(ii)) createInclOptsParams := make([]db.InclOptsCreateBatchParams, len(ii)) createBottomElevationMmtParams := make([]db.TimeseriesMeasurementCreateBatchParams, len(ii)) @@ -56,7 +56,7 @@ func createInclOptsBatch(ctx context.Context, q *db.Queries, ii []dto.Instrument InstrumentID: inst.ID, } } - createBottomElevationTsParams[idx] = db.TimeseriesCreateBatchParams{ + createBottomElevationTSParams[idx] = db.TimeseriesCreateBatchParams{ InstrumentID: inst.ID, Name: inst.Slug + "-bottom-elevation", ParameterID: db.InclParameterID, @@ -91,7 +91,7 @@ func createInclOptsBatch(ctx context.Context, q *db.Queries, ii []dto.Instrument if err != nil { return err } - q.TimeseriesCreateBatch(ctx, createBottomElevationTsParams).QueryRow(func(i int, r db.TimeseriesCreateBatchRow, e error) { + q.TimeseriesCreateBatch(ctx, createBottomElevationTSParams).QueryRow(func(i int, r db.TimeseriesCreateBatchRow, e error) { if e != nil { err = e return diff --git a/api/internal/service/instrument_ipi.go b/api/internal/service/instrument_ipi.go index 6f40bd97..f4a9eb11 100644 --- a/api/internal/service/instrument_ipi.go +++ b/api/internal/service/instrument_ipi.go @@ -55,7 +55,7 @@ func createIpiOptsBatch(ctx context.Context, q *db.Queries, ii []dto.InstrumentD createTimeseriesBatchParams := make([][]db.TimeseriesCreateBatchParams, len(ii)) createIpiSegmentBatchParams := make([][]db.IpiSegmentCreateBatchParams, len(ii)) - createBottomElevationTsParams := make([]db.TimeseriesCreateBatchParams, len(ii)) + createBottomElevationTSParams := make([]db.TimeseriesCreateBatchParams, len(ii)) createIpiOptsParams := make([]db.IpiOptsCreateBatchParams, len(ii)) createBottomElevationMmtParams := make([]db.TimeseriesMeasurementCreateBatchParams, len(ii)) @@ -77,7 +77,7 @@ func createIpiOptsBatch(ctx context.Context, q *db.Queries, ii []dto.InstrumentD InstrumentID: inst.ID, } } - createBottomElevationTsParams[idx] = db.TimeseriesCreateBatchParams{ + createBottomElevationTSParams[idx] = db.TimeseriesCreateBatchParams{ InstrumentID: inst.ID, Name: inst.Slug + "-bottom-elevation", ParameterID: db.IpiParameterID, @@ -113,7 +113,7 @@ func createIpiOptsBatch(ctx context.Context, q *db.Queries, ii []dto.InstrumentD if err != nil { return err } - q.TimeseriesCreateBatch(ctx, createBottomElevationTsParams).QueryRow(func(i int, r db.TimeseriesCreateBatchRow, e error) { + q.TimeseriesCreateBatch(ctx, createBottomElevationTSParams).QueryRow(func(i int, r db.TimeseriesCreateBatchRow, e error) { if e != nil { err = e return diff --git a/api/internal/service/instrument_saa.go b/api/internal/service/instrument_saa.go index 21fce8fa..6ef3c639 100644 --- a/api/internal/service/instrument_saa.go +++ b/api/internal/service/instrument_saa.go @@ -55,7 +55,7 @@ func createSaaOptsBatch(ctx context.Context, q *db.Queries, ii []dto.InstrumentD createTimeseriesBatchParams := make([][]db.TimeseriesCreateBatchParams, len(ii)) createSaaSegmentBatchParams := make([][]db.SaaSegmentCreateBatchParams, len(ii)) - createBottomElevationTsParams := make([]db.TimeseriesCreateBatchParams, len(ii)) + createBottomElevationTSParams := make([]db.TimeseriesCreateBatchParams, len(ii)) createSaaOptsParams := make([]db.SaaOptsCreateBatchParams, len(ii)) createBottomElevationMmtParams := make([]db.TimeseriesMeasurementCreateBatchParams, len(ii)) @@ -77,7 +77,7 @@ func createSaaOptsBatch(ctx context.Context, q *db.Queries, ii []dto.InstrumentD InstrumentID: inst.ID, } } - createBottomElevationTsParams[idx] = db.TimeseriesCreateBatchParams{ + createBottomElevationTSParams[idx] = db.TimeseriesCreateBatchParams{ InstrumentID: inst.ID, Name: inst.Slug + "-bottom-elevation", ParameterID: db.SaaParameterID, @@ -113,7 +113,7 @@ func createSaaOptsBatch(ctx context.Context, q *db.Queries, ii []dto.InstrumentD if err != nil { return err } - q.TimeseriesCreateBatch(ctx, createBottomElevationTsParams).QueryRow(func(i int, r db.TimeseriesCreateBatchRow, e error) { + q.TimeseriesCreateBatch(ctx, createBottomElevationTSParams).QueryRow(func(i int, r db.TimeseriesCreateBatchRow, e error) { if e != nil { err = e return diff --git a/api/internal/service/plot_config_contour.go b/api/internal/service/plot_config_contour.go index 34fa3753..02f160e9 100644 --- a/api/internal/service/plot_config_contour.go +++ b/api/internal/service/plot_config_contour.go @@ -3,6 +3,7 @@ package service import ( "context" "errors" + "fmt" "time" "github.com/USACE/instrumentation-api/api/v4/internal/db" @@ -27,6 +28,9 @@ func (s *DBService) PlotConfigCreateContour(ctx context.Context, pc dto.PlotConf pc.PlotType = dto.ContourPlotType pcID, err := createPlotConfigCommon(ctx, qtx, pc.PlotConfigDTO) + if err != nil { + return a, fmt.Errorf("createPlotConfigCommon: %w", err) + } if err := qtx.PlotContourConfigCreate(ctx, db.PlotContourConfigCreateParams{ PlotConfigID: pcID, Time: pc.Display.Time, diff --git a/api/internal/service/plot_config_scatter_line.go b/api/internal/service/plot_config_scatter_line.go index 565cb22e..252c90d9 100644 --- a/api/internal/service/plot_config_scatter_line.go +++ b/api/internal/service/plot_config_scatter_line.go @@ -21,8 +21,11 @@ func (s *DBService) PlotConfigCreateScatterLine(ctx context.Context, pc dto.Plot pc.PlotType = dto.ScatterLinePlotType pcID, err := createPlotConfigCommon(ctx, qtx, pc.PlotConfigDTO) + if err != nil { + return a, fmt.Errorf("createPlotConfigCommon %w", err) + } if err := validateCreateTraces(ctx, qtx, pcID, pc.Display.Traces); err != nil { - return a, err + return a, fmt.Errorf("validateCreateTraces %w", err) } if err := qtx.PlotConfigScatterLineLayoutCreate(ctx, db.PlotConfigScatterLineLayoutCreateParams{ PlotConfigID: pcID, @@ -153,7 +156,7 @@ func validateColor(colorHex string) error { return invalidHexErr } for _, r := range parts[1] { - if !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f' || r >= 'A' && r <= 'F') { + if (r < '0' || r > '9') && (r < 'a' || r > 'f') && (r < 'A' || r > 'F') { return invalidHexErr } } diff --git a/api/internal/service/profile.go b/api/internal/service/profile.go index b41c7cce..05b657b7 100644 --- a/api/internal/service/profile.go +++ b/api/internal/service/profile.go @@ -20,7 +20,7 @@ func (s *DBService) ProfileGetWithTokensForClaims(ctx context.Context, claims dt var a db.VProfile var err error if claims.CacUID != nil { - a, err = s.Queries.ProfileGetForEDIPI(ctx, int64(*claims.CacUID)) + a, err = s.ProfileGetForEDIPI(ctx, int64(*claims.CacUID)) } else { a, err = s.ProfileGetForEmail(ctx, claims.Email) } @@ -31,7 +31,7 @@ func (s *DBService) ProfileGetWithTokensForClaims(ctx context.Context, claims dt } func (s *DBService) ProfileUpdateForClaims(ctx context.Context, p db.VProfile, claims dto.ProfileClaims) (db.VProfile, error) { - var claimsMatchProfile bool = p.Username == claims.PreferredUsername && + claimsMatchProfile := p.Username == claims.PreferredUsername && strings.EqualFold(p.Email, claims.Email) && p.DisplayName == claims.Name @@ -39,7 +39,7 @@ func (s *DBService) ProfileUpdateForClaims(ctx context.Context, p db.VProfile, c return p, nil } if claims.CacUID != nil && !claimsMatchProfile { - if err := s.Queries.ProfileUpdateForEDIPI(ctx, db.ProfileUpdateForEDIPIParams{ + if err := s.ProfileUpdateForEDIPI(ctx, db.ProfileUpdateForEDIPIParams{ Username: claims.PreferredUsername, Email: claims.Email, DisplayName: claims.Name, @@ -54,7 +54,7 @@ func (s *DBService) ProfileUpdateForClaims(ctx context.Context, p db.VProfile, c return p, nil } if strings.EqualFold(p.Email, claims.Email) && !claimsMatchProfile { - if err := s.Queries.ProfileUpdateForEmail(ctx, db.ProfileUpdateForEmailParams{ + if err := s.ProfileUpdateForEmail(ctx, db.ProfileUpdateForEmailParams{ Username: claims.PreferredUsername, DisplayName: claims.Name, Email: claims.Email, diff --git a/api/internal/service/project.go b/api/internal/service/project.go index 333bb22d..8d8d9986 100644 --- a/api/internal/service/project.go +++ b/api/internal/service/project.go @@ -9,11 +9,6 @@ import ( "github.com/google/uuid" ) -type ImgUploaderOpts struct { - rawPath string - bucketName string -} - type ProjectCount struct { ProjectCount int64 `json:"project_count"` } diff --git a/api/internal/service/survey123.go b/api/internal/service/survey123.go index 9e349886..1368b1f6 100644 --- a/api/internal/service/survey123.go +++ b/api/internal/service/survey123.go @@ -333,7 +333,6 @@ func (s *DBService) parseAttributes(attr map[string]any, eqt map[string]*uuid.UU usrErr := fmt.Errorf("invalid value type for field '%s%s' (must be number), using NaN;", instKey, subKey) s.logger.Debug(context.Background(), "survey123 parsing error", "err", err, "userErr", usrErr) errs = append(errs, usrErr) - continue } default: tmp := true @@ -342,7 +341,6 @@ func (s *DBService) parseAttributes(attr map[string]any, eqt map[string]*uuid.UU err := fmt.Errorf("invalid value type for field '%s%s' (must be number) using NaN;", instKey, subKey) s.logger.Debug(context.Background(), "survey123 parsing error", "err", err) errs = append(errs, err) - continue } tsID, exists := eqt[instKey+"__"+subKey] if !exists { diff --git a/api/internal/service/thinglogix.go b/api/internal/service/thinglogix.go index cb1cc2fd..e76d3ba2 100644 --- a/api/internal/service/thinglogix.go +++ b/api/internal/service/thinglogix.go @@ -179,16 +179,16 @@ type ThinglogixService struct { logger *logger.Logger } -// Credentials for the ThingLogix API authentication. +// CognitoCredentialsResponse holds credentials for ThingLogix API authentication. // Its methods implement a browser flow for a custom wrapper implementation of AWS Cognito. type CognitoCredentialsResponse struct { Credentials struct { - AccessKeyId string - SecretKey string - SessionToken string - Expiration float64 - } - IdentityId string + AccessKeyID string `json:"AccessKeyId"` + SecretKey string `json:"SecretKey"` + SessionToken string `json:"SessionToken"` + Expiration float64 `json:"Expiration"` + } `json:"Credentials"` + IdentityID string `json:"IdentityId"` } func NewThinglogixService(ctx context.Context, cfg *config.ThinglogixConfig, l *logger.Logger) (*ThinglogixService, error) { @@ -222,7 +222,7 @@ func NewThinglogixService(ctx context.Context, cfg *config.ThinglogixConfig, l * func (a *ThinglogixService) FetchDevices(ctx context.Context) (json.RawMessage, error) { // using body in GET to match browser flow body := []byte(`{}`) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, a.Config.ThinglogixApiGatewayEndpoint+"/foundry/devices", bytes.NewReader(body)) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, a.Config.ThinglogixAPIGatewayEndpoint+"/foundry/devices", bytes.NewReader(body)) if err != nil { return nil, err } @@ -240,7 +240,7 @@ func (a *ThinglogixService) FetchDevices(ctx context.Context) (json.RawMessage, req.Header.Set("Content-Type", "application/json") // needs to be set for signer, even though this is a GET awsCreds := aws.Credentials{ - AccessKeyID: a.Auth.Credentials.AccessKeyId, + AccessKeyID: a.Auth.Credentials.AccessKeyID, SecretAccessKey: a.Auth.Credentials.SecretKey, SessionToken: a.Auth.Credentials.SessionToken, Source: "Thinglogix", @@ -287,7 +287,7 @@ func (a *ThinglogixService) hashedPassword() string { } func (a *ThinglogixService) computeDecryptionKey() (string, error) { - parsedURL, err := url.Parse(a.Config.ThinglogixApiGatewayEndpoint) + parsedURL, err := url.Parse(a.Config.ThinglogixAPIGatewayEndpoint) if err != nil { return "", fmt.Errorf("invalid endpoint: %w", err) } @@ -319,7 +319,7 @@ func (a *ThinglogixService) getLoginToken(ctx context.Context, uid string) (stri } url := fmt.Sprintf("%s/foundry/login?uid=%s&username=%s×tamp=%s&signature=%s", - a.Config.ThinglogixApiGatewayEndpoint, + a.Config.ThinglogixAPIGatewayEndpoint, uid, a.Config.ThinglogixUser, timestamp, @@ -355,7 +355,7 @@ func (a *ThinglogixService) getLoginToken(ctx context.Context, uid string) (stri return "", fmt.Errorf("could not decode response body: %w", err) } - decryptedJson, err := decrypt(body, substringRunes(decryptionKey, 0, 32)) + decryptedJSON, err := decrypt(body, substringRunes(decryptionKey, 0, 32)) if err != nil { return "", fmt.Errorf("decryption failed: %w", err) } @@ -366,7 +366,7 @@ func (a *ThinglogixService) getLoginToken(ctx context.Context, uid string) (stri User json.RawMessage `json:"user"` Region string `json:"region"` } - if err := json.Unmarshal([]byte(decryptedJson), &parsed); err != nil { + if err := json.Unmarshal([]byte(decryptedJSON), &parsed); err != nil { return "", fmt.Errorf("unmarshal failed: %w", err) } @@ -395,7 +395,7 @@ func (a *ThinglogixService) getProviderToken(ctx context.Context, uid, key strin signature := a.generateProviderSignature(stringToSign, key) urlStr := fmt.Sprintf("%s/foundry/token?uid=%s×tamp=%s%s&signature=%s", - a.Config.ThinglogixApiGatewayEndpoint, + a.Config.ThinglogixAPIGatewayEndpoint, url.QueryEscape(uid), url.QueryEscape(timestamp), providerParams, @@ -426,22 +426,22 @@ func (a *ThinglogixService) getProviderToken(ctx context.Context, uid, key strin return "", "", fmt.Errorf("could not decode response body: %w", err) } - decryptedJson, err := decrypt(body, key) + decryptedJSON, err := decrypt(body, key) if err != nil { return "", "", fmt.Errorf("decryption failed: %w", err) } var parsed struct { Token string `json:"token"` - IdentityId string `json:"identityId"` - IdentityPoolId string `json:"identityPoolId"` - RdsInstalled string `json:"rds_installed"` + IdentityID string `json:"identityId"` + IdentityPoolID string `json:"identityPoolId"` + RDSInstalled string `json:"rds_installed"` } - if err := json.Unmarshal([]byte(decryptedJson), &parsed); err != nil { + if err := json.Unmarshal([]byte(decryptedJSON), &parsed); err != nil { return "", "", fmt.Errorf("unmarshal failed: %w", err) } - return parsed.Token, parsed.IdentityId, nil + return parsed.Token, parsed.IdentityID, nil } func (a *ThinglogixService) initAWSCredentials(ctx context.Context, identityID, jwt string) error { diff --git a/api/internal/timewindow/timewindow.go b/api/internal/timewindow/timewindow.go index 4a18351f..6a5d78d7 100644 --- a/api/internal/timewindow/timewindow.go +++ b/api/internal/timewindow/timewindow.go @@ -1,3 +1,4 @@ +// Package timewindow provides functionality to encode and decode time windows package timewindow import ( diff --git a/api/internal/tz/tz.go b/api/internal/tz/tz.go index 13804f9e..e3f1dfe2 100644 --- a/api/internal/tz/tz.go +++ b/api/internal/tz/tz.go @@ -1,3 +1,4 @@ +// Package tz provides functionality to list timezones from the IANA timezone data available from the filesystem. package tz import ( @@ -21,7 +22,7 @@ func ListTimezones(zoneDir string) ([]string, error) { func (t *timezones) walkTimezoneDirs(zoneDir, path string) error { files, err := os.ReadDir(zoneDir + path) if err != nil { - return fmt.Errorf("Unable to load timezones from directory %s ; %w", zoneDir+path, err) + return fmt.Errorf("unable to load timezones from directory %s ; %w", zoneDir+path, err) } for _, f := range files { if f.Name() != strings.ToUpper(f.Name()[:1])+f.Name()[1:] { diff --git a/api/internal/upload/upload.go b/api/internal/upload/upload.go index fca71dea..c0a6c2a8 100644 --- a/api/internal/upload/upload.go +++ b/api/internal/upload/upload.go @@ -1,3 +1,4 @@ +// Package upload provides functionality to upload timeseries measurements and notes to the database. package upload import ( @@ -198,7 +199,7 @@ func (up *Upload) UploadMeasurementNoteBatchRow(ctx context.Context, row []strin "uploader_config_id", up.UploaderConfigID, "requestTime", up.requestTimeWithDrift, "rowTime", t, - "up.uploadOptsInternal.rowNumber", up.uploadOptsInternal.rowNumber, + "up.uploadOptsInternal.rowNumber", up.rowNumber, "up.TimeFormat", up.TimeFormat, "up.TimeColIdx", up.TimeColIdx, ) diff --git a/api/internal/util/redactor.go b/api/internal/util/redactor.go index 4e266ec4..df17c489 100644 --- a/api/internal/util/redactor.go +++ b/api/internal/util/redactor.go @@ -4,6 +4,8 @@ import ( "net/url" ) +// RedactQueryParams redacts the specified query parameters in the given URL by replacing their values with "REDACTED". +// // https://github.com/golang/go/issues/47442#issuecomment-888554396 func RedactQueryParams(u *url.URL, queryParams ...string) { q := u.Query() diff --git a/api/internal/util/util.go b/api/internal/util/util.go new file mode 100644 index 00000000..f9c39b84 --- /dev/null +++ b/api/internal/util/util.go @@ -0,0 +1,2 @@ +// Package util provides utility functions for the API. +package util diff --git a/api/internal/worker/worker.go b/api/internal/worker/worker.go index 2b0bdeab..aa7f2036 100644 --- a/api/internal/worker/worker.go +++ b/api/internal/worker/worker.go @@ -1,3 +1,4 @@ +// Package worker implements the pgqueue.PGQueueWorker interface using riverqueue. package worker import ( From b60c22f2e7f6d8321e2dc574b11c82a45dfe6f65 Mon Sep 17 00:00:00 2001 From: Dennis Smith Date: Fri, 16 Jan 2026 17:05:55 -0500 Subject: [PATCH 2/2] fix: updated ts_test to reflect new error notation --- api/internal/tz/tz_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/internal/tz/tz_test.go b/api/internal/tz/tz_test.go index 2ae36981..ec4b7403 100644 --- a/api/internal/tz/tz_test.go +++ b/api/internal/tz/tz_test.go @@ -16,7 +16,7 @@ func TestListTimezones_NonExistentDir(t *testing.T) { tzs, err := tz.ListTimezones(nonexistent) assert.Nil(t, tzs) assert.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("Unable to load timezones from directory %s", nonexistent)) + assert.Contains(t, err.Error(), fmt.Sprintf("unable to load timezones from directory %s", nonexistent)) } func TestListTimezones_ValidStructure(t *testing.T) {