Skip to content

Commit

Permalink
feat(examples): add authentication examples and refactor existing exa…
Browse files Browse the repository at this point in the history
…mples

Add a new file `auth_examples.py` to demonstrate various authentication
methods using the Otf API. Refactor existing example files to use the
`OtfUser` class for authentication, improving code consistency and
readability. This change provides a more structured approach to
authentication and aligns with the new authentication examples.
  • Loading branch information
NodeJSmith committed Jan 5, 2025
1 parent f0a1fd5 commit 8463f35
Show file tree
Hide file tree
Showing 5 changed files with 503 additions and 422 deletions.
76 changes: 76 additions & 0 deletions examples/auth_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os
from getpass import getpass

from otf_api import Otf, OtfAuth, OtfAuthConfig, OtfUser

USERNAME = os.getenv("OTF_EMAIL") or input("Enter your OTF email: ")
PASSWORD = os.getenv("OTF_PASSWORD") or getpass("Enter your OTF password: ")


def main():
"""
OtfAuthConfig provides three options currently:
- cache_device_data: bool - Whether to register/cache device data with AWS Cognito
I'm not sure if there is any benefit to this at this point, but in general this is used to allow skipping MFA
- cache_tokens_plaintext: bool - Whether to cache the tokens in plaintext in the config file - this is an obvious
security risk, but it's useful for development purposes. If you want to do this, it is at your own risk. The
benefit is that after you log in with your username/password once, you can use the cached tokens to log in
without providing them again.
"""

# This is the most configurable way to access the API but also the most verbose

auth_config = OtfAuthConfig(cache_device_data=True, cache_tokens_plaintext=True)

auth = OtfAuth.create(USERNAME, PASSWORD, config=auth_config)
user = OtfUser(auth=auth)
print(user.otf_auth.auth_type)

# You can also use `login` to log in with a username and password, with the config being optional
user = OtfUser.login(USERNAME, PASSWORD, config=auth_config)
print(user.otf_auth.auth_type)

# If you have tokens available you can provide them using `from_tokens` instead of `login`

user = OtfUser.from_tokens(
user.cognito.access_token, user.cognito.id_token, user.cognito.refresh_token, config=auth_config
)
print(user.otf_auth.auth_type)

# Likewise, if you have a Cognito instance you can provide that as well

user = OtfUser.from_cognito(cognito=user.cognito, config=auth_config)
print(user.otf_auth.auth_type)

# If you have already logged in and you cached your tokens, you can use `from_cache` to create a user object
# without providing any tokens

user = OtfUser.from_cache(config=auth_config)
print(user.otf_auth.auth_type)

# if you want to clear the cached tokens, you can use `clear_cached_tokens`
# if you want to clear the cached device data, you can use `clear_cached_device_data`
# if you want to clear both, you can use `clear_cache`
user.clear_cached_tokens()
user.clear_cached_device_data()
user.clear_cache()

# now if we tried to log in from cache, it would raise a ValueError
try:
user = OtfUser.from_cache(config=auth_config)
except ValueError as e:
print(e)

# to instantiate an Otf instance, you can provide either a user object or an auth object

# if you provide a user then authenticate doesn't need to be called
otf_from_user = Otf(user=user)
print(otf_from_user.member_uuid)

# whereas if you provide an auth object, authenticate will be called
otf_from_auth = Otf(auth=auth)
print(otf_from_auth.member_uuid)


if __name__ == "__main__":
main()
173 changes: 87 additions & 86 deletions examples/challenge_tracker_examples.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,25 @@
import os
from getpass import getpass

from otf_api import Otf
from otf_api import Otf, OtfUser
from otf_api.models import ChallengeType, EquipmentType

USERNAME = os.getenv("OTF_EMAIL") or input("Enter your OTF email: ")
PASSWORD = os.getenv("OTF_PASSWORD") or getpass("Enter your OTF password: ")


def main():
with Otf(USERNAME, PASSWORD) as otf:
# challenge tracker content is an overview of the challenges OTF runs
# and your participation in them
challenge_tracker_content = otf.get_challenge_tracker_content()
print(challenge_tracker_content.benchmarks[0].model_dump_json(indent=4))
user = OtfUser.login(USERNAME, PASSWORD)
otf = Otf(user=user)
# challenge tracker content is an overview of the challenges OTF runs
# and your participation in them
challenge_tracker_content = otf.get_challenge_tracker_content()
print(challenge_tracker_content.benchmarks[0].model_dump_json(indent=4))

"""
{
"equipment_id": 2,
"equipment_name": "Treadmill",
"years": [
{
"year": "2024",
"is_participated": false,
"in_progress": false
},
...
],
"logo_url": "https://otf-icons.s3.amazonaws.com/benchmarks/Treadmill.png"
}
"""

print(challenge_tracker_content.challenges[0].model_dump_json(indent=4))
"""
{
"challenge_category_id": 10,
"challenge_sub_category_id": 8,
"challenge_name": "Catch Me If You Can 3G",
"""
{
"equipment_id": 2,
"equipment_name": "Treadmill",
"years": [
{
"year": "2024",
Expand All @@ -45,67 +28,85 @@ def main():
},
...
],
"logo_url": "https://otf-icons.s3.amazonaws.com/challenges/CatchMeIfYouCan.png"
}
"""

# challenge tracker details are detailed information about specific challenges
# this endpoint takes an equipment type and a challenge type as arguments
tread_challenge_details = otf.get_challenge_tracker_detail(EquipmentType.Treadmill, ChallengeType.Other)
print(tread_challenge_details.details[0].model_dump_json(indent=4))
"logo_url": "https://otf-icons.s3.amazonaws.com/benchmarks/Treadmill.png"
}
"""

"""
print(challenge_tracker_content.challenges[0].model_dump_json(indent=4))
"""
{
"challenge_category_id": 10,
"challenge_sub_category_id": 8,
"challenge_name": "Catch Me If You Can 3G",
"years": [
{
"challenge_category_id": 10,
"challenge_sub_category_id": null,
"year": "2024",
"is_participated": false,
"in_progress": false
},
...
],
"logo_url": "https://otf-icons.s3.amazonaws.com/challenges/CatchMeIfYouCan.png"
}
"""

# challenge tracker details are detailed information about specific challenges
# this endpoint takes an equipment type and a challenge type as arguments
tread_challenge_details = otf.get_challenge_tracker_detail(EquipmentType.Treadmill, ChallengeType.Other)
print(tread_challenge_details.details[0].model_dump_json(indent=4))

"""
{
"challenge_category_id": 10,
"challenge_sub_category_id": null,
"equipment_id": 2,
"equipment_name": "Treadmill",
"metric_entry": {
"title": "22 MIN",
"equipment_id": 2,
"equipment_name": "Treadmill",
"metric_entry": {
"title": "22 MIN",
"equipment_id": 2,
"entry_type": "Distance",
"metric_key": "22MIN",
"min_value": "0.16093440000000003",
"max_value": "8.04672"
},
"challenge_name": "Catch me If You Can",
"logo_url": "https://otf-icons.s3.amazonaws.com/challenges/CatchMeIfYouCan.png",
"best_record": 1.40012928,
"last_record": 1.40012928,
"previous_record": 1.40012928,
"unit": "km",
"goals": null,
"challenge_histories": [
{
"challenge_objective": "None",
"challenge_id": 449906,
"studio_id": 1267,
"studio_name": "AnyTown OH - East",
"start_date": "2024-02-06 00:00:00",
"end_date": "2024-02-06 23:59:00",
"total_result": 1.40012928,
"is_finished": true,
"benchmark_histories": [
{
"studio_name": "AnyTown OH - East",
"equipment_id": 2,
"result": 1.40012928,
"date_created": "2024-02-06 16:01:26",
"date_updated": "2024-02-06 16:01:26",
"class_time": "2024-02-06 09:45:00",
"challenge_sub_category_id": null,
"class_id": 86842386,
"substitute_id": 1,
"weight_lbs": 0,
"workout_type_id": null,
"workout_id": null,
"linked_challenges": []
}
]
}
]
}
"""
"entry_type": "Distance",
"metric_key": "22MIN",
"min_value": "0.16093440000000003",
"max_value": "8.04672"
},
"challenge_name": "Catch me If You Can",
"logo_url": "https://otf-icons.s3.amazonaws.com/challenges/CatchMeIfYouCan.png",
"best_record": 1.40012928,
"last_record": 1.40012928,
"previous_record": 1.40012928,
"unit": "km",
"goals": null,
"challenge_histories": [
{
"challenge_objective": "None",
"challenge_id": 449906,
"studio_id": 1267,
"studio_name": "AnyTown OH - East",
"start_date": "2024-02-06 00:00:00",
"end_date": "2024-02-06 23:59:00",
"total_result": 1.40012928,
"is_finished": true,
"benchmark_histories": [
{
"studio_name": "AnyTown OH - East",
"equipment_id": 2,
"result": 1.40012928,
"date_created": "2024-02-06 16:01:26",
"date_updated": "2024-02-06 16:01:26",
"class_time": "2024-02-06 09:45:00",
"challenge_sub_category_id": null,
"class_id": 86842386,
"substitute_id": 1,
"weight_lbs": 0,
"workout_type_id": null,
"workout_id": null,
"linked_challenges": []
}
]
}
]
}
"""


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit 8463f35

Please sign in to comment.