microsoft-todo-cli 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,136 @@
1
+ # Oauth settings
2
+ import json
3
+ import os
4
+ import sys
5
+ import time
6
+
7
+ import yaml
8
+ from requests_oauthlib import OAuth2Session
9
+
10
+ settings = {
11
+ "redirect": "https://localhost/login/authorized",
12
+ "scopes": "openid offline_access tasks.readwrite",
13
+ "authority": "https://login.microsoftonline.com/common",
14
+ "authorize_endpoint": "/oauth2/v2.0/authorize",
15
+ "token_endpoint": "/oauth2/v2.0/token",
16
+ }
17
+
18
+ # Code taken from https://docs.microsoft.com/en-us/graph/tutorials/python?tutorial-step=3
19
+
20
+ # This is necessary because Azure does not guarantee
21
+ # to return scopes in the same case and order as requested
22
+ os.environ["OAUTHLIB_RELAX_TOKEN_SCOPE"] = "1"
23
+ os.environ["OAUTHLIB_IGNORE_SCOPE_CHANGE"] = "1"
24
+
25
+ redirect = settings["redirect"]
26
+ scope = settings["scopes"]
27
+
28
+ authorize_url = "{0}{1}".format(settings["authority"], settings["authorize_endpoint"])
29
+ token_url = "{0}{1}".format(settings["authority"], settings["token_endpoint"])
30
+
31
+ # User settings location
32
+ config_dir = "{}/.config/tod0".format(os.path.expanduser("~"))
33
+ if not os.path.isdir(config_dir):
34
+ os.makedirs(config_dir)
35
+
36
+
37
+ def check_keys(keys):
38
+ client_id = keys.get("client_id", "")
39
+ client_secret = keys.get("client_secret", "")
40
+
41
+ if not client_id or not client_secret:
42
+ print(
43
+ "Please enter your client id and secret in {}".format(
44
+ os.path.join(config_dir, "keys.yml")
45
+ )
46
+ )
47
+ print(
48
+ "Instructions to getting your API client id and secret can be found here:\n{}".format(
49
+ "https://github.com/underwear/microsoft-todo-cli/blob/main/docs/setup-api.md"
50
+ )
51
+ )
52
+ sys.exit(1)
53
+
54
+
55
+ # Check for api keys
56
+ keys_path = os.path.join(config_dir, "keys.yml")
57
+ if not os.path.isfile(keys_path):
58
+ keys = {"client_id": "", "client_secret": ""}
59
+
60
+ with open(keys_path, "w") as f:
61
+ yaml.dump(keys, f)
62
+ check_keys(keys)
63
+ else:
64
+ # Load api keys
65
+ with open(keys_path) as f:
66
+ keys = yaml.load(f, yaml.SafeLoader) or {}
67
+ check_keys(keys)
68
+
69
+ client_id = keys["client_id"]
70
+ client_secret = keys["client_secret"]
71
+
72
+ TOKEN_FILE = os.path.join(config_dir, "token.json")
73
+
74
+
75
+ def get_token():
76
+ token = None
77
+
78
+ # Try to load token from local
79
+ if os.path.isfile(TOKEN_FILE):
80
+ try:
81
+ with open(TOKEN_FILE, "r") as f:
82
+ token = json.load(f)
83
+ token = refresh_token(token)
84
+ except (json.JSONDecodeError, KeyError, OSError):
85
+ token = None
86
+
87
+ if token is None:
88
+ # Authorize user to get token
89
+ outlook = OAuth2Session(client_id, scope=scope, redirect_uri=redirect)
90
+
91
+ # Redirect the user owner to the OAuth provider
92
+ authorization_url, state = outlook.authorization_url(authorize_url)
93
+ print("Please go here and authorize:\n", authorization_url)
94
+
95
+ # Get the authorization verifier code from the callback url
96
+ redirect_response = input("Paste the full redirect URL below:\n")
97
+
98
+ # Fetch the access token
99
+ token = outlook.fetch_token(
100
+ token_url,
101
+ client_secret=client_secret,
102
+ authorization_response=redirect_response,
103
+ )
104
+
105
+ store_token(token)
106
+ return token
107
+
108
+
109
+ def store_token(token):
110
+ with open(TOKEN_FILE, "w") as f:
111
+ json.dump(token, f)
112
+
113
+
114
+ def refresh_token(token):
115
+ # Check expiration
116
+ now = time.time()
117
+ # Subtract 5 minutes from expiration to account for clock skew
118
+ expire_time = token["expires_at"] - 300
119
+ if now >= expire_time:
120
+ # Refresh the token
121
+ aad_auth = OAuth2Session(
122
+ client_id, token=token, scope=scope, redirect_uri=redirect
123
+ )
124
+
125
+ refresh_params = {"client_id": client_id, "client_secret": client_secret}
126
+
127
+ new_token = aad_auth.refresh_token(token_url, **refresh_params)
128
+ return new_token
129
+
130
+ # Token still valid, just return it
131
+ return token
132
+
133
+
134
+ def get_oauth_session():
135
+ token = get_token()
136
+ return OAuth2Session(client_id, scope=scope, token=token)