@@ -200,6 +200,78 @@ def _get_output_mode() -> str:
200200 return "table"
201201
202202
203+ def _get_required_permissions (ctx : click .Context ) -> list [str ]:
204+ """Get required Workato permissions for a CLI command.
205+
206+ Args:
207+ ctx: Click context object
208+
209+ Returns:
210+ List of required permission strings
211+ """
212+ # Map CLI command names to required Workato permissions
213+ permission_map = {
214+ "init" : [
215+ "Projects → Projects & folders" ,
216+ "Projects → Connections" ,
217+ "Projects → Recipes" ,
218+ "Projects → Recipe Versions" ,
219+ "Projects → Recipe lifecycle management" ,
220+ "Projects → Export manifests" ,
221+ "Tools → Collections & endpoints" ,
222+ "Admin → Workspace details" ,
223+ ],
224+ "recipes" : [
225+ "Projects → Export manifests" ,
226+ "Projects → Recipes" ,
227+ ],
228+ "pull" : [
229+ "Projects → Recipe lifecycle management" ,
230+ "Projects → Export manifests" ,
231+ ],
232+ "push" : [
233+ "Projects → Recipe lifecycle management" ,
234+ ],
235+ "api-clients" : [
236+ "Tools → Clients & access profiles" ,
237+ ],
238+ "api-collections" : [
239+ "Tools → Collections & endpoints" ,
240+ ],
241+ "assets" : [
242+ "Projects → Export manifests" ,
243+ ],
244+ "connections" : [
245+ "Projects → Connections" ,
246+ ],
247+ "connectors" : [
248+ "Tools → Connector SDKs" ,
249+ "Tools → Connectors" ,
250+ ],
251+ "data-tables" : [
252+ "Tools → Data tables" ,
253+ ],
254+ "properties" : [
255+ "Tools → Environment properties" ,
256+ ],
257+ "workspace" : [
258+ "Admin → Workspace details" ,
259+ ],
260+ }
261+
262+ # Get command name from context
263+ # For nested commands like "workato recipes list", check parent context
264+ command_name = ctx .info_name
265+ if ctx .parent and ctx .parent .info_name and ctx .parent .info_name not in ("workato" ,):
266+ # If parent is not root, use parent's name (the command group)
267+ command_name = ctx .parent .info_name
268+
269+ if not command_name :
270+ return []
271+
272+ return permission_map .get (command_name , [])
273+
274+
203275def _handle_client_error (
204276 e : BadRequestException | UnprocessableEntityException ,
205277) -> None :
@@ -235,6 +307,12 @@ def _handle_client_error(
235307def _handle_auth_error (e : UnauthorizedException ) -> None :
236308 """Handle 401 Unauthorized errors."""
237309 output_mode = _get_output_mode ()
310+ ctx = click .get_current_context (silent = True )
311+
312+ # Get required permissions for this command
313+ required_permissions = []
314+ if ctx :
315+ required_permissions = _get_required_permissions (ctx )
238316
239317 if output_mode == "json" :
240318 error_data = {
@@ -245,9 +323,19 @@ def _handle_auth_error(e: UnauthorizedException) -> None:
245323 click .echo (json .dumps (error_data ))
246324 return
247325
248- click .echo ("❌ Authentication failed" )
326+ command_info = f" (command: { ctx .command_path } )" if ctx else ""
327+ click .echo (f"❌ Authentication failed{ command_info } " )
249328 click .echo (" Your API token may be invalid or lack sufficient permissions" )
250329 click .echo ()
330+
331+ # Show required permissions if available
332+ if required_permissions :
333+ click .echo ("🔐 Required permissions for this command:" )
334+ for permission in required_permissions :
335+ click .echo (f" • { permission } " )
336+ click .echo ("Ensure your API client has the permissions listed above" )
337+ click .echo ()
338+
251339 click .echo ("💡 This could be due to:" )
252340 click .echo (" • Invalid or expired API token" )
253341 click .echo (" • API client lacking required permissions for this operation" )
0 commit comments