Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* alert metadata WIP * add alert metada changes * add alert type * add validation * generic api handler correction * add meta field to webhook notification * remove log statements * resolve go lint issues * Update migrate/migrations/20240212125328-alert-metadata.sql Co-authored-by: Nathaniel Caza <[email protected]> * Update graphql2/schema.graphql Co-authored-by: Nathaniel Caza <[email protected]> * Update graphql2/graphqlapp/alert.go Co-authored-by: Nathaniel Caza <[email protected]> * change as per review * Add createMetaTx method * fix urlform values * fix generic api tests * fix lint error * remove commented code * move metadata out of CreateOrUpdate Since we're handling this separatly with a specific store method, we don't want to add a second place to set metadata here. If/when we update things using CreateOrUpdate, we'll make a Tx method for it. This way we don't need to update call sites across the app for the new signature. * update SetMetadata to support service permissions validation So this query is a bit more complicated, but we want to make sure no future bug allows a service/integration key to update the metadata of an alert that doesn't belong to it. Integration keys in GoAlert are tied to a single service, and all DB calls regarding alerts should be guarded such that only alerts belonging to that specific service may be modified, including the newly introduced metadata. The approach I took here allows us to pass a service ID, optionally (i.e., ONLY when a request comes from an integration), where the query will fail to insert/update any data if it's mismatched. If the service ID is null, it will skip this check (i.e., a user action). * fix type for manymetadata and add single query This is just updating the type from int to bigint (64 bit) and using @alert_ids instead of $1 so that sqlc generates a better name for the argument. * regen sqlc * move store methods to metadata.go For organization sake, moving the store methods to a separate file (we have a bad habbit of having the store.go files growing forever). I also implemented things using the `gadb` and taking a `DBTX` rather than a sql.Tx. This is the most recent pattern, although most DB code has not been refactored for this. I'm using the `map[string]string` Go type directly to get rid of any indirection on the metadata format external to this package. Internally, I added a `metadataDBFormat` that hopefully by name makes it clearer it's only intended to be used at rest. Compared to what was there before, I also: - Added assertions on the type string - Added a MetadataAlertID type that includes an alert ID for the dataloader - Added an Access Denied error if SetMetadataTx fails because of an invalid alert or service ID mismatch * move validation to metadata.go For this I just moved the validation to metadata.go and implemented it as a standalone function rather than a method. This was a mistake on my part of recommending a method -- we really don't need a specific type for metadata as it's just a `map[string]string` we also don't have a use-case to "normalize" the data, as we always store it as-is. This is different to things like services, schedules, etc... where we will do things like trim whitespace, remove double-spaces, to "normalize" the input. For this it's just pass or fail. * missing sig. updates Some leftover updates I forgot to commit * add ServiceNullUUID method to permission pkg Similar to the UserNullUUID -- a convenience/helper method so we can pull the service ID from the current context and pass it directly as a query argument. * update grafana call * regen sqlc * fix CreateOrUpdate call * add db in call for metadata * fix edge case handling in MetaValue ErrNoRows is handled by the method itself, so here we can just return any err we get. We also want to check if the map is nil before doing `md[key]` so we don't panic if the alert has no metadata. * move map handling out of Tx function This is a bit of an optimization -- we can handle allocating the memory, and processing the map outside of the transaction to keep the transaction as quick as possible. Additionally, we can do some early validation to jump out _before_ we get to the withContextTx call. This helps because to create the alert, we actually: - Start a transaction - Grab a global exclusive lock on the service's row - Create the alert itself - Add the log entry about the alert So if we already know the metadata is going to be rejected, we can skip that. Lastly, now that the alert store only takes `map[string]map` it simplifies the code here as well. * add create CreateOrUpdateWithMeta store method and update generic api handler call to point to new method * add comment * remove unused queries * clairify comment * tweak error message * cleanup graphql code - removed debug print - removed redundant nil check on Metadata() result - updated Metadata comment regarding return values * update documentation * remove changes to existing tests (will create new) * add metadata smoke test * add dataloader for batching metadata lookups * use dataloader * regen * add id column for switchover * regen sqlc --------- Co-authored-by: Forfold <[email protected]> Co-authored-by: Nathaniel Caza <[email protected]>
- Loading branch information