You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(slack): keep buttons + link to renewal docs on action-required errors
For expired refresh token and 403 not-owner failures, show
":warning: Action required, see thread…" with Approve/Reject still
visible so the admin can retry, and post a thread message with a
clickable link to the README renewal section.
/** Error subclass used to signal "the admin must fix something before the retry will succeed". */
9
+
exportclassActionRequiredErrorextendsError{
10
+
constructor(message){
11
+
super(message);
12
+
this.name='ActionRequiredError';
13
+
this.actionRequired=true;
14
+
}
15
+
}
16
+
6
17
let_graphToken={value: null,expiresAt: 0};
7
18
8
19
asyncfunctiongetGraphToken(env){
@@ -45,8 +56,8 @@ async function graphApiWithToken(accessToken, path, method = 'GET', body = null)
45
56
constresText=awaitres.text();
46
57
if(!res.ok){
47
58
if(res.status===403&&path.includes('/members')){
48
-
thrownewError(
49
-
'403 Forbidden — the account from /auth/microsoft must be an owner of this team. If the invitee is a guest, your tenant may block adding guests via Graph; add them manually in Teams if needed.',
59
+
thrownewActionRequiredError(
60
+
`The account associated with the delegated refresh token is not an owner of this team. Sign in as a team owner and renew the token by following the steps in <${RENEW_TOKEN_URL}|the README>, then click Approve again. If the invitee is a guest, your tenant may also block adding guests via Graph — add them manually in Teams if needed.`,
if(!err.message?.includes('User not found'))throwerr;
181
192
constdelegatedToken=awaitgetDelegatedToken(env);
182
193
if(!delegatedToken){
183
-
thrownewError(
184
-
'DELEGATED_REFRESH_TOKEN is required. Visit GET /auth/microsoft, sign in as a team owner, then set the returned refresh token as DELEGATED_REFRESH_TOKEN.',
194
+
thrownewActionRequiredError(
195
+
`The delegated refresh token is missing or expired. Renew it by following the steps in <${RENEW_TOKEN_URL}|the README>, then click Approve again.`,
Copy file name to clipboardExpand all lines: src/slack.js
+70-60Lines changed: 70 additions & 60 deletions
Original file line number
Diff line number
Diff line change
@@ -73,6 +73,55 @@ function spinnerBlocks(request, env, opts) {
73
73
];
74
74
}
75
75
76
+
/** Approve/Reject actions block — reused so the buttons can be re-rendered after recoverable errors. */
77
+
functionapprovalActionsBlock(request){
78
+
return{
79
+
type: 'actions',
80
+
block_id: 'approval_actions',
81
+
elements: [
82
+
{
83
+
type: 'button',
84
+
text: {type: 'plain_text',text: 'Approve'},
85
+
style: 'primary',
86
+
action_id: 'approve_request',
87
+
value: String(request.id),
88
+
},
89
+
{
90
+
type: 'button',
91
+
text: {type: 'plain_text',text: 'Reject'},
92
+
style: 'danger',
93
+
action_id: 'reject_request',
94
+
value: String(request.id),
95
+
},
96
+
],
97
+
};
98
+
}
99
+
100
+
/** Blocks shown when the approval failed with a fixable cause (expired token, not owner, …). Keeps the buttons so the admin can retry after fixing the issue. */
101
+
functionactionRequiredBlocks(request,env,opts){
102
+
return[
103
+
...cardBodyBlocks(request,env,opts),
104
+
{type: 'section',text: {type: 'mrkdwn',text: ':warning: Action required, see thread…'}},
105
+
approvalActionsBlock(request),
106
+
];
107
+
}
108
+
109
+
/** Post the failure detail as a threaded reply. Action-required errors are rendered as mrkdwn so the README link in the message is clickable; other errors stay in a code block. */
consterrorCardText=':warning: An error occurred…';
398
+
constactionRequired=err.actionRequired===true;
399
+
consterrorCardText=actionRequired ? ':warning: Action required, see thread…' : ':warning: An error occurred…';
369
400
if(messageTs){
370
401
try{
371
402
constfallbackText=`${request.requester_email??request.requester_name} requested to invite ${request.member_email} to ${request.team_name}\n${errorCardText}`;
0 commit comments