Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 99 additions & 3 deletions src/workato_platform_cli/cli/utils/exception_handler.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shihanpan The CLI reported an "Authentication Error" and eludes to the cause being an Invalid API Token, regardless of whether or not this is actually the case.

In cases where this is an "Authorization Error" due to API scopes, we should report that only.

The end state is that only a single error condition can occur and be reported (i.e. either your API Token is bad, or your API scopes are bad, not both).

Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,78 @@ def _get_output_mode() -> str:
return "table"


def _get_required_permissions(ctx: click.Context) -> list[str]:
"""Get required Workato permissions for a CLI command.

Args:
ctx: Click context object

Returns:
List of required permission strings
"""
# Map CLI command names to required Workato permissions
permission_map = {
"init": [
"Projects → Projects & folders",
"Projects → Connections",
"Projects → Recipes",
"Projects → Recipe Versions",
"Projects → Recipe lifecycle management",
"Projects → Export manifests",
"Tools → Collections & endpoints",
"Admin → Workspace details",
],
"recipes": [
"Projects → Export manifests",
"Projects → Recipes",
],
"pull": [
"Projects → Recipe lifecycle management",
"Projects → Export manifests",
],
"push": [
"Projects → Recipe lifecycle management",
],
"api-clients": [
"Tools → Clients & access profiles",
],
"api-collections": [
"Tools → Collections & endpoints",
],
"assets": [
"Projects → Export manifests",
],
"connections": [
"Projects → Connections",
],
"connectors": [
"Tools → Connector SDKs",
"Tools → Connectors",
],
"data-tables": [
"Tools → Data tables",
],
"properties": [
"Tools → Environment properties",
],
"workspace": [
"Admin → Workspace details",
],
}

# Get command name from context
# For nested commands like "workato recipes list", check parent context
command_name = ctx.info_name
if ctx.parent and ctx.parent.info_name and ctx.parent.info_name not in ("workato",):
# If parent is not root, use parent's name (the command group)
command_name = ctx.parent.info_name

if not command_name:
return []

return permission_map.get(command_name, [])


def _handle_client_error(
e: BadRequestException | UnprocessableEntityException,
) -> None:
Expand Down Expand Up @@ -235,6 +307,12 @@ def _handle_client_error(
def _handle_auth_error(e: UnauthorizedException) -> None:
"""Handle 401 Unauthorized errors."""
output_mode = _get_output_mode()
ctx = click.get_current_context(silent=True)

# Get required permissions for this command
required_permissions = []
if ctx:
required_permissions = _get_required_permissions(ctx)

if output_mode == "json":
error_data = {
Expand All @@ -245,12 +323,30 @@ def _handle_auth_error(e: UnauthorizedException) -> None:
click.echo(json.dumps(error_data))
return

click.echo("❌ Authentication failed")
click.echo(" Your API token may be invalid")
click.echo("💡 Please check your authentication:")
command_info = f" (command: {ctx.command_path})" if ctx else ""
click.echo(f"❌ Authentication failed{command_info}")
click.echo(" Your API token may be invalid or lack sufficient permissions")
click.echo()

# Show required permissions if available
if required_permissions:
click.echo("🔐 Required permissions for this command:")
for permission in required_permissions:
click.echo(f" • {permission}")
click.echo("Ensure your API client has the permissions listed above")
click.echo()

click.echo("💡 This could be due to:")
click.echo(" • Invalid or expired API token")
click.echo(" • API client lacking required permissions for this operation")
click.echo()
click.echo("🔧 To resolve:")
click.echo(" • Verify your API token is correct")
click.echo(" • Run 'workato profiles list' to check your profile")
click.echo(" • Run 'workato profiles use' to update your credentials")
click.echo()
click.echo("📚 Learn more about permissions required for API client")
click.echo(" https://docs.workato.com/en/platform-cli.html#authentication")


def _handle_forbidden_error(e: ForbiddenException) -> None:
Expand Down