Repository navigation
Expand file tree
/
Copy pathcli_auth.py
More file actions
158 lines (137 loc) · 5.23 KB
/
Copy pathcli_auth.py
File metadata and controls
158 lines (137 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env python3
"""
CLI tool for Google sign-in for the Submission Uploader.
End users run `python cli_auth.py setup` — no Google Cloud Console steps required.
"""
import argparse
import os
import sys
import json
from google_auth import APP_NAME, DEFAULT_SCOPES, authorize, load_credentials, oauth_client_configured
# Set console encoding to UTF-8 to handle Unicode characters
if sys.platform == 'win32':
import codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')
sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, 'strict')
def load_config(config_file='config.json'):
"""Load configuration from JSON file."""
try:
with open(config_file, 'r') as f:
return json.load(f)
except FileNotFoundError:
print(f"Configuration file '{config_file}' not found.")
print("Please create a config.json file or copy from config.sample.json")
return None
except json.JSONDecodeError:
print(f"Invalid JSON in configuration file '{config_file}'.")
return None
def auth_settings(config):
authentication = config.get('authentication', {})
return {
'token_file': authentication.get('token_file', 'token.json'),
'scopes': authentication.get('scopes', DEFAULT_SCOPES),
'oauth_client_path': authentication.get('oauth_client_file'),
}
def generate_token(config):
"""Run Google sign-in and save the user's token."""
settings = auth_settings(config)
if not oauth_client_configured(settings['oauth_client_path']):
print(f"✗ {APP_NAME} is missing its OAuth client configuration.")
print(" If you received this app from someone else, ask them for an updated build.")
print(" If you are building the app, copy oauth_client.sample.json to oauth_client.json")
print(" and fill in your Desktop app OAuth client from Google Cloud Console.")
return False
try:
print("Starting Google sign-in...")
authorize(
settings['token_file'],
settings['scopes'],
settings['oauth_client_path'],
)
print("✓ Google account connected!")
print(f"✓ Session saved to '{settings['token_file']}'")
return True
except Exception as e:
print(f"✗ Sign-in failed: {str(e)}")
return False
def check_token_status(config):
"""Check the status of the saved Google session."""
settings = auth_settings(config)
token_file = settings['token_file']
scopes = settings['scopes']
if not oauth_client_configured(settings['oauth_client_path']):
print(f"✗ {APP_NAME} is missing its OAuth client configuration.")
return False
if not os.path.exists(token_file):
print(f"✗ No saved sign-in found ('{token_file}').")
return False
try:
creds = load_credentials(token_file, scopes)
if creds:
print("✓ Google account connected and ready to use.")
return True
print("✗ Saved sign-in expired. Run: python cli_auth.py setup")
return False
except Exception as e:
print(f"✗ Error checking sign-in: {e}")
return False
def print_usage():
"""Print usage instructions."""
print(f"{APP_NAME} — Google Sign-In")
print("=" * 40)
print()
print("Usage:")
print(" python cli_auth.py [command]")
print()
print("Commands:")
print(" setup - Sign in with Google (opens browser)")
print(" check - Check whether you are signed in")
print(" help - Show this help message")
print()
print("No Google Cloud project setup is required for end users.")
print("Just run setup and approve access in your browser.")
def parse_args():
parser = argparse.ArgumentParser(description="Sign in to Google for Submission Uploader")
parser.add_argument('command', nargs='?', choices=('setup', 'check', 'help'), default='help')
return parser.parse_args()
def main():
args = parse_args()
command = args.command.lower()
if command == 'help':
print_usage()
return
config = load_config()
if not config:
if command != 'setup' or os.path.exists('config.json'):
return
config = {
'authentication': {
'scopes': DEFAULT_SCOPES,
'token_file': 'token.json',
}
}
if command == 'setup':
print(f"Setting up Google sign-in for {APP_NAME}...")
print("Your browser will open so you can approve access.")
print()
if generate_token(config):
print()
print("Setup complete! You can now use the command-line uploader:")
print("python uploader.py /path/to/submissions/folder")
else:
print()
print("Setup failed. Please check the error messages above.")
sys.exit(1)
elif command == 'check':
print("Checking Google sign-in status...")
if check_token_status(config):
print("Ready for command-line usage.")
else:
print("Sign-in required. Run: python cli_auth.py setup")
sys.exit(1)
else:
print(f"Unknown command: {command}")
print_usage()
sys.exit(1)
if __name__ == '__main__':
main()