Skip to content

Commit 5ff617f

Browse files
committed
Token error
1 parent 816dae7 commit 5ff617f

2 files changed

Lines changed: 186 additions & 116 deletions

File tree

meta_creator/metadata_extractor.py

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,55 +31,33 @@ def data_extraction(request):
3131
repo_url = request.POST.get('repo_url')
3232
personal_token_key = request.POST.get('personal_token_key')
3333

34-
valid_token = validate_token(repo_url, personal_token_key)
35-
36-
if not is_github_repo(repo_url) and not valid_token:
37-
result = {
38-
'success': False,
39-
'errors': "GitLab requires a valid personal access token."
40-
}
41-
else:
42-
token = valid_token # could be None for GitHub
34+
token_result = validate_token(repo_url, personal_token_key)
4335

44-
# Define empty result dict
45-
result = {
46-
'success': True,
47-
'warnings': [],
48-
'errors': [],
49-
'metadata': None
36+
if token_result["error_type"]:
37+
return {
38+
"success": False,
39+
"errors": token_result["error_message"],
5040
}
5141

52-
# # Validate GitHub input
53-
# is_valid_github, error_messages = validate_github_inputs(gl_url)
54-
# if not is_valid_github:
55-
# is_valid_gitlab, error_messages_gitlab = validate_gitlab_inputs(gl_url, personal_token_key)
42+
token = token_result["token"] # could be None for GitHub public repos
5643

57-
# if not is_valid_gitlab:
58-
# error_messages.join(error_messages_gitlab)
59-
# return {
60-
# 'success': False,
61-
# 'errors': error_messages
62-
# }
44+
result = {
45+
'success': True,
46+
'warnings': [],
47+
'errors': [],
48+
'metadata': None
49+
}
6350

64-
# extracted_metadata = get_gitlab_metadata(gl_url, personal_token_key)
65-
# if not extracted_metadata:
66-
# extracted_metadata = get_gitlab_metadata(gl_url, default_access_token_gitlab)
51+
# Run HERMES process
52+
hermes_metadata = run_hermes_commands(repo_url, token)
6753

68-
# result['metadata'] = init_curated_metadata(extracted_metadata)
69-
70-
71-
# Run HERMES process
72-
hermes_metadata = run_hermes_commands(repo_url, token)
73-
# if hermes_metadata == None:
74-
# hermes_metadata = get_github_metadata(gl_url, default_access_token_GH)
54+
if isinstance(hermes_metadata, dict):
55+
result['metadata'] = init_curated_metadata(hermes_metadata.get('metadata'))
56+
result['warnings'].extend(hermes_metadata.get('warnings', []))
57+
result['errors'].extend(hermes_metadata.get('errors', []))
58+
result['success'] = hermes_metadata.get('success', False)
59+
else:
60+
result['success'] = False
61+
result['errors'].append("HERMES returned unexpected result format.")
7562

76-
if isinstance(hermes_metadata, dict):
77-
result['metadata'] = init_curated_metadata(hermes_metadata.get('metadata'))
78-
result['warnings'].extend(hermes_metadata.get('warnings', []))
79-
result['errors'].extend(hermes_metadata.get('errors', []))
80-
result['success'] = hermes_metadata.get('success', False)
81-
else:
82-
result['success'] = False
83-
result['errors'].append("HERMES returned unexpected result format.")
84-
8563
return result

meta_creator/token_check.py

Lines changed: 164 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,6 @@
33
import os
44

55
def load_tokens_from_file(file_path="tokens.txt"):
6-
"""
7-
Loads tokens from a JSON-formatted text file.
8-
9-
Args:
10-
file_path (str): Path to the token file. Defaults to 'tokens.txt'.
11-
12-
Returns:
13-
dict: A dictionary containing tokens if the file exists and is valid JSON,
14-
otherwise an empty dictionary.
15-
"""
166
if not os.path.exists(file_path):
177
return {}
188
with open(file_path, "r") as f:
@@ -23,94 +13,196 @@ def load_tokens_from_file(file_path="tokens.txt"):
2313

2414

2515
def is_github_repo(url):
26-
"""
27-
Checks if a given URL points to a GitHub repository.
28-
29-
Args:
30-
url (str): The repository URL.
31-
32-
Returns:
33-
bool: True if the URL contains 'github', otherwise False.
34-
"""
3516
return "github" in url
3617

3718

38-
3919
def check_github_token(repo_url, token):
4020
"""
41-
Validates a GitHub token by sending a request to the GitHub API for the repository.
42-
43-
Args:
44-
repo_url (str): The GitHub repository URL.
45-
token (str): The GitHub token to validate.
21+
Validates a GitHub token and URL against the GitHub API.
4622
4723
Returns:
48-
bool: True if the token is valid (status code 200), otherwise False.
24+
dict with keys 'status' and 'message'.
25+
status values: 'valid', 'invalid_token', 'expired_token', 'invalid_url', 'error'
4926
"""
50-
api_url = repo_url.replace("github.com", "api.github.com/repos")
51-
headers = {"Authorization": f"token {token}"}
52-
response = requests.get(api_url, headers=headers)
53-
return response.status_code == 200
27+
api_url = repo_url.replace("github.com", "api.github.com/repos").rstrip("/")
28+
headers = {"Authorization": f"token {token}"} if token else {}
29+
30+
try:
31+
response = requests.get(api_url, headers=headers)
32+
except requests.RequestException as e:
33+
return {"status": "error", "message": f"Network error while reaching GitHub: {str(e)}"}
34+
35+
if response.status_code == 200:
36+
return {"status": "valid", "message": ""}
37+
38+
if response.status_code == 401:
39+
try:
40+
msg = response.json().get("message", "")
41+
if "expired" in msg.lower():
42+
return {
43+
"status": "expired_token",
44+
"message": "The GitHub token has expired. Please generate a new token and try again.",
45+
}
46+
except Exception:
47+
pass
48+
return {
49+
"status": "invalid_token",
50+
"message": "The provided GitHub token is invalid. Please check your token and try again.",
51+
}
52+
53+
if response.status_code == 404:
54+
return {
55+
"status": "invalid_url",
56+
"message": "GitHub repository not found. Please check the URL and try again.",
57+
}
58+
59+
if response.status_code == 403:
60+
return {
61+
"status": "error",
62+
"message": "Access to GitHub is forbidden. You may have exceeded the API rate limit.",
63+
}
64+
65+
return {
66+
"status": "error",
67+
"message": f"Unexpected response from GitHub API (HTTP {response.status_code}).",
68+
}
5469

5570

5671
def check_gitlab_token(repo_url, token):
5772
"""
58-
Validates a GitLab token by sending a request to the GitLab API for the repository.
59-
60-
Args:
61-
repo_url (str): The GitLab repository URL.
62-
token (str): The GitLab token to validate.
73+
Validates a GitLab token and URL against the GitLab API.
6374
6475
Returns:
65-
bool: True if the token is valid (status code 200), otherwise False.
76+
dict with keys 'status' and 'message'.
77+
status values: 'valid', 'invalid_token', 'expired_token', 'invalid_url', 'error'
6678
"""
6779
try:
6880
project_path = repo_url.split("gitlab.com/")[1].rstrip("/").replace("/", "%2F")
6981
api_url = f"https://gitlab.com/api/v4/projects/{project_path}"
7082
except IndexError:
71-
return False
72-
headers = {"PRIVATE-TOKEN": token}
73-
response = requests.get(api_url, headers=headers)
74-
return response.status_code == 200
83+
return {"status": "invalid_url", "message": "Invalid GitLab repository URL format."}
7584

85+
headers = {"PRIVATE-TOKEN": token} if token else {}
7686

77-
def validate_token(repo_url, token):
78-
"""
79-
Validates the given token or falls back to a stored token from file based on the repo type.
87+
try:
88+
response = requests.get(api_url, headers=headers)
89+
except requests.RequestException as e:
90+
return {"status": "error", "message": f"Network error while reaching GitLab: {str(e)}"}
91+
92+
if response.status_code == 200:
93+
return {"status": "valid", "message": ""}
8094

81-
For GitHub:
82-
- Uses the provided token if valid.
83-
- Otherwise, uses a fallback GitHub token from file if available and valid.
84-
- Returns None if no token is valid, but this is acceptable for GitHub.
95+
if response.status_code == 401:
96+
try:
97+
body = response.json()
98+
# GitLab returns {"error": "invalid_token", "error_description": "Token is expired..."}
99+
error_desc = body.get("error_description", "") or body.get("message", "")
100+
if "expired" in error_desc.lower():
101+
return {
102+
"status": "expired_token",
103+
"message": "The GitLab token has expired. Please generate a new token and try again.",
104+
}
105+
except Exception:
106+
pass
107+
return {
108+
"status": "invalid_token",
109+
"message": "The provided GitLab token is invalid. Please check your token and try again.",
110+
}
111+
112+
if response.status_code == 404:
113+
return {
114+
"status": "invalid_url",
115+
"message": "GitLab repository not found. Please check the URL and try again.",
116+
}
117+
118+
if response.status_code == 403:
119+
return {
120+
"status": "error",
121+
"message": "Access to the GitLab repository is forbidden.",
122+
}
123+
124+
return {
125+
"status": "error",
126+
"message": f"Unexpected response from GitLab API (HTTP {response.status_code}).",
127+
}
85128

86-
For GitLab:
87-
- Uses the provided token if valid.
88-
- Otherwise, uses a fallback GitLab token from file if available and valid.
89-
- Returns None if no valid token is available (required for GitLab).
90129

91-
Args:
92-
repo_url (str): The repository URL.
93-
token (str): The optional token provided for authentication.
130+
def validate_token(repo_url, token):
131+
"""
132+
Validates the given token (or a fallback from file) for the given repository URL.
94133
95134
Returns:
96-
str or None: A valid token if available and valid, otherwise None.
135+
dict: {
136+
'token': str or None — the valid token to use for subsequent requests,
137+
'error_type': str or None — one of 'invalid_token', 'expired_token',
138+
'invalid_url', 'no_token', 'error',
139+
'error_message': str or None — human-readable error for the user,
140+
}
97141
"""
98142
tokens_from_file = load_tokens_from_file()
99-
143+
100144
if is_github_repo(repo_url):
101-
if token and check_github_token(repo_url, token):
102-
return token # Valid provided token
103-
fallback_token = tokens_from_file.get("github_token")
104-
if fallback_token and check_github_token(repo_url, fallback_token):
105-
return fallback_token # Valid fallback token
106-
return None # No token available but OK for GitHub
107-
108-
elif not is_github_repo(repo_url):
109-
if token and check_gitlab_token(repo_url, token):
110-
return token # Valid provided token
111-
fallback_token = tokens_from_file.get("gitlab_token")
112-
if fallback_token and check_gitlab_token(repo_url, fallback_token):
113-
return fallback_token # Valid fallback token
114-
return None # Not okay for GitLab
115-
116-
return None
145+
if token:
146+
result = check_github_token(repo_url, token)
147+
if result["status"] == "valid":
148+
return {"token": token, "error_type": None, "error_message": None}
149+
150+
# For a token-specific error, try the fallback before surfacing to the user
151+
if result["status"] in ("invalid_token", "expired_token"):
152+
fallback = tokens_from_file.get("github_token")
153+
if fallback and fallback != token:
154+
fb_result = check_github_token(repo_url, fallback)
155+
if fb_result["status"] == "valid":
156+
return {"token": fallback, "error_type": None, "error_message": None}
157+
# Surface the original user-token error
158+
return {"token": None, "error_type": result["status"], "error_message": result["message"]}
159+
160+
# URL invalid or other error — return immediately
161+
return {"token": None, "error_type": result["status"], "error_message": result["message"]}
162+
163+
# No token provided — try fallback, then proceed without auth (public repos)
164+
fallback = tokens_from_file.get("github_token")
165+
if fallback:
166+
fb_result = check_github_token(repo_url, fallback)
167+
if fb_result["status"] == "valid":
168+
return {"token": fallback, "error_type": None, "error_message": None}
169+
if fb_result["status"] == "invalid_url":
170+
return {"token": None, "error_type": "invalid_url", "error_message": fb_result["message"]}
171+
172+
# No token at all — check URL validity anonymously
173+
url_check = check_github_token(repo_url, None)
174+
if url_check["status"] == "invalid_url":
175+
return {"token": None, "error_type": "invalid_url", "error_message": url_check["message"]}
176+
177+
# Public repo, proceed without a token
178+
return {"token": None, "error_type": None, "error_message": None}
179+
180+
else: # GitLab
181+
if token:
182+
result = check_gitlab_token(repo_url, token)
183+
if result["status"] == "valid":
184+
return {"token": token, "error_type": None, "error_message": None}
185+
186+
if result["status"] in ("invalid_token", "expired_token"):
187+
fallback = tokens_from_file.get("gitlab_token")
188+
if fallback and fallback != token:
189+
fb_result = check_gitlab_token(repo_url, fallback)
190+
if fb_result["status"] == "valid":
191+
return {"token": fallback, "error_type": None, "error_message": None}
192+
return {"token": None, "error_type": result["status"], "error_message": result["message"]}
193+
194+
return {"token": None, "error_type": result["status"], "error_message": result["message"]}
195+
196+
# No token provided — try fallback
197+
fallback = tokens_from_file.get("gitlab_token")
198+
if fallback:
199+
fb_result = check_gitlab_token(repo_url, fallback)
200+
if fb_result["status"] == "valid":
201+
return {"token": fallback, "error_type": None, "error_message": None}
202+
return {"token": None, "error_type": fb_result["status"], "error_message": fb_result["message"]}
203+
204+
return {
205+
"token": None,
206+
"error_type": "no_token",
207+
"error_message": "GitLab requires a valid personal access token. Please provide one and try again.",
208+
}

0 commit comments

Comments
 (0)