|
1 | 1 | #!/usr/bin/env python3 |
2 | | -import argparse |
3 | 2 | import os |
4 | 3 |
|
5 | | -from oauth2client import client, tools |
6 | | -from oauth2client.file import Storage |
7 | | - |
8 | | -flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args() |
| 4 | +from google.auth.transport.requests import Request |
| 5 | +from google.oauth2.credentials import Credentials |
| 6 | +from google_auth_oauthlib.flow import InstalledAppFlow |
9 | 7 |
|
10 | 8 | # If modifying these scopes, delete your previously saved credentials |
11 | 9 | # at zulip/bots/gcal/ |
12 | 10 | # NOTE: When adding more scopes, add them after the previous one in the same field, with a space |
13 | 11 | # seperating them. |
14 | | -SCOPES = "https://www.googleapis.com/auth/calendar.readonly" |
| 12 | +SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"] |
15 | 13 | # This file contains the information that google uses to figure out which application is requesting |
16 | 14 | # this client's data. |
17 | 15 | CLIENT_SECRET_FILE = "client_secret.json" # noqa: S105 |
18 | | -APPLICATION_NAME = "Zulip Calendar Bot" |
19 | 16 | HOME_DIR = os.path.expanduser("~") |
20 | 17 |
|
21 | 18 |
|
22 | | -def get_credentials() -> client.Credentials: |
23 | | - """Gets valid user credentials from storage. |
| 19 | +def get_credentials() -> Credentials: |
| 20 | + """ |
| 21 | + Writes google tokens to a json file, using the client secret file (for the OAuth flow), |
| 22 | + and the refresh token. |
| 23 | +
|
| 24 | + If the tokens file exists and is valid, nothing needs to be done. |
| 25 | + If the tokens file exists, but the auth token is expired (expiry duration of auth token |
| 26 | + is 1 hour), the refresh token is used to get a new token. |
| 27 | + If the tokens file does not exist, or is invalid, the OAuth2 flow is triggered. |
24 | 28 |
|
25 | | - If nothing has been stored, or if the stored credentials are invalid, |
26 | | - the OAuth2 flow is completed to obtain the new credentials. |
| 29 | + The OAuth2 flow needs the client secret file, and requires the user to grant access to |
| 30 | + the application via a browser authorization page, for the first run. |
27 | 31 |
|
28 | | - Returns: |
29 | | - Credentials, the obtained credential. |
| 32 | + The fetched tokens are written to storage in a json file, for reference by other scripts. |
30 | 33 | """ |
31 | 34 |
|
| 35 | + creds = None |
32 | 36 | credential_path = os.path.join(HOME_DIR, "google-credentials.json") |
33 | 37 |
|
34 | | - store = Storage(credential_path) |
35 | | - credentials = store.get() |
36 | | - if not credentials or credentials.invalid: |
37 | | - flow = client.flow_from_clientsecrets(os.path.join(HOME_DIR, CLIENT_SECRET_FILE), SCOPES) |
38 | | - flow.user_agent = APPLICATION_NAME |
39 | | - # This attempts to open an authorization page in the default web browser, and asks the user |
40 | | - # to grant the bot access to their data. If the user grants permission, the run_flow() |
41 | | - # function returns new credentials. |
42 | | - credentials = tools.run_flow(flow, store, flags) |
43 | | - print("Storing credentials to " + credential_path) |
| 38 | + if os.path.exists(credential_path): |
| 39 | + creds = Credentials.from_authorized_user_file(credential_path, SCOPES) |
| 40 | + if not creds or not creds.valid: |
| 41 | + if creds and creds.expired and creds.refresh_token: |
| 42 | + creds.refresh(Request()) |
| 43 | + else: |
| 44 | + flow = InstalledAppFlow.from_client_secrets_file( |
| 45 | + os.path.join(HOME_DIR, CLIENT_SECRET_FILE), SCOPES |
| 46 | + ) |
| 47 | + creds = flow.run_local_server(port=0) |
| 48 | + with open(credential_path, "w") as token: |
| 49 | + token.write(creds.to_json()) |
| 50 | + return creds |
44 | 51 |
|
45 | 52 |
|
46 | 53 | get_credentials() |
0 commit comments