Skip to content

Commit 1311dc7

Browse files
committed
feat: enhance init command with API key validation and improved credential handling
1 parent 8ba6111 commit 1311dc7

File tree

1 file changed

+101
-29
lines changed

1 file changed

+101
-29
lines changed

bugster/commands/init.py

Lines changed: 101 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from bugster.analytics import track_command
1414
from bugster.clients.http_client import BugsterHTTPClient
15-
from bugster.commands.auth import auth_command
15+
from bugster.commands.auth import auth_command, validate_api_key
1616
from bugster.constants import (
1717
CONFIG_PATH,
1818
TESTS_DIR,
@@ -87,28 +87,52 @@ def generate_project_id(project_name: str) -> str:
8787

8888

8989
@track_command("init")
90-
def init_command():
90+
def init_command(
91+
api_key: str = None,
92+
project_name: str = None,
93+
url: str = None,
94+
user: str = None,
95+
password: str = None,
96+
credential_name: str = None,
97+
no_auth: bool = False,
98+
no_credentials: bool = False,
99+
):
91100
"""Initialize Bugster CLI configuration."""
92101
InitMessages.welcome()
93102

94-
# First check if user is authenticated
95-
api_key = get_api_key()
96-
97-
if not api_key:
103+
# Handle API key authentication
104+
current_api_key = get_api_key()
105+
106+
# Use provided API key or get from storage
107+
if api_key:
108+
# Validate provided API key
109+
if not validate_api_key(api_key):
110+
console.print("[red]Invalid API key. Please check the format and try again.[/red]")
111+
raise typer.Exit(1)
112+
113+
# Save the provided API key
114+
from bugster.utils.user_config import save_api_key
115+
save_api_key(api_key)
116+
current_api_key = api_key
117+
console.print("[green]✓ API key saved successfully[/green]")
118+
elif not current_api_key and not no_auth:
98119
logger.info("API key not found, running auth command...")
99120
InitMessages.auth_required()
100121

101122
# Run auth command
102123
auth_command()
103124

104125
# Check if auth was successful
105-
api_key = get_api_key()
126+
current_api_key = get_api_key()
106127

107-
if not api_key:
128+
if not current_api_key:
108129
InitMessages.auth_failed()
109130
raise typer.Exit(1)
110131

111132
InitMessages.auth_success()
133+
elif not current_api_key and no_auth:
134+
console.print("[red]No API key configured and --no-auth flag provided. Please provide --api-key or run without --no-auth.[/red]")
135+
raise typer.Exit(1)
112136

113137
# Check for existing configuration
114138
config_exists, existing_config_path = find_existing_config()
@@ -128,15 +152,21 @@ def init_command():
128152

129153
# Project setup
130154
InitMessages.project_setup()
131-
project_name = Prompt.ask("🏷️ Project name", default=Path.cwd().name)
155+
156+
# Use provided project name or prompt for it
157+
if project_name is None:
158+
project_name = Prompt.ask("🏷️ Project name", default=Path.cwd().name)
159+
else:
160+
console.print(f"🏷️ Project name: {project_name}")
161+
132162
project_path = ""
133163
with contextlib.suppress(Exception):
134164
project_path = get_git_prefix_path()
135165

136166
# Create project via API
137167
try:
138168
with BugsterHTTPClient() as client:
139-
client.set_headers({"x-api-key": api_key})
169+
client.set_headers({"x-api-key": current_api_key})
140170
InitMessages.creating_project()
141171

142172
project_data = client.post(
@@ -155,30 +185,72 @@ def init_command():
155185
project_id = generate_project_id(project_name)
156186

157187
InitMessages.show_project_id(project_id)
158-
base_url = Prompt.ask("\n🌐 Application URL", default="http://localhost:3000")
188+
189+
# Use provided URL or prompt for it
190+
if url is None:
191+
base_url = Prompt.ask("\n🌐 Application URL", default="http://localhost:3000")
192+
else:
193+
base_url = url
194+
console.print(f"🌐 Application URL: {base_url}")
159195

160196
# Credentials setup
161-
InitMessages.auth_setup()
162197
credentials = []
163198

164-
if (
165-
Prompt.ask(
166-
"➕ Would you like to add custom login credentials? (y/n)", default="y"
167-
).lower()
168-
== "y"
169-
):
170-
identifier = Prompt.ask(
171-
"👤 Credential name",
172-
default="admin",
173-
)
174-
username = Prompt.ask("📧 Username/Email")
175-
password = Prompt.ask("🔒 Password", password=True)
176-
177-
credentials.append(create_credential_entry(identifier, username, password))
178-
InitMessages.credential_added()
199+
if no_credentials:
200+
# Skip credentials setup entirely
201+
if user is not None or password is not None or credential_name is not None:
202+
console.print("[red]Error: Cannot use --user, --password, or --credential-name with --no-credentials.[/red]")
203+
raise typer.Exit(1)
204+
else:
205+
console.print("🚫 Skipping credential setup (--no-credentials flag provided)")
179206
else:
180-
credentials.append(create_credential_entry())
181-
InitMessages.using_default_credentials()
207+
InitMessages.auth_setup()
208+
209+
# Determine if we should use custom credentials
210+
use_custom_credentials = False
211+
212+
if user is not None and password is not None:
213+
# Both user and password provided via flags
214+
use_custom_credentials = True
215+
console.print("✓ Using provided login credentials")
216+
elif user is not None or password is not None:
217+
# Only one of user/password provided - this is an error
218+
console.print("[red]Error: Both --user and --password must be provided together.[/red]")
219+
raise typer.Exit(1)
220+
else:
221+
# No credentials provided via flags, prompt interactively
222+
if (
223+
Prompt.ask(
224+
"➕ Would you like to add custom login credentials? (y/n)", default="y"
225+
).lower()
226+
== "y"
227+
):
228+
use_custom_credentials = True
229+
230+
if use_custom_credentials:
231+
# Use provided values or prompt for them
232+
if user is not None and password is not None:
233+
# Values provided via flags
234+
identifier = credential_name or "admin"
235+
username = user
236+
password_value = password
237+
console.print(f"👤 Credential name: {identifier}")
238+
console.print(f"📧 Username/Email: {username}")
239+
console.print("🔒 Password: [hidden]")
240+
else:
241+
# Interactive mode
242+
identifier = Prompt.ask(
243+
"👤 Credential name",
244+
default="admin",
245+
)
246+
username = Prompt.ask("📧 Username/Email")
247+
password_value = Prompt.ask("🔒 Password", password=True)
248+
249+
credentials.append(create_credential_entry(identifier, username, password_value))
250+
InitMessages.credential_added()
251+
else:
252+
credentials.append(create_credential_entry())
253+
InitMessages.using_default_credentials()
182254

183255
# Create project structure
184256
InitMessages.project_structure_setup()

0 commit comments

Comments
 (0)