Skip to content

Commit

Permalink
Support API v2 endpoint for refreshing auth token
Browse files Browse the repository at this point in the history
The token will be regenerated and a new expiration date will be set, so
it is necessary to rebuild the client with the new token afterwards.
This is documented in the README and as a doc string on the
`refresh_token` client method.
  • Loading branch information
hmpf committed Dec 10, 2024
1 parent 293b72e commit c64e4ce
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@ stateless_incident = Incident(
)
```


### Get a new authentication token

If your argus server is running version 1.29.0 or newer you can request to get
a new token (with a new expiration date) via API version 2. The token you are
using to access the server with must still be valid.

```python
tokenobj = c.refresh_token()
c = Client(api_root_url="https://argus.example.org/api/v2", token=tokenobj.token)
# save the contents of tokenobj in an environment variable, config file or
# secrets file so that it is not lost on program exit
```

## BUGS

* Doesn't provide high-level error handling yet.
7 changes: 7 additions & 0 deletions src/pyargus/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def connect(api_root_url: str, token: str, timeout: float = 2.0) -> API:
argusapi.add_resource(
resource_name="acknowledgements", resource_class=IncidentAcknowledgementResource
)
argusapi.add_resource(resource_name="tokens", resource_class=ExpiringTokenResource)
return argusapi


Expand Down Expand Up @@ -51,3 +52,9 @@ class IncidentAcknowledgementResource(Resource):
"create": {"method": "POST", "url": "incidents/{}/acks"},
"retrieve": {"method": "GET", "url": "incidents/{}/acks/{}"},
}


class ExpiringTokenResource(Resource):
actions = {
"refresh": {"method": "POST", "url": "auth/token/login/"},
}
13 changes: 13 additions & 0 deletions src/pyargus/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,19 @@ def post_incident_event(self, incident: IncidentType, event: models.Event):
response = self.api.events.create(incident_pk, body=body)
return models.Event.from_json(response.body)

def refresh_token(self) -> models.ExpiringToken:
"""Post w/o body to get a new token and its expiration timestamp
It will be necessary to re-initialize the client as the old token has
been rendered invalid.
Store the new token (and the returned expiration datetime) where your
program can load it on next run: environment variable, config file or
secrets file.
"""
response = self.api.tokens.refresh()
return models.ExpiringToken.from_json(response.body)


def paginated_query(method: Callable, *args, **kwargs) -> Iterator[Tuple]:
"""Extracts paginated results from a simple_rest_client API call.
Expand Down
16 changes: 16 additions & 0 deletions src/pyargus/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,19 @@ def from_json(cls, data: dict) -> Acknowledgement:
else None,
}
return cls(**kwargs)


@dataclass
class ExpiringToken:
"""Class for describing the authentication token"""

expiration: datetime
token: int

@classmethod
def from_json(cls, data: dict) -> ExpiringToken:
kwargs = {
"expiration": parse_date(data["expiration"]),
"token": parse_date(data["token"]),
}
return cls(**kwargs)

0 comments on commit c64e4ce

Please sign in to comment.