Skip to content

Response 403 (and no data) returned from MetadataFactory.update_metadata() using GITLAB_API_TOKEN

See detailed issue description below the ToDo, as well as in the discussion.

ToDo:

  • modify geomagio/api/secure/metadata.py so that the PUT route uses a full path to the reviewer group
    • for example: ghsc/geomag/operations/roles/reviewer
    • this more consistent with front-end does things, and more secure
  • modify geomagio/api/secure/login.py so that get_gitlab_user() adds all groups to user.groups
    • for example:
      groups_response = await client.get(
          f"{url}/groups?per_page=100&search=ghsc/geomag/operations",
          headers=header
      )
  • modify geomagio/api/secure/metadata.py so that the PUT and POST routes check a set of allowed groups
    • pass a list of groups to the require_user() call
    • observers (and higher) should be allowed to post, and
    • reviewers (and higher) should be allowed to put

Detailed Description:

When an authenticated user, logged in and using either the Swagger interface at https://staging-geomag.cr.usgs.gov/ws/secure/docs, or the Geomag Operations app at https://staging-geomag.cr.usgs.gov/operations, tries to "update" a metadata record, all goes well. Specifically, the https://staging-geomag.cr.usgs.gov/ws/secure/metadata/{id} "PUT" endpoint (defined in geomagio/api/secure/metadata.py) calls MetadataDatabaseFactory.update_metadata(), which copies the old record to a history table, and overwrites the {id} record in the main metadata table.

HOWEVER, if a user attempts to do this by passing a GITLAB_API_TOKEN, and not logging in (for example, running a script to automatically update data), a "PUT" request always returns a 403 response ("Forbidden"), and does not actually update the database. The token is seemingly valid, because a "POST" request, used to create new metadata, is always successful.

The following is a minimal sequence of interactive python commands that can be used to reproduce the issue if the geomag-algorithms project has been properly installed:

from geomagio.metadata import Metadata, MetadataCategory, MetadataFactory, MetadataQuery

factory = MetadataFactory(url="https://staging-geomag.cr.usgs.gov/ws/secure/metadata", token="a-valid-gitlab-token")

# prints out new metadata json...use id# for subsequent call
factory.create_metadata(Metadata(station="BDT", category=MetadataCategory.FLAG, comment="test flag"))
#Metadata(id={id}, metadata_id=None, created_by=None, created_time=UTCDateTime(2024, 4, 2, 19, 46, 54), updated_by=None, updated_time=None, starttime=None, endtime=None, network=None, station='BDT', channel=None, location=None, category=<MetadataCategory.FLAG: 'flag'>, priority=1, data_valid=True, metadata=None, comment='test flag', review_comment=None, status='new')

# retrieve metadata (using id printed previously)
metadata = factory.get_metadata_by_id(id={id})
# modify metadata
metadata.review_comment = "reviewed flag"

# update metadata; prints out updated metadata json...
factory.update_metadata(metadata)
# Metadata(id=None, metadata_id=None, created_by=None, created_time=None, updated_by=None, updated_time=None, starttime=None, endtime=None, network=None, station=None, channel=None, location=None, category=None, priority=1, data_valid=True, metadata=None, comment=None, review_comment=None, status=None)

The updated_metadata is all default values, and if one retrieves it again, it can be seen that the changes were not applied.

Also, identical results were obtained using the production service at https://geomag.usgs.gov/ws/secure/metadata. So, this does not seem to be specific to the staging server.

Finally, this worked as intended once-upon-a-time, since a demo Jupyter notebook left by Payton Cain shows output that is not just the default metadata.

Please comment below if you have any suggestions, or corrections to this description.

Looping in @ehunter, @awernle, @bgeels, and @nshavers.

Edited by Erin (Josh) Rigler